目前我们有一个部署架构,一堆数据导向的服务通过RMI暴露给业务服务。这两种类型(数据导向的服务和业务服务)都是无状态会话bean。每个数据服务接口包(包含远程接口)还有一个定位器,用于执行JNDI查找。我们这样做是为了可以从业务服务逻辑的任何地方调用数据导向的服务。
以下是定位器的示例:
public final class OMRLocator {
private static final Logger LOG = Logger.getLogger( OMRLocator.class );
private static final String ORG_WILDFLY_INITIAL_CTX_FACTORY = "org.wildfly.naming.client.WildFlyInitialContextFactory";
private OMRLocator() {
}
@Produces
public static OrganisationsAndMandatesRegister locate() {
try {
Properties ctxProp = new Properties();
ctxProp.put( Context.INITIAL_CONTEXT_FACTORY, ORG_WILDFLY_INITIAL_CTX_FACTORY );
InitialContext ctx = new InitialContext( ctxProp );
return (OrganisationsAndMandatesRegister) ctx.lookup( OrganisationsAndMandatesConstants.REMOTE_NAME );
}
catch ( NamingException ex ) {
LOG.log( Level.WARN, "Cannot reach: " + OrganisationsAndMandatesConstants.REMOTE_NAME, ex );
return null;
}
}
}
我们之前在JBOSS EAP6上运行,并开始使用CDI进行实验。因此,我们向data-service-beans添加了一个
beans.xml
,并使用@Produces
将(在这种情况下为OrganisationAndMandatesRegister
)变成CDI可注入的对象。我们的想法是,在未来,我们可能会重新打包我们的应用程序,并将数据服务与业务服务一起打包到一个企业存档中。最近,我们迁移到了JBOSS EAP7.2(Wildfly 8?),突然出现了各种意外的延迟和事务问题。
我怀疑我们获取bean的方式是这些问题的因素之一。例如:我猜作用域取决于业务EJB生命周期,但对于每次调用业务服务中的
locate()
,都会产生一个新的数据服务实例。那么问题来了:在使用CDI时,生产远程bean(通过RMI)的最佳方法是什么?是否应考虑作用域,因为两种类型的服务均为无状态(或者说这是自动完成的)?
@Produces
进行了一些实验。令我惊讶的是(当我调试时),纯粹的@Produces
只会导致locate
方法被调用一次。然而,当我将@RequestScoped
添加到@Produces
中时,每个bean调用都会突然调用locate
(这正是我首先期望的,因为作用域是依赖于它的)。我还没有理解这个。 - Sjaak@Produces
注入的,具有构造函数注入,我更喜欢使用字段(单元测试)。据我所知,@EJB只能用于字段。我试图完全删除定位器,但似乎无法使用@ Inject进行远程EJB(Weld抱怨)...我认为@EJB仅适用于企业bean,因此如果我遵循您的建议,则定位器本身必须是@ApplicationScoped
(本地)无状态bean。 - Sjaak