假设以下类的构造:
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
}
}
答案 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注释...而且您的代码也应该重构。