0
votes

I have an application which has a @Remote @Singleton EJB which injects a @RequestScoped entity manager produced by CDI. Another application on the same server (wildfly 9)/JVM will use this EJB to get a result fetched from the entity manager.

The first invocation of the EJB will return the expected result. It produces the entity manager, fetches the data and disposes the entity manager again when the invocation returns. Each subsequent invocation of that EJB will throw an error because of a closed entity manager. No produce / dispose for a new entity manager is made.

Is this the expected bahavior? Do I have an error in my code?


IFrameworkResourceManager framework = _applicationContext.getFrameworkResourceManager();
final User resolvedUser = framework.resolveUser(username, domain);
// ...
final Rights resolvedRights = framework.resolveRights(resolvedUser.getGuid(), applicationId);
// ...

This piece of code is executed in a CDI producer which again is executed as soon as a new http session is created for an user. Nothing changes if I call getFramworkResourceManager again before invoking resolveRights.


public IFrameworkResourceManager getFrameworkResourceManager() {
    return IFrameworkResourceManager frm = (IFrameworkResourceManager) ctx
        .lookup("java:global/WebFramework/WebFrameworkImpl!my.package.IWebFramework");
}

It doesn't matter if I use a direct JNDI lookup or @EJB injection. The returned instance is reported (toString()) as 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);
}

Sysout of resolveUser: org.hibernate.jpa.internal.EntityManagerImpl@379e882b || true

Sysout of resolveRights: org.hibernate.jpa.internal.EntityManagerImpl@379e882b || false


Edit 20.11.2015 13:43: Persistence unit is of type RESOURCE_LOCAL. Additionally all @ResourceScoped beans are affected. @PostConstruct and @PreDestroy are only invoked for the first EJB invocation. Each subsequent invocation uses the previous instance of the resource scoped bean which is not correct.

Edit 20.11.2015 13:55: Everything works as expected if the EJB is invoked from within the same application that provides the EJB. This behavior only appears for invocations from other applications.

Edit 20.11.2015 15:24: JBoss AS 7.1.3.Final, Wildfly 9.0.0.Final and Wildfly 10.0.0.CR4 are all effected. But according to the CDI spec (1.0 to 1.2) chapter 6.7.4 this should work. I've filled a bug report (WFLY-5716).

2

2 Answers

1
votes

When using RESOURCE_LOCAL, you shoud create youe EntityManager from EntityManagerFacgtory and handle it by yourself, like:

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();
    }
}
0
votes

Bugfix for this wired behavior is already merged in the WELD repository: