使用@RequestScoped CDI bean 的@Remote EJB
@Remote EJB which uses @RequestScoped CDI bean
我有一个应用程序,它有一个 @Remote @Singleton
EJB,它注入了一个由 CDI 生成的 @RequestScoped
实体管理器。同一服务器 (wildfly 9)/JVM 上的另一个应用程序将使用此 EJB 获取从实体管理器获取的结果。
EJB 的第一次调用将return 预期结果。它产生实体管理器,获取数据并在调用 returns 时再次处理实体管理器。由于关闭的实体管理器,该 EJB 的每个后续调用都将抛出错误。没有为新的实体管理器生成/处理。
这是预期的行为吗?我的代码有错误吗?
IFrameworkResourceManager framework = _applicationContext.getFrameworkResourceManager();
final User resolvedUser = framework.resolveUser(username, domain);
// ...
final Rights resolvedRights = framework.resolveRights(resolvedUser.getGuid(), applicationId);
// ...
这段代码在 CDI 生产者中执行,一旦为用户创建新的 http 会话就会再次执行。如果我在调用 resolveRights
.
之前再次调用 getFramworkResourceManager
,则没有任何变化
public IFrameworkResourceManager getFrameworkResourceManager() {
return IFrameworkResourceManager frm = (IFrameworkResourceManager) ctx
.lookup("java:global/WebFramework/WebFrameworkImpl!my.package.IWebFramework");
}
我使用直接JNDI查找还是@EJB
注入都没有关系。 returned 实例被报告 (toString()
) 为 Proxy for remote EJB StatelessEJBLocator for "/WebFramework/WebFrameworkImpl", view is interface my.package.IWebFramework, affinity is None
@LocalBean
@Singleton
public class WebFrameworkImpl implements IWebFramework, Serializable {
@Inject
private EntityManager _entityManager;
@Override
public User resolveUser(String username, String domain) {
System.out.println(_entityManager + " || " + _entityManager.isOpen());
// execute query using QueryDSL and the injected entityManager
}
@Override
public Rights resolveRights(String guidUser, int applicationId) {
System.out.println(_entityManager + " || " + _entityManager.isOpen());
// execute query using QueryDSL and the injected entityManager
}
}
@Remote
public interface IWebFramework extends IFrameworkResourceManager {
// some methods...
}
public interface IFrameworkResourceManager {
public User resolveUser(String username, String domain);
public Rights resolveRights(String guidUser, int applicationId);
}
resolveUser
的系统输出:org.hibernate.jpa.internal.EntityManagerImpl@379e882b || true
resolveRights
的系统输出:org.hibernate.jpa.internal.EntityManagerImpl@379e882b || false
编辑 2015 年 11 月 20 日 13:43:持久性单元的类型为 RESOURCE_LOCAL
。此外,所有 @ResourceScoped
个 beans 都会受到影响。 @PostConstruct
和 @PreDestroy
仅在第一次 EJB 调用时被调用。每个后续调用都使用不正确的资源作用域 bean 的先前实例。
编辑 2015 年 11 月 20 日 13:55:如果从提供 EJB 的同一应用程序中调用 EJB,一切都会按预期进行。此行为仅出现在来自其他应用程序的调用中。
编辑 2015 年 11 月 20 日 15:24:JBoss AS 7.1.3.Final、Wildfly 9.0.0.Final 和 Wildfly 10.0 .0.CR4 都受到影响。但根据 CDI 规范(1.0 到 1.2)第 6.7.4 章,这应该可行。我已经填写了错误报告 (WFLY-5716)。
使用 RESOURCE_LOCAL
时,您应该从 EntityManagerFactory 创建 EntityManager 并自行处理,例如:
private EntityManagerFactory factory = Persistence.createEntityManagerFactory("unit-name");
public void someMethod(){
EntityManager em = emf.createEntityManager();
EntityTransaction tx = null;
try {
tx = em.getTransaction();
tx.begin();
// do some work
tx.commit();
}
catch (RuntimeException e) {
if ( tx != null && tx.isActive() )
tx.rollback();
throw e; // or display error message
}
finally {
em.close();
}
}
此连线行为的错误修复已合并到 WELD 存储库中:
我有一个应用程序,它有一个 @Remote @Singleton
EJB,它注入了一个由 CDI 生成的 @RequestScoped
实体管理器。同一服务器 (wildfly 9)/JVM 上的另一个应用程序将使用此 EJB 获取从实体管理器获取的结果。
EJB 的第一次调用将return 预期结果。它产生实体管理器,获取数据并在调用 returns 时再次处理实体管理器。由于关闭的实体管理器,该 EJB 的每个后续调用都将抛出错误。没有为新的实体管理器生成/处理。
这是预期的行为吗?我的代码有错误吗?
IFrameworkResourceManager framework = _applicationContext.getFrameworkResourceManager();
final User resolvedUser = framework.resolveUser(username, domain);
// ...
final Rights resolvedRights = framework.resolveRights(resolvedUser.getGuid(), applicationId);
// ...
这段代码在 CDI 生产者中执行,一旦为用户创建新的 http 会话就会再次执行。如果我在调用 resolveRights
.
getFramworkResourceManager
,则没有任何变化
public IFrameworkResourceManager getFrameworkResourceManager() {
return IFrameworkResourceManager frm = (IFrameworkResourceManager) ctx
.lookup("java:global/WebFramework/WebFrameworkImpl!my.package.IWebFramework");
}
我使用直接JNDI查找还是@EJB
注入都没有关系。 returned 实例被报告 (toString()
) 为 Proxy for remote EJB StatelessEJBLocator for "/WebFramework/WebFrameworkImpl", view is interface my.package.IWebFramework, affinity is None
@LocalBean
@Singleton
public class WebFrameworkImpl implements IWebFramework, Serializable {
@Inject
private EntityManager _entityManager;
@Override
public User resolveUser(String username, String domain) {
System.out.println(_entityManager + " || " + _entityManager.isOpen());
// execute query using QueryDSL and the injected entityManager
}
@Override
public Rights resolveRights(String guidUser, int applicationId) {
System.out.println(_entityManager + " || " + _entityManager.isOpen());
// execute query using QueryDSL and the injected entityManager
}
}
@Remote
public interface IWebFramework extends IFrameworkResourceManager {
// some methods...
}
public interface IFrameworkResourceManager {
public User resolveUser(String username, String domain);
public Rights resolveRights(String guidUser, int applicationId);
}
resolveUser
的系统输出:org.hibernate.jpa.internal.EntityManagerImpl@379e882b || true
resolveRights
的系统输出:org.hibernate.jpa.internal.EntityManagerImpl@379e882b || false
编辑 2015 年 11 月 20 日 13:43:持久性单元的类型为 RESOURCE_LOCAL
。此外,所有 @ResourceScoped
个 beans 都会受到影响。 @PostConstruct
和 @PreDestroy
仅在第一次 EJB 调用时被调用。每个后续调用都使用不正确的资源作用域 bean 的先前实例。
编辑 2015 年 11 月 20 日 13:55:如果从提供 EJB 的同一应用程序中调用 EJB,一切都会按预期进行。此行为仅出现在来自其他应用程序的调用中。
编辑 2015 年 11 月 20 日 15:24:JBoss AS 7.1.3.Final、Wildfly 9.0.0.Final 和 Wildfly 10.0 .0.CR4 都受到影响。但根据 CDI 规范(1.0 到 1.2)第 6.7.4 章,这应该可行。我已经填写了错误报告 (WFLY-5716)。
使用 RESOURCE_LOCAL
时,您应该从 EntityManagerFactory 创建 EntityManager 并自行处理,例如:
private EntityManagerFactory factory = Persistence.createEntityManagerFactory("unit-name");
public void someMethod(){
EntityManager em = emf.createEntityManager();
EntityTransaction tx = null;
try {
tx = em.getTransaction();
tx.begin();
// do some work
tx.commit();
}
catch (RuntimeException e) {
if ( tx != null && tx.isActive() )
tx.rollback();
throw e; // or display error message
}
finally {
em.close();
}
}
此连线行为的错误修复已合并到 WELD 存储库中: