【问题标题】:Spring Batch on application server: JobExecution not found on afterJob listener应用程序服务器上的 Spring Batch:在 afterJob 侦听器上找不到 JobExecution
【发布时间】: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


【解决方案1】:

正如 Michael 所建议的,问题出在我使用的事务管理器上。当我切换到 WebSphereUowTransactionManager 时,我解决了我的问题。 http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/transaction/jta/WebSphereUowTransactionManager.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-25
    • 1970-01-01
    • 2015-02-21
    • 2019-01-03
    • 2016-02-03
    相关资源
    最近更新 更多