【问题标题】:@Remote EJB which uses @RequestScoped CDI bean@Remote EJB 使用 @RequestScoped CDI bean
【发布时间】:2015-11-20 12:26:24
【问题描述】:

我有一个应用程序,它有一个 @Remote @Singleton EJB,它注入了一个由 CDI 生成的 @RequestScoped 实体管理器。同一服务器 (wildfly 9)/JVM 上的另一个应用程序将使用此 EJB 来获取从实体管理器获取的结果。

第一次调用 EJB 将返回预期的结果。它生成实体管理器,获取数据并在调用返回时再次处理实体管理器。由于关闭的实体管理器,该 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 注入都没关系。返回的实例报告(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


Edit 20.11.2015 13:43:持久性单元的类型为 RESOURCE_LOCAL。此外,所有@ResourceScoped bean 都会受到影响。 @PostConstruct 和 @PreDestroy 仅在第一次 EJB 调用时被调用。每个后续调用都使用不正确的资源范围 bean 的前一个实例。

Edit 20.11.2015 13:55:如果从提供 EJB 的同一应用程序中调用 EJB,一切都会按预期工作。此行为仅出现在来自其他应用程序的调用中。

Edit 20.11.2015 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)。

【问题讨论】:

    标签: java jakarta-ee cdi wildfly


    【解决方案1】:

    当使用RESOURCE_LOCAL时,你应该从EntityManagerFacgtory创建你的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();
        }
    }
    

    【讨论】:

    • 我不能这样做,因为我们正在使用需要RESOURCE_LOCAL 持久性上下文的自定义事务处理。这也不是实体管理器注入的问题,因为在第二次调用时不会创建请求范围的上下文 - 旧实例将被重用,这是错误的。
    • 我还编辑了我最初的问题并附加了更多信息。实体管理器的注入适用于除此之外的任何用例。如果在提供 EJB 的同一应用程序中调用 EJB,它甚至可以工作。根据规范,远程 EJB 调用应该有一个活动的和工作的请求范围。您的解决方案似乎是一种解决方法,但它不能是唯一的解决方案。
    • 这不是一种变通方法,它是官方获取 RESOURCE_LOCAL 模式下的 EntityManager 的方式。如果您只想执行读取操作,则可以跳过事务 try/catch 并从 EntityManager 调用 findById 方法。
    • 这是一种解决方法,我正在做您在示例中所做的事情,但隐藏在将创建的实体管理器绑定到请求范围的 CDI 生产者中。但是请求范围的处理在某种程度上被“损坏”了。我切换到您的示例,直到找到解决方案(如果它是一个错误)。
    • 您可以随时扩展您的 entityManager 范围,使其与 Singleton 一样长。
    【解决方案2】:

    此有线行为的错误修复已合并到 WELD 存储库中:

    【讨论】:

      猜你喜欢
      • 2014-06-02
      • 1970-01-01
      • 1970-01-01
      • 2016-06-08
      • 1970-01-01
      • 2019-08-04
      • 2013-11-22
      • 2015-07-14
      • 2015-02-12
      相关资源
      最近更新 更多