EJB抽象方法的本地调用是否打开了一个新的Transaction?

时间:2017-02-07 14:23:59

标签: inheritance java-ee transactions ejb

假设以下类的构造:

Filereader找到文件的匹配导入器并调用Importer.import方法。

此方法调用使用REQUIRES_NEW注释的抽象方法importSpecific

从容器的角度来看,本地调用不会打开新的Transaction,但是从继承的角度来看,我不确定。

importSpecific中的ImporterBase.import来电是否会创建新的交易?为什么会这样?

类FileReader:

@Singleton(name = "FileReader")
public class FileReader extends Traceable {

    /*@Inject
      @Any
      public Instance<Importer> importers;*/

    @EJB
    ExampleImporter importer;

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void listenToFileAvailableEvent(@Observes FileAvailable event) throws InterruptedException {        
        for (final String filename : event.getFilenames()) {            
            readFile(filename);
        }
    }

    public void readFile(String filenameWithPath) {
        //[...]-> Extract FileMetadata and find correct importer
        importer.import(dateiMeta);
    }
}

界面导入程序:

@Local
public interface Importer {
    void import(FileMetaData dateiMeta) throws Exception;
    void importSpecific(FileMetaData dateiMeta) throws Exception;
}

Class ImporterBase:

public abstract class ImporterBase implements Importer {
   @Resource
   private SessionContext ctx;

   @Override
   public void import(FileMetaData dateiMeta) throws Exception {           
       try {           
          ctx.getBusinessObject(Importer.class).importSpecific(dateiMeta);//This causes the error
       } catch (Exception ex) {            
           //[...] Log Error
           throw ex;
       }        
   }

   @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
   public abstract void importSpecific(FileMetaData dateiMeta) throws   Exception;

}

Class ExampleImporter:

@Stateless
public class ExampleImporter extends ImporterBase {

    @Override
    public void importSpecific(FileMetaData dateiMeta) throws Exception {
        //Import from file
    }   
}

1 个答案:

答案 0 :(得分:0)

不,importSpecific方法import调用何时(以及如何)从不打开新事务;因为(如你所说)容器始终是本地电话......

但是,根据this,注释@TransactionAttribute可以继承...所以,

为了使这种配置起作用,您必须:

1)在您的业务接口上声明importSpecific方法,即Importer接口。

2)将Importer接口表示为本地接口。

3)在FileReader Singleton,使用@EJB注释获取Importer Bean的代理。如果使用CDI注释(如@Inject),容器将注入CDI对象而不是EJB代理! (小心这个)

4)将您的ImporterBase代码更改为:

public abstract class ImporterBase implements Importer {
    @Resource
    private SessionContext ejbCtxt;

    @Override
    public void import(FileMetaData dateiMeta) throws Exception {
        Importer proxy0;    
        try {           
            proxy0 = this.ejbCtxt.getBusinessObject(Importer.class);
            proxy0.importSpecific(dateiMeta);

        } catch (Exception ex) {            
            //[...] Log Error
            throw ex;
        }        
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public abstract void importSpecific(FileMetaData dateiMeta) throws Exception;

}

5)改变你的ExampleImporter

@Stateless
@Local(Importer.class)
public class ExampleImporter extends ImportBase {
...
}

如果您确实需要在Singleton类中使用CDI Bean而不是EJB代理,则需要使用@Transactional CDI注释...而且您的代码也应该重构。