Project: springxd
Issue XD-1644: Rest: Improve the determination whether a Job Execution is Restartable
In *BatchJobExecutionsController$restartJobExecution()* we need to do a better check whether a Batch Job Execution is restartable. This is also true when executing *BatchJobExecutionsController$list()*. The check performed under *new JobExecutionInfo(jobExecution, timeZone)* is not sufficient. *Reason*: Currently in the UI when I have failed Job Executions, I can restart those (good). However, if the next execution succeeds, the previously restartable jobs should NOT be marked as restartable anymore. Right now you can restart those jobs, resulting in a: {code} Caused by: org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException: A job instance already exists and is complete for parameters={random=0.5735953106895085, throwError=true}. If you want to run this job again, change the parameters. org.springframework.batch.core.repository.support.SimpleJobRepository.createJobExecution(SimpleJobRepository.java:126) sun.reflect.GeneratedMethodAccessor211.invoke(Unknown Source) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(Method.java:606) org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262) org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) org.springframework.batch.core.repository.support.AbstractJobRepositoryFactoryBean$1.invoke(AbstractJobRepositoryFactoryBean.java:172) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) com.sun.proxy.$Proxy40.createJobExecution(Unknown Source) org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:125) sun.reflect.GeneratedMethodAccessor209.invoke(Unknown Source) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(Method.java:606) org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:117) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) com.sun.proxy.$Proxy42.run(Unknown Source) org.springframework.batch.integration.launch.JobLaunchingMessageHandler.launch(JobLaunchingMessageHandler.java:50) sun.reflect.GeneratedMethodAccessor208.invoke(Unknown Source) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(Method.java:606) org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:63) org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:95) org.springframework.expression.spel.ast.MethodReference.access$000(MethodReference.java:44) org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:258) org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:84) org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:114) org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:111) org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:159) org.springframework.integration.util.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:268) org.springframework.integration.util.MessagingMethodInvokerHelper.process(MessagingMethodInvokerHelper.java:142) org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:75)	... 98 more {code}
Story points: 4