1

I have a Spring Batch job that started throwing this odd exception.

I wish I had more information than this stack trace, and I might, but I just don't know what to provide.

Searching around I've only found one other person with this particular error, but no replies as of August 2013. spring.io forum

Would anyone have any suggestions? Thanks /w

10:44:15,096 ERROR AbstractJob,pool-15-thread-1:326 - Encountered fatal error executing job
org.springframework.batch.core.JobExecutionException: Flow execution ended unexpectedly
        at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:141)
        at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:301)
        at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:134)
        at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:49)
        at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:127)
        at com.example.batch.RunScheduler.run(RunScheduler.java:62)
        at sun.reflect.GeneratedMethodAccessor139.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:64)
        at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:53)
        at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:744)
Caused by: org.springframework.batch.core.job.flow.FlowExecutionException: Ended flow=sourceJob at state=sourceJob.sourceStep1 with exception
        at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:161)
        at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:131)
        at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
        ... 18 more
Caused by: java.lang.IllegalStateException: Shouldn't be illegal to access field 'serialVersionUID': java.lang.IllegalAccessException: Can not set static final long field org.springframework.batch.core.StepExecution.serialVersionUID to java.lang.Long
        at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:573)
        at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:547)
        at org.springframework.batch.core.repository.dao.MapStepExecutionDao.copy(MapStepExecutionDao.java:59)
        at org.springframework.batch.core.repository.dao.MapStepExecutionDao.updateStepExecution(MapStepExecutionDao.java:109)
        at org.springframework.batch.core.repository.support.SimpleJobRepository.update(SimpleJobRepository.java:189)
        at sun.reflect.GeneratedMethodAccessor144.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
        at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
        at com.sun.proxy.$Proxy61.update(Unknown Source)
        at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:183)
        at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:137)
        at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64)
        at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
        at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:152)
        ... 20 more
wsams
  • 2,499
  • 7
  • 40
  • 51
  • If you can open a Jira issue with this and a test case, it would be helpful to address. – Michael Minella Dec 12 '13 at 02:22
  • @MichaelMinella, I'll see if I can devise a test case. It's somewhat difficult because not all of our devs are seeing the issue - same for test machines. Additionally I've never seen it in a unit/it test. Would a Jira issue sans a test be okay until I can devise one? – wsams Dec 12 '13 at 14:33
  • The Jira issue would be a start. – Michael Minella Dec 12 '13 at 22:15

3 Answers3

1

This appears to be a bug in Spring 3.2.0, and possibly other versions. See the source code to org.springframework.util.ReflectionUtils.doWithFields(Class,FieldCallback,FieldFilter) at line 565. The comment on this line suggests that the code should skip static and/or final fields, but there is no code to actually implement this test. Certainly, the exception being thrown is an expected result of attempting to modify a static final field (non-static final fields can be modified via reflection, but static final is treated as a compile-time constant so modification is disallowed).

Jules
  • 14,841
  • 9
  • 83
  • 130
  • 1
    The problem affects only in-memory `StepExecutionDao` impl (`MapStepExecutionDao`) and not the jdbc counterpart; the problem is the missing use of `FieldFilter`; you can workaround create a custom `MapStepExecutionDao` and use `ReflectionUtils.shallowCopyFieldState` as `private static void MapStepExecutionDao.copy(StepExecution sourceExecution, StepExecution targetExecution)` implementation – Luca Basso Ricci Dec 12 '13 at 10:00
  • Looking `StepExecution` I didn't see any `serialVersionUID` field; is a synthetic one? but synthetics should not be returned by `Class.getDeclaredFields()`; or I am missing something? – Luca Basso Ricci Dec 12 '13 at 10:20
  • I believe it's because `StepExecution` implements `Serializable` and one is auto-generated if not defined @bellabax. – wsams Dec 12 '13 at 14:09
  • Yep. but does `Class.getDeclaredFields()` method return syntethic fields? – Luca Basso Ricci Dec 12 '13 at 14:17
  • 1
    @bellabax, I switched from `org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean` to `JobRepositoryFactoryBean` and configured the job repository bean as such and so far so good. ` ` – wsams Dec 13 '13 at 02:41
  • Here is the Jira issue [#BATCH-2157](https://jira.spring.io/browse/BATCH-2157). According to a comment on [16 Jan 2015](https://jira.spring.io/browse/BATCH-2157?focusedCommentId=111664&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-111664) it was fixed in spring batch version 3.0.2. – Niel de Wet Jul 22 '15 at 10:06
0

The issue referred to by Jules was fixed. Just upgrade to spring batch version 3.0.2.RELEASE or later.

Niel de Wet
  • 7,806
  • 9
  • 63
  • 100
0

If upgrade to Spring Batch Core 3.0.2 is hard (for any reason) and if you are using jacoco integration through Maven, a solution could be exclude Spring classes in jacoco integration :

<pluginManagement>
    <plugins>
        <!-- Avoid BATCH-2157 until Spring Batch Core 3.0.2 -->
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>...</version>
            <configuration>
                <excludes>
                    <exclude>**/springframework/**</exclude>
                </excludes>
            </configuration>
        </plugin>
        [...]
    </plugins>
    [...]
</pluginManagement>

The Maven tests are passing with that ; but the impact on code coverage is not qualified (it would be minimal).

Alix Lourme
  • 1,135
  • 1
  • 11
  • 21