Java JSR352Spring批处理:事务管理

Java JSR352Spring批处理:事务管理,java,spring-batch,websphere-8,Java,Spring Batch,Websphere 8,我尝试在Websphere中以JSR352模式使用Spring批处理。(Websphere 8.0,Spring批处理3.0.1) 据我对文档的理解,spring应该处理事务,即在调用步骤的ItemReader之前开始事务,在调用ItemWriter之后提交事务,等等 但是,在我的例子中,调用ItemReader时没有事务处于活动状态(userTransaction.getStatus()==6)。如果我自己在itemReader中启动事务,我的代码就可以工作,但我的理解是我不应该这样做 我怀疑

我尝试在Websphere中以JSR352模式使用Spring批处理。(Websphere 8.0,Spring批处理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>
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;
    }

}
[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
我的问题是:

  • 我的理解正确吗,spring批处理应该管理事务
  • 那它为什么不这样做呢

  • 在阅读并逐步阅读spring批处理代码以及JSR352规范之后,我认为这可能是spring批处理中的一个bug

    我不喜欢把问题归咎于像spring这样经过良好测试的库,所以我仍然可能是错的。以下是我的发现:

    Spring调用读写器的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>
    
    11.6常规块处理
    1.
    2.
    3.[StepListener.beforeStep…]//线程A
    4.[ ]
    5.ItemReader.open//线程A
    6.ItemWriter.open//线程A
    7.[ ]
    8. // 区块处理:
    9{
    A.
    b{
    i、 ItemReader.readItem//线程A
    ii.ItemProcessor.processItem//线程A
    三,。
    
    规范的符号似乎表明,在这里启动事务是可选的,这使得编写读写器变得很麻烦,因为我必须检查是否有有效的事务,并创建自己的事务括号是必要的。

    在阅读并逐步阅读spring批处理代码,以及阅读JSR352规范之后,我将这可能是spring批处理中的一个错误

    我不喜欢把问题归咎于像spring这样经过良好测试的库,所以我仍然可能是错的

    Spring调用读写器的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>
    
    11.6常规块处理
    1.
    2.
    3.[StepListener.beforeStep…]//线程A
    4. [ ]
    5.ItemReader.open//线程A
    6.ItemWriter.open//线程A
    7. [ ]
    8//块处理:
    9.  {
    A.
    b{
    i、 ItemReader.readItem//线程A
    ii.ItemProcessor.processItem//线程A
    三,。
    
    规范的符号似乎表明,在这里启动事务是可选的,这使得编写读写器很麻烦,因为我必须检查是否有有效的事务,并创建自己的事务括号是必要的。

    在samplebatch3.xml上,您需要在步骤和块标记之间声明一个tasklet,并且在tasklet标记上,您将引用放在Spring批处理将使用的事务管理器上,否则他将不知道使用哪个事务管理器。请参阅本页第5.1.1节:

    编辑:抱歉,我忘了您使用jsr-352而不是纯Spring批处理,请参见下面的链接,它指定了一些需要传递给框架的设置,其中之一是事务管理器

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


    请参见samplebatch3.xml上的“如何自定义标准配置”一节,您需要在步骤标记和区块标记之间声明一个tasklet,并且在tasklet标记上,您可以引用Spring批将使用的事务管理器,否则他将不知道使用哪个事务管理器。请参见本页的第5.1.1节:

    编辑:抱歉,我忘了您使用jsr-352而不是纯Spring批处理,请参见下面的链接,它指定了一些需要传递给框架的设置,其中之一是事务管理器

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


    请参阅“如何定制标准配置”一节,让我插话一下这里提出的几个问题。完全公开,我目前是Spring Batch的项目负责人,也是JSR-352的专家组成员

    Spring Batch和JSR-352的状态如何 从3.0.0版开始,Spring Batch符合JSR-352的所有SE要求。JSR-352的要求分为SE和EE两类。我们没有解决规范中规定的与Spring Batch“正常”处理不同的任何EE特性

    为什么Spring Batch没有实现特定于EE的功能?
    我们之所以只实施SE需求,原因很简单。我们可以通过可用的TCK验证这些需求是否符合规范。验证EE特定需求的唯一方法是将TCK作为应用服务器(Oracle的CTS)认证的一部分运行,Spring Batch显然不是其中的一部分,也无权访问(考虑到它必须获得许可)

    我们已经请求了一个TCK版本,我们可以根据今天的响应验证EE功能