JSR 352 Spring Batch:事务管理

时间:2014-10-07 11:14:29

标签: java spring-batch websphere-8

我尝试在Websphere中使用JSR 352模式下的Spring Batch。 (Websphere 8.0,Spring Batch 3.0.1)

据我了解文档,spring应该处理事务,即在调用步骤的ItemReader之前开始事务,在调用ItemWriter之后提交事务等等。

但是,在我的情况下,调用ItemReader时没有事务处于活动状态(userTransaction.getStatus()== 6)。如果我自己在itemReader中启动交易,我的代码就有效,但我的理解是我不应该这样做。

我怀疑问题与我设置批次的方式有关。

这是一个显示问题的示例代码:

META_INF / batch.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">


<tx:jta-transaction-manager />

</beans>

META-INF /分批作业/ samplebatch3.xml:

<?xml version="1.0" encoding="UTF-8"?>


<job version="1.0"
     id="samplebatch3" 
     xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/jobXML_1_0.xsd">
 <step id="step1">
     <chunk  checkpoint-policy="item"
            item-count="5">
            <reader ref="my.jbatchtest.samplebatch3.SampleReader" />
            <processor ref="my.jbatchtest.samplebatch3.SampleProcessor"/>
            <writer ref="my.jbatchtest.samplebatch3.SampleWriter" />
     </chunk> 
  </step>
</job>

ItemReader:

package my.jbatchtest.samplebatch3;

import java.io.Serializable;

import javax.batch.api.chunk.ItemReader;
import javax.naming.InitialContext;
import javax.transaction.UserTransaction;

import org.xadisk.connector.outbound.XADiskConnectionFactory;

public class SampleReader implements ItemReader {

    private UserTransaction utx;


    public SampleReader() {
        // TODO Auto-generated constructor stub
    }

    @Override
    public void open(Serializable checkpoint) throws Exception {

        utx = (UserTransaction) new InitialContext().lookup("jta/usertransaction");   
        System.out.println("Status before begin:"+utx.getStatus());
        utx.begin();
        System.out.println("Status after begin:"+utx.getStatus());

    }

    @Override
    public void close() throws Exception {
        // TODO Auto-generated method stub

    }

    @Override
    public Object readItem() throws Exception {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Serializable checkpointInfo() throws Exception {
        // TODO Auto-generated method stub
        return null;
    }

}

ItemReader的调试输出:

[07.10.14 12:52:48:881 CEST] 00000039 SystemOut     O Status before begin:6
[07.10.14 12:52:48:881 CEST] 00000039 SystemOut     O Status after begin:0

我的问题是:

  1. 我的理解是正确的,春季批次应该管理交易吗?
  2. 然后为什么不这样做?

3 个答案:

答案 0 :(得分:7)

让我谈谈在这里提出的一些问题。完全披露,我目前是Spring Batch的项目负责人,我也是JSR-352的专家组。

Spring Batch和JSR-352的状态是什么
版本3.0.0的Spring Batch符合JSR-352标准,适用于所有SE要求。 JSR-352的要求分为SE和EE分组。我们没有解决规范中规定的与Spring Batch&#34; normal&#34;处理

为什么没有Spring Batch实现EE特定功能?
出于一个简单的原因,我们走了仅实施SE要求的路线。这些是我们可以通过可用的TCK验证符合规范的唯一要求。验证EE特定要求的唯一方法是将TCK作为应用程序服务器(Oracle的CTS)认证的一部分运行,Spring Batch显然不是其中的一部分,也不具有访问权限(鉴于此必须获得许可)。

我们已经要求TCK的一个版本,我们可以验证EE功能,截至今天,我们收到的回复是"In opening up the TCK for public contributions on GitHub, this is certainly an enhancement we'd be happy to accept help with."

与任何优秀的开发人员一样,我们不希望在没有测试的情况下开发新功能。我们希望能够验证我们实施的内容是否符合要求。在这种情况下,验证步骤在于对我们的代码执行TCK,这是我们目前无法做到的。无法执行TCK使我们面临以我们认为的方式实施EE功能的风险。是正确的,释放它们,然后如果/当TCK可以运行时必须改变它们的行为,这与JCP试图提供的可移植性直接相矛盾。

BATCH-2240怎么样?
BATCH-2240目前的情况是一个修复Spring Batch JSR-352实现行为的请求。相反,它要求在事务中包装ItemStream#open()ItemStream#close()方法的行为只会影响正常的Spring Batch处理。修复BATCH-2240不会直接解决Spring Batch的JSR-352的行为方式。它被标记为一个小改进,因为它不被视为我们的JSR-352实现中的错误,它被视为我们常规Spring Batch处理的附加功能。

回答原始问题
1. 我的理解是否正确,春季批次应该管理交易? - 是的,您的理解是正确的。 Spring Batch确实处理事务。使用基于块的步骤,在事务外部调用open和close方法,允许重置实现组件的状态。在Spring Batch中,没有什么可以阻止您使用TransactionTemplate在事务中包装代码以获得类似的功能 2. 那为什么不这样做? - 我希望以上几点能解决这个问题。

<强>结论
一旦我们有办法验证我们已经以保证JCP尝试实现的可移植性的方式解决了它们,我们想要解决JSR-352的EE特定功能。我们认为,正确的方法是拥有一个我们可以运行的标准化TCK。一旦解决了这个问题,解决规范的EE版本和Spring Batch之间的差异将是一个高优先级。

答案 1 :(得分:1)

在阅读并单步执行弹簧批处理代码并阅读JSR 352规范后,我认为这可能是春季批处理中的一个错误。

我不喜欢像春天这样对经过良好测试的图书馆指责问题,所以我仍然可能错了。这是我发现的:

Spring调用reader和writer的open()方法,然后执行读取,处理和写入的主要批处理循环。完成循环后,将在读写器上调用close()。

问题是,spring批处理只在事务上下文中运行主批处理循环。它不会为open()和close()调用启动事务。

根据规范,这些调用应该在他们自己的事务中运行。这来自JSR 352规范:

11.6 Regular Chunk Processing

1. <Create StepContext>
2. <Store step level properties in StepContext>
3. <->[StepListener.beforeStep...] // thread A
4. [<begin transaction> ]
5. <->ItemReader.open // thread A
6. <->ItemWriter.open // thread A
7. [<commit transaction> ]
8. // chunk processing:
9. <repeat until no more items> {
   a. <begin checkpoint [<begin transaction> ]>
   b. <repeat until commit criteria reached> {
        i. <->ItemReader.readItem // thread A
       ii. <->ItemProcessor.processItem // thread A
      iii. <add item to buffer>
   c. }
   d. <->ItemWriter.writeItems // thread A
   e. <->[ItemReader.checkpointInfo] // thread A
   f. <->[ItemWriter.checkpointInfo] // thread A
   g. <Store StepContext persistent area>
   h.
   i. <commit checkpoint (commit transaction)>
10. }
11. [<begin transaction> ]
12. <->ItemWriter.close // thread A
13. <->ItemReader.close // thread A
14. [<commit transaction> ]
15. <->[StepListener.afterStep...] // thread A
16. <Store StepContext persistent area>
17. <Destroy StepContext>

第4,7,11和4行永远不会发生在春季批次中。

我在我的代码中看到了这种行为(open()和close()中没有打开的事务),它也反映在spring批处理代码中:主循环的明显事务括号,open()没有事务代码和关闭())

我发现无法在spring.io网站上发布错误,只是指向stackoverflow.com的链接。也许来自Spring团队的人会看到这个并提供一些反馈(或者至少将其传递给开发人员)

Upate :这似乎是一个众所周知的问题:https://jira.spring.io/browse/BATCH-2240 规范的表示法似乎表明在这里开始一个事务是可选的,这使编码读者和编写者很麻烦,因为我必须检查我是否有一个有效的事务,并且创建我自己的事务括号是必要的。

答案 2 :(得分:1)

在你的samplebatch3.xml上,你需要在你的步骤和块标签之间声明一个tasklet,并且在tasklet标签上,你提交一个对Spring Batch将使用的事务管理器的引用,否则他不会知道要使用哪个事务管理器。请参阅本页5.1.1节:

http://docs.spring.io/spring-batch/trunk/reference/html/configureStep.html

编辑:对不起,我忘了你使用jsr-352而不是普通的Spring批处理,看到下面的链接,它指定了你需要传递给框架的一些设置,其中一个是事务管理器

http://docs.spring.io/spring-batch/trunk/reference/html/jsr-352.html

在本文中,有一个配置示例:

https://blog.codecentric.de/en/2014/08/writing-jsr-352-style-jobs-spring-batch-part-1-configuration-options/

请参阅“如何自定义标准配置”

部分
相关问题