【发布时间】:2014-11-28 11:49:20
【问题描述】:
我是 Spring 批处理和 Spring 的新手。我正在开发一个将在 WebSphere Application Server 上运行的批处理作业。到目前为止,我刚刚构建了一个带有一些虚拟步骤的骨架。我还有一个监听器,用于在作业结束时更新一些 Oracle 数据库表。这是我的 appContext 的一部分:
<batch:job id="spedizioneJob" restartable="true" parent="bankitJob">
<batch:step id="verifyInputStep" next="technicalPropertiesEnforcementStep">
<batch:tasklet ref="verifyInput" />
</batch:step>
<batch:step id="technicalPropertiesEnforcementStep" next="protocolAndProbatoryStep">
<batch:tasklet ref="technicalPropertiesEnforcement" />
</batch:step>
<batch:step id="protocolAndProbatoryStep" next="exdiSendingStep">
<batch:tasklet ref="protocolAndProbatory" />
</batch:step>
<batch:step id="exdiSendingStep">
<batch:tasklet ref="exdiSending" />
</batch:step>
<batch:listeners merge="true">
<batch:listener ref="spedizioneJobListener" />
</batch:listeners>
</batch:job>
这是Job sn-p之后的开始:
public void afterJob(JobExecution jobExecution) {
// get params
String iref = jobExecution.getJobParameters().getString("APPL_REQ_ID");
SpedizioneInput spInput=(SpedizioneInput)jobExecution.getExecutionContext().get("input");
奇怪的是,在我的一些测试运行中(Rational Application Developer 上的本地测试环境,但同样发生在 WAS 的服务器实例上),通常不是第一次,找不到 jobExecution,我得到了这个异常:
[03/10/14 12.47.48:505 CEST] 0000003a AbstractJob E org.springframework.batch.core.job.AbstractJob execute Encountered fatal error executing job
org.springframework.batch.core.repository.dao.NoSuchObjectException: Invalid JobExecution, ID 224 not found.
at org.springframework.batch.core.repository.dao.JdbcJobExecutionDao.updateJobExecution(JdbcJobExecutionDao.java:218)
at org.springframework.batch.core.repository.support.SimpleJobRepository.update(SimpleJobRepository.java:160)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:600)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at $Proxy36.update(Unknown Source)
at org.springframework.batch.core.job.AbstractJob.updateStatus(AbstractJob.java:416)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:299)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135)
at java.lang.Thread.run(Thread.java:736)
我不知道这是否与我运行作业的方式有关......我配置了这样一种启动器:
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
<property name="taskExecutor">
<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor" />
</property>
</bean>
我从一个会话 EJB 启动我的工作,它被一个 Servlet 调用。这是启动时的 EJB 代码:
try {
System.out.println("Before launching spedizione job");
JobExecution jexec=jobLauncher.run(job, jpb.toJobParameters());
System.out.println("After launching spedizione job "+jexec.getJobConfigurationName()+" status "+jexec.getStatus().toString());
我的日志确认这是按预期向作业发出异步调用,但我怀疑会话 bean 事务有时可能不会在作业进入侦听器的 afterJob 方法之前提交...
提前感谢您的回复
【问题讨论】:
-
您能否深入了解一下您配置事务的方式?
-
嗨。关于调用 jobLauncher.run 的会话 Bean,我没有特别配置任何东西,因此事务是容器管理的,并且应该是默认的,我可以检查 websphere 文档。对于 spring 批处理作业配置,我只是指定 org.springframework.batch.support.transaction.ResourcelessTransactionManager 作为作业存储库的事务管理器。用于处理 jobRepository 的数据源是在 WebSphere Application Server 中使用 Oracle XA JDBC 提供程序配置的
-
你为什么使用
ResourcelessTransactionManager?上面的错误可能是由于在事务范围内(在 EJB 中)启动批处理作业和在 Spring Batch 中不使用事务(通过使用ResourcelessTransactionManager的方式)的组合。作业正在尝试更新记录在存储库中,但会话 bean 尚未提交它的事务,所以它不存在。
标签: spring-batch application-server