Search code examples
javajakarta-eejpawebsphere

Persistence Unit fails to inject first time an app is published but succeeds when app is restarted


When i first start up my application server with the already published deployed app, any attempt to inject the persistence unit declared in a particular module fails the first time the bean declaring it is invoked. I can solve the issue by restarting the application, however this consistently happens every time I republish.

I am using WebSphere v8.0.4.2 and developing through Rational Application Developer v8 (although I think that's irrelevant).

NOTE: the ABCBean contains the EntityManager and resides in the ABC.jar, and The OTHERMODULE.jar is the code that the exception relates to. the modules are a part of one EAR file.

so:

ABC
\__ ABCBean
\__ META-INF/persistence.xml

OTHERMODULE
\__ beans that call above bean and cannot resolve persistence unit.

The exception I get when invoking my persistence bean is:

javax.ejb.EJBTransactionRolledbackException: nested exception is: javax.ejb.EJBException: The ABCBean/em reference of type javax.persistence.EntityManager for the ABCBean component in the XYZ.jar module of the MYAPP application cannot be resolved.
javax.ejb.EJBException: The ABCBean/em reference of type javax.persistence.EntityManager for the ABCBean component in the OTHERMODULE.jar module of the MYAPP application cannot be resolved.
    at com.ibm.wsspi.injectionengine.InjectionBinding.getInjectionObject(InjectionBinding.java:1100)
    at com.ibm.wsspi.injectionengine.InjectionBinding.getInjectableObject(InjectionBinding.java:1013)
    at com.ibm.wsspi.injectionengine.InjectionTarget.inject(InjectionTarget.java:198)
    at com.ibm.ws.injectionengine.AbstractInjectionEngine.inject(AbstractInjectionEngine.java:947)
    at com.ibm.ejs.container.StatelessBeanO.initialize(StatelessBeanO.java:300)
    at com.ibm.ejs.container.BeanOFactory.create(BeanOFactory.java:147)...

Here is my persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" ...>
    <persistence-unit name="ABC_EJB">
        <jta-data-source>jdbc/***</jta-data-source>
        ...
    </persistence-unit>
</persistence>

And the Class in the exception:

@Stateless
@LocalBean
public class ABCBean {
    ...

    @PersistenceContext(unitName = "ABC_EJB")
    private EntityManager em;
    ...

}

Solution

  • The persistence context is not referencable to the OTHERMODULE because the it is limited to the scope of the ABC.jar. the answer with the most votes at the bottom of this question shows the documentation related to sharing persistence.xml contexts across an EAR deployment. here is an excerpt from the specs:

    the root of a persistence unit must be one of the following:

    • an EJB-JAR file
    • the WEB-INF/classes directory of a WAR file[80]
    • a jar file in the WEB-INF/lib directory of a WAR file
    • a jar file in the EAR library directory
    • an application client jar file

    AND

    A persistence unit that is defined at the level of the EAR is generally visible to all components in the application. However, if a persistence unit of the same name is defined by an EJB-JAR, WAR, or application jar file within the EAR, the persistence unit of that name defined at EAR level will not be visible to the components defined by that EJB-JAR, WAR, or application jar file unless the persistence unit reference uses the persistence unit name # syntax to specify a path name to disambiguate the reference.

    my solved project structure is as follows:

    APP_EAR
    \__lib
        \__domain.jar
            \__META-INF
                \__persistence.xml (with <jar-file>../ABC.jar</jar-file> element because ABC module contains entity classes).
    \__ABC.jar
    \__OTHERMODULE.jar
    

    afterwards i could remove all the ejb-jar persistence-context-refs from the file and it would still resolve the reference.