ConcurrentModificationException at JobOperator#getJobExecution()
xkylex Apr 4, 2014 5:03 PMMy batch polls JobExecution periodically with JobOperator#getJobExecution() to check whether the batch execution is completed. it uses remote EJB invocation, and it works well most but today I got unexpected ConcurrentModificationException.
Am I doing anything bad? or is there some un-threadsafe implementation in JBeret?
Stackstace:
2014-04-04 22:02:34,130 WARN [org.jberet] (batch-batch - 15) JBERET000001: Failed to run batchlet org.jberet.job.model.RefArtifact@69b35c3f: java.lang.RuntimeException: JBAS014154: Failed to marshal EJB parameters at org.jboss.as.ejb3.remote.LocalEjbReceiver.clone(LocalEjbReceiver.java:291) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final] at org.jboss.as.ejb3.remote.LocalEjbReceiver.clone(LocalEjbReceiver.java:280) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final] at org.jboss.as.ejb3.remote.LocalEjbReceiver.processInvocation(LocalEjbReceiver.java:252) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final] at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:181) [jboss-ejb-client-2.0.0.Final.jar:2.0.0.Final] at org.jboss.ejb.client.EJBObjectInterceptor.handleInvocation(EJBObjectInterceptor.java:58) [jboss-ejb-client-2.0.0.Final.jar:2.0.0.Final] at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:183) [jboss-ejb-client-2.0.0.Final.jar:2.0.0.Final] at org.jboss.ejb.client.EJBHomeInterceptor.handleInvocation(EJBHomeInterceptor.java:83) [jboss-ejb-client-2.0.0.Final.jar:2.0.0.Final] at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:183) [jboss-ejb-client-2.0.0.Final.jar:2.0.0.Final] at org.jboss.ejb.client.TransactionInterceptor.handleInvocation(TransactionInterceptor.java:42) [jboss-ejb-client-2.0.0.Final.jar:2.0.0.Final] at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:183) [jboss-ejb-client-2.0.0.Final.jar:2.0.0.Final] at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:125) [jboss-ejb-client-2.0.0.Final.jar:2.0.0.Final] at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:183) [jboss-ejb-client-2.0.0.Final.jar:2.0.0.Final] at org.jboss.ejb.client.EJBInvocationHandler.sendRequestWithPossibleRetries(EJBInvocationHandler.java:253) [jboss-ejb-client-2.0.0.Final.jar:2.0.0.Final] at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:198) [jboss-ejb-client-2.0.0.Final.jar:2.0.0.Final] at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:181) [jboss-ejb-client-2.0.0.Final.jar:2.0.0.Final] at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:144) [jboss-ejb-client-2.0.0.Final.jar:2.0.0.Final] at com.sun.proxy.$Proxy87.getJobExecution(Unknown Source) at org.nailedtothex.stock.common.util.JobUtil.waitForFinish(JobUtil.java:21) [stock-common-1.0-SNAPSHOT.jar:] at org.nailedtothex.stock.batch.common.batchlet.JobLaunchBatchlet.waitForFinish(JobLaunchBatchlet.java:87) [stock-batch-1.0-SNAPSHOT.jar:] at org.nailedtothex.stock.batch.common.batchlet.JobLaunchBatchlet.process(JobLaunchBatchlet.java:60) [stock-batch-1.0-SNAPSHOT.jar:] at org.jberet.runtime.runner.BatchletRunner.run(BatchletRunner.java:61) [jberet-core-1.0.1.CR2-SNAPSHOT.jar:1.0.1.CR2-SNAPSHOT] at org.jberet.runtime.runner.StepExecutionRunner.runBatchletOrChunk(StepExecutionRunner.java:207) [jberet-core-1.0.1.CR2-SNAPSHOT.jar:1.0.1.CR2-SNAPSHOT] at org.jberet.runtime.runner.StepExecutionRunner.run(StepExecutionRunner.java:131) [jberet-core-1.0.1.CR2-SNAPSHOT.jar:1.0.1.CR2-SNAPSHOT] at org.jberet.runtime.runner.CompositeExecutionRunner.runStep(CompositeExecutionRunner.java:162) [jberet-core-1.0.1.CR2-SNAPSHOT.jar:1.0.1.CR2-SNAPSHOT] at org.jberet.runtime.runner.CompositeExecutionRunner.runFromHeadOrRestartPoint(CompositeExecutionRunner.java:88) [jberet-core-1.0.1.CR2-SNAPSHOT.jar:1.0.1.CR2-SNAPSHOT] at org.jberet.runtime.runner.JobExecutionRunner.run(JobExecutionRunner.java:58) [jberet-core-1.0.1.CR2-SNAPSHOT.jar:1.0.1.CR2-SNAPSHOT] at org.wildfly.jberet.services.BatchEnvironmentService$WildFlyBatchEnvironment$1.run(BatchEnvironmentService.java:149) [wildfly-jberet-8.0.0.Final.jar:8.0.0.Final] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [rt.jar:1.7.0_51] at java.util.concurrent.FutureTask.run(FutureTask.java:262) [rt.jar:1.7.0_51] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_51] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_51] at java.lang.Thread.run(Thread.java:744) [rt.jar:1.7.0_51] at org.jboss.threads.JBossThread.run(JBossThread.java:122) Caused by: java.util.ConcurrentModificationException at java.util.ArrayList.writeObject(ArrayList.java:746) [rt.jar:1.7.0_51] at sun.reflect.GeneratedMethodAccessor29.invoke(Unknown Source) [:1.7.0_51] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_51] at java.lang.reflect.Method.invoke(Method.java:606) [rt.jar:1.7.0_51] at org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:275) at org.jboss.marshalling.cloner.SerializingCloner.initSerializableClone(SerializingCloner.java:294) at org.jboss.marshalling.cloner.SerializingCloner.clone(SerializingCloner.java:249) at org.jboss.marshalling.cloner.SerializingCloner.clone(SerializingCloner.java:129) at org.jboss.marshalling.cloner.SerializingCloner.cloneFields(SerializingCloner.java:345) at org.jboss.marshalling.cloner.SerializingCloner.initSerializableClone(SerializingCloner.java:305) at org.jboss.marshalling.cloner.SerializingCloner.clone(SerializingCloner.java:249) at org.jboss.marshalling.cloner.SerializingCloner.clone(SerializingCloner.java:129) at org.jboss.as.ejb3.remote.LocalEjbReceiver.clone(LocalEjbReceiver.java:289) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final] ... 32 more
My polling implementation:
public class JobUtil { private static final long POLLING_WAIT = 300l; private static final Set<BatchStatus> INCOMPLETE_STATUSES = EnumSet.of(BatchStatus.STARTED, BatchStatus.STARTING); public static JobExecution waitForFinish(long executionId, JobOperator jobOperator) { JobExecution jobExecution = null; do { try { Thread.sleep(POLLING_WAIT); } catch (InterruptedException e) { throw new RuntimeException(e); } jobExecution = jobOperator.getJobExecution(executionId); } while (INCOMPLETE_STATUSES.contains(jobExecution.getBatchStatus())); return jobExecution; } }
Thanks.