BATCHEE-132 ensure ServicesManager represents the 'container' of batchee and defines its lifecycle
diff --git a/jbatch/src/main/java/org/apache/batchee/container/impl/JobOperatorImpl.java b/jbatch/src/main/java/org/apache/batchee/container/impl/JobOperatorImpl.java
index af0f54d..9212839 100755
--- a/jbatch/src/main/java/org/apache/batchee/container/impl/JobOperatorImpl.java
+++ b/jbatch/src/main/java/org/apache/batchee/container/impl/JobOperatorImpl.java
@@ -16,18 +16,16 @@
*/
package org.apache.batchee.container.impl;
-import org.apache.batchee.container.Init;
-import org.apache.batchee.container.services.BatchKernelService;
-import org.apache.batchee.container.services.InternalJobExecution;
-import org.apache.batchee.container.services.JobStatusManagerService;
-import org.apache.batchee.container.services.ServicesManager;
-import org.apache.batchee.container.status.JobStatus;
-import org.apache.batchee.jmx.BatchEE;
-import org.apache.batchee.jmx.BatchEEMBean;
-import org.apache.batchee.jmx.BatchEEMBeanImpl;
-import org.apache.batchee.spi.JobExecutionCallbackService;
-import org.apache.batchee.spi.JobXMLLoaderService;
-import org.apache.batchee.spi.PersistenceManagerService;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import javax.batch.operations.JobExecutionAlreadyCompleteException;
import javax.batch.operations.JobExecutionIsRunningException;
@@ -44,52 +42,23 @@
import javax.batch.runtime.JobExecution;
import javax.batch.runtime.JobInstance;
import javax.batch.runtime.StepExecution;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.lang.management.ManagementFactory;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Properties;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import static org.apache.batchee.container.util.ClassLoaderAwareHandler.makeLoaderAware;
+import org.apache.batchee.container.Init;
+import org.apache.batchee.container.services.BatchKernelService;
+import org.apache.batchee.container.services.InternalJobExecution;
+import org.apache.batchee.container.services.JobStatusManagerService;
+import org.apache.batchee.container.services.ServicesManager;
+import org.apache.batchee.container.status.JobStatus;
+import org.apache.batchee.spi.JobExecutionCallbackService;
+import org.apache.batchee.spi.JobXMLLoaderService;
+import org.apache.batchee.spi.PersistenceManagerService;
-public class JobOperatorImpl implements JobOperator, AutoCloseable {
+public class JobOperatorImpl implements JobOperator {
private static final Logger LOGGER = Logger.getLogger(JobOperatorImpl.class.getName());
static {
Init.doInit();
-
- if (Boolean.parseBoolean(ServicesManager.value("org.apache.batchee.jmx", "true"))) {
- try {
- final MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
- final String app = ServicesManager.value("org.apache.batchee.jmx.application", "");
- final ObjectName name;
- if (app.isEmpty()) {
- name = new ObjectName(BatchEEMBean.DEFAULT_OBJECT_NAME);
- } else {
- name = new ObjectName(BatchEEMBean.DEFAULT_OBJECT_NAME + ",application=" + app);
- }
-
- if (platformMBeanServer.isRegistered(name)) {
- platformMBeanServer.unregisterMBean(name);
- }
-
- platformMBeanServer.registerMBean(
- new BatchEE(
- makeLoaderAware(BatchEEMBean.class, new Class<?>[]{ BatchEEMBean.class }, BatchEEMBeanImpl.INSTANCE)),
- name);
- } catch (final Exception e) {
- throw new IllegalStateException(e);
- }
- }
}
private final BatchKernelService kernelService;
@@ -115,10 +84,6 @@
this(ServicesManager.find());
}
- public void close() throws Exception {
-
- }
-
@Override
public long start(final String jobXMLName, final Properties jobParameters) throws JobStartException, JobSecurityException {
/*
diff --git a/jbatch/src/main/java/org/apache/batchee/container/services/ServicesManager.java b/jbatch/src/main/java/org/apache/batchee/container/services/ServicesManager.java
index 4aefa33..bd83689 100755
--- a/jbatch/src/main/java/org/apache/batchee/container/services/ServicesManager.java
+++ b/jbatch/src/main/java/org/apache/batchee/container/services/ServicesManager.java
@@ -17,6 +17,23 @@
*/
package org.apache.batchee.container.services;
+import static org.apache.batchee.container.util.ClassLoaderAwareHandler.makeLoaderAware;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
import org.apache.batchee.container.exception.BatchContainerRuntimeException;
import org.apache.batchee.container.exception.BatchContainerServiceException;
import org.apache.batchee.container.services.callback.SimpleJobExecutionCallbackService;
@@ -31,6 +48,9 @@
import org.apache.batchee.container.services.status.DefaultJobStatusManager;
import org.apache.batchee.container.services.transaction.DefaultBatchTransactionService;
import org.apache.batchee.container.util.BatchContainerConstants;
+import org.apache.batchee.jmx.BatchEE;
+import org.apache.batchee.jmx.BatchEEMBean;
+import org.apache.batchee.jmx.BatchEEMBeanImpl;
import org.apache.batchee.spi.BatchArtifactFactory;
import org.apache.batchee.spi.BatchService;
import org.apache.batchee.spi.BatchThreadPoolService;
@@ -40,15 +60,6 @@
import org.apache.batchee.spi.PersistenceManagerService;
import org.apache.batchee.spi.TransactionManagementService;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.logging.Logger;
-
public class ServicesManager implements BatchContainerConstants {
private final static Logger LOGGER = Logger.getLogger(ServicesManager.class.getName());
@@ -77,6 +88,7 @@
private static ServicesManagerLocator servicesManagerLocator;
+ private ObjectName jmxName;
private ClassLoader loader = null;
// designed to be used from app or a server
@@ -147,12 +159,69 @@
logServices = Boolean.parseBoolean(batchRuntimeConfig.getProperty("batchee.service-manager.log", "false"));
+ if (Boolean.parseBoolean(batchRuntimeConfig.getProperty("org.apache.batchee.jmx", "true"))) {
+ try {
+ final MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
+ final String app = batchRuntimeConfig.getProperty("org.apache.batchee.jmx.application", "");
+ if (app.isEmpty()) {
+ jmxName = new ObjectName(BatchEEMBean.DEFAULT_OBJECT_NAME);
+ } else {
+ jmxName = new ObjectName(BatchEEMBean.DEFAULT_OBJECT_NAME + ",application=" + app);
+ }
+
+ if (!platformMBeanServer.isRegistered(jmxName)) {
+ platformMBeanServer.registerMBean(
+ new BatchEE(
+ makeLoaderAware(BatchEEMBean.class, new Class<?>[]{ BatchEEMBean.class },
+ BatchEEMBeanImpl.INSTANCE)),
+ jmxName);
+ } else {
+ jmxName = null;
+ LOGGER.warning("You didn't specify org.apache.batchee.jmx.application and JMX is already registered, skipping");
+ }
+ } catch (final Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
isInited = Boolean.TRUE;
}
}
}
}
+ public void close() {
+ if (isInited) {
+ synchronized (isInitedLock) {
+ if (isInited) {
+ service(BatchThreadPoolService.class).shutdown();
+ synchronized (serviceRegistry) {
+ for (final Object service : serviceRegistry.values()) {
+ if (Closeable.class.isInstance(service)) {
+ try {
+ Closeable.class.cast(service).close();
+ } catch (IOException e) { // don't make it blocking, on j7 we can use suppressed maybe?
+ LOGGER.log(Level.SEVERE, e.getMessage(), e);
+ }
+ }
+ }
+ }
+
+
+ if (jmxName != null) { // unregister jmx bean if deployed in an app
+ final MBeanServer jmx = ManagementFactory.getPlatformMBeanServer();
+ try {
+ jmx.unregisterMBean(jmxName);
+ } catch (final Exception e) {
+ // no-op
+ }
+ }
+ isInited = false;
+ }
+ }
+ }
+ }
+
public <T extends BatchService> T service(final Class<T> clazz) throws BatchContainerServiceException {
T service = clazz.cast(serviceRegistry.get(clazz.getName()));
if (service == null) {
diff --git a/jbatch/src/main/java/org/apache/batchee/container/services/data/DefaultDataRepresentationService.java b/jbatch/src/main/java/org/apache/batchee/container/services/data/DefaultDataRepresentationService.java
index 7453059..15eb5ca 100644
--- a/jbatch/src/main/java/org/apache/batchee/container/services/data/DefaultDataRepresentationService.java
+++ b/jbatch/src/main/java/org/apache/batchee/container/services/data/DefaultDataRepresentationService.java
@@ -22,7 +22,6 @@
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@@ -46,7 +45,7 @@
public static final String BATCHEE_DATA_PREFIX = "BatchEE_data" + BATCHEE_SPLIT_TOKEN;
- private static final Charset UTF8_CHARSET = StandardCharsets.UTF_8;
+ private static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
private static final Logger LOGGER = Logger.getLogger(DefaultDataRepresentationService.class.getName());
@@ -298,7 +297,7 @@
Class<?> typeClass = getClassLoader().loadClass(typeVal);
Method method = typeClass.getMethod(methodName, paramType);
return method.invoke(null, valueVal);
- } catch (ReflectiveOperationException e) {
+ } catch (Exception e) {
throw new BatchContainerServiceException("Cannot convert data [" + valueVal + "] of type [" + typeVal + "]", e );
}
}
diff --git a/jbatch/src/main/java/org/apache/batchee/jmx/BatchEEMBeanImpl.java b/jbatch/src/main/java/org/apache/batchee/jmx/BatchEEMBeanImpl.java
index b396ee5..108ce42 100644
--- a/jbatch/src/main/java/org/apache/batchee/jmx/BatchEEMBeanImpl.java
+++ b/jbatch/src/main/java/org/apache/batchee/jmx/BatchEEMBeanImpl.java
@@ -41,8 +41,6 @@
public class BatchEEMBeanImpl implements BatchEEMBean {
public static final BatchEEMBeanImpl INSTANCE = new BatchEEMBeanImpl();
- private final JobOperator operator = BatchRuntime.getJobOperator();
-
private static final String[] JOB_INSTANCES_ATTRIBUTES = { "jobName", "instanceId" };
private static final TabularType JOB_INSTANCES_TABULAR_TYPE;
private static final CompositeType JOB_INSTANCES_COMPOSITE_TYPE;
@@ -154,20 +152,24 @@
// no-op
}
+ private JobOperator operator() { // lazy since we register jmx with the servicesmanager init
+ return BatchRuntime.getJobOperator();
+ }
+
@Override
public String[] getJobNames() {
- final Set<String> jobNames = operator.getJobNames();
+ final Set<String> jobNames = operator().getJobNames();
return jobNames.toArray(new String[jobNames.size()]);
}
@Override
public int getJobInstanceCount(final String jobName) {
- return operator.getJobInstanceCount(jobName);
+ return operator().getJobInstanceCount(jobName);
}
@Override
public TabularData getJobInstances(final String jobName, final int start, final int count) {
- final List<JobInstance> instances = operator.getJobInstances(jobName, start, count);
+ final List<JobInstance> instances = operator().getJobInstances(jobName, start, count);
try {
final TabularDataSupport data = new TabularDataSupport(JOB_INSTANCES_TABULAR_TYPE);
@@ -183,7 +185,7 @@
@Override
public Long[] getRunningExecutions(final String jobName) {
try {
- final List<Long> runningExecutions = operator.getRunningExecutions(jobName);
+ final List<Long> runningExecutions = operator().getRunningExecutions(jobName);
return runningExecutions.toArray(new Long[runningExecutions.size()]);
} catch (final NoSuchJobException nsje) {
return new Long[0];
@@ -192,7 +194,7 @@
@Override
public TabularData getParameters(final long executionId) {
- final Properties parameters = operator.getParameters(executionId);
+ final Properties parameters = operator().getParameters(executionId);
try {
final TabularDataSupport data = new TabularDataSupport(PROPERTIES_TABULAR_TYPE);
for (final Map.Entry<Object, Object> entry : parameters.entrySet()) {
@@ -206,7 +208,7 @@
@Override
public TabularData getJobInstance(final long executionId) {
- final JobInstance instance = operator.getJobInstance(executionId);
+ final JobInstance instance = operator().getJobInstance(executionId);
try {
final TabularDataSupport data = new TabularDataSupport(JOB_INSTANCES_TABULAR_TYPE);
data.put(new CompositeDataSupport(JOB_INSTANCES_COMPOSITE_TYPE, JOB_INSTANCES_ATTRIBUTES, new Object[] { instance.getJobName(), instance.getInstanceId() }));
@@ -218,27 +220,27 @@
@Override
public void stop(final long executionId) {
- operator.stop(executionId);
+ operator().stop(executionId);
}
@Override
public void abandon(final long executionId) {
- operator.abandon(executionId);
+ operator().abandon(executionId);
}
@Override
public long start(final String jobXMLName, final String jobParameters) {
- return operator.start(jobXMLName, toProperties(jobParameters));
+ return operator().start(jobXMLName, toProperties(jobParameters));
}
@Override
public long restart(final long executionId, final String restartParameters) {
- return operator.restart(executionId, toProperties(restartParameters));
+ return operator().restart(executionId, toProperties(restartParameters));
}
@Override
public TabularData getJobExecutions(final long id, final String name) {
- final List<JobExecution> executions = operator.getJobExecutions(new JobInstanceImpl(id, name));
+ final List<JobExecution> executions = operator().getJobExecutions(new JobInstanceImpl(id, name));
try {
final TabularDataSupport data = new TabularDataSupport(JOB_EXECUTION_TABULAR_TYPE);
for (final JobExecution n : executions) {
@@ -252,7 +254,7 @@
@Override
public TabularData getJobExecution(final long executionId) {
- final JobExecution execution = operator.getJobExecution(executionId);
+ final JobExecution execution = operator().getJobExecution(executionId);
try {
final TabularDataSupport data = new TabularDataSupport(JOB_EXECUTION_TABULAR_TYPE);
data.put(new CompositeDataSupport(JOB_EXECUTION_COMPOSITE_TYPE, JOB_EXECUTION_ATTRIBUTES, asArray(execution)));
@@ -264,7 +266,7 @@
@Override
public TabularData getStepExecutions(final long jobExecutionId) {
- final List<StepExecution> executions = operator.getStepExecutions(jobExecutionId);
+ final List<StepExecution> executions = operator().getStepExecutions(jobExecutionId);
try {
final TabularDataSupport data = new TabularDataSupport(STEP_EXECUTION_TABULAR_TYPE);
for (final StepExecution n : executions) {
diff --git a/jbatch/src/main/java/org/apache/batchee/servlet/CleanUpWebappListener.java b/jbatch/src/main/java/org/apache/batchee/servlet/CleanUpWebappListener.java
index 9beef4c..51a3b92 100644
--- a/jbatch/src/main/java/org/apache/batchee/servlet/CleanUpWebappListener.java
+++ b/jbatch/src/main/java/org/apache/batchee/servlet/CleanUpWebappListener.java
@@ -16,16 +16,11 @@
*/
package org.apache.batchee.servlet;
-import org.apache.batchee.container.services.ServicesManager;
-import org.apache.batchee.jmx.BatchEEMBean;
-import org.apache.batchee.spi.BatchThreadPoolService;
-
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
-import java.lang.management.ManagementFactory;
+
+import org.apache.batchee.container.services.ServicesManager;
@WebListener
public class CleanUpWebappListener implements ServletContextListener {
@@ -36,20 +31,9 @@
@Override
public void contextDestroyed(final ServletContextEvent sce) {
- final BatchThreadPoolService threadPoolService = ServicesManager.find().service(BatchThreadPoolService.class);
- if (CleanUpWebappListener.class.getClassLoader() == sce.getServletContext().getClassLoader()) {
- threadPoolService.shutdown();
-
- // unregister jmx bean if deployed in an app
- final MBeanServer jmx = ManagementFactory.getPlatformMBeanServer();
- try {
- final ObjectName objectName = new ObjectName(BatchEEMBean.DEFAULT_OBJECT_NAME);
- if (jmx.isRegistered(objectName)) {
- jmx.unregisterMBean(objectName);
- }
- } catch (final Exception e) {
- // no-op
- }
+ final ServicesManager servicesManager = ServicesManager.find();
+ if (ServicesManager.class.getClassLoader() == sce.getServletContext().getClassLoader()) {
+ servicesManager.close();
}
}
}
diff --git a/jbatch/src/test/java/org/apache/batchee/test/data/DefaultDataRepresentationServiceTest.java b/jbatch/src/test/java/org/apache/batchee/test/data/DefaultDataRepresentationServiceTest.java
index e5fba15..617f9db 100644
--- a/jbatch/src/test/java/org/apache/batchee/test/data/DefaultDataRepresentationServiceTest.java
+++ b/jbatch/src/test/java/org/apache/batchee/test/data/DefaultDataRepresentationServiceTest.java
@@ -129,7 +129,7 @@
Class<?> clazz = Class.forName(className);
Method now = clazz.getMethod("now");
return now.invoke(null);
- } catch (ReflectiveOperationException e) {
+ } catch (Exception e) {
// all fine, we are just not running on java8
}
return null;