3 Replies Latest reply on Feb 25, 2011 3:13 AM by jaikiran

    EAR with WAR accessing a JAR with JPA entities and persistence.xml

    zecas

      Hi,

       

       

      I'm struggling with setting my persistence jar running in my web application, and maybe someone can give me a tip on doing this.

       

       

      I've created a standalone java api package, it is a simple jar file, persist-1.0.0.jar, with the following structure:

       

       

      [persist-1.0.0.jar]

      |

      +- META-INF

      |   |

      |   +- persistence.xml

      |

      +- com

           |

           +- jpa

               |

               +- Entity1.class

               +- Entity2.class

                  ...

       

       

      My persistence.xml contents are:

       

       

      <?xml version="1.0" encoding="UTF-8"?>

      <persistence version="2.0"

                xmlns="http://java.sun.com/xml/ns/persistence"

                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                >

                <persistence-unit name="myunit">

                          <jta-data-source>java:ds/MYUNIT</jta-data-source>

                          <class>com.jpa.Entity1</class>

                          <class>com.jpa.Entity2</class>

                </persistence-unit>

      </persistence>

       

       

      Now I have a WAR project inside an EAR, let's call them "webapp-1.0.0.war" and "myear-1.0.0.ear" respectivelly.

       

       

      At the moment, the jar is packaged at EAR level, and my WAR's MANIFEST.MF has a classpath reference to it (Class-Path: persist-1.0.0.jar).

       

       

      My intentions are that I just use "persist-1.0.0.jar" in the war project without any reference. The "persist-1.0.0.jar" should be in the classpath, with all entity classes and "persistence.xml" definition file, still I cannot use them without creating a specific "persistence.xml" file INSIDE my WAR project, which references the entity classes or just references the jar file for it to search them.

       

       

      Example:

       

       

      public class MyListener implements ServletContextListener {

                @PersistenceUnit(name="myunit")

                private EntityManagerFactory emf;

                ...

      }

       

       

      Will give me a:

       

       

      2011-02-23 11:09:35,127 ERROR [org.apache.catalina.core.StandardContext] (main) Context [/webapp] startup failed due to previous errors

      java.lang.IllegalArgumentException: Container org.jboss.web.tomcat.service.TomcatInjectionContainer@18cdde3 failed to resolve persistence unit null

                at org.jboss.injection.PersistenceUnitHandler.addPUDependency(PersistenceUnitHandler.java:135)

                at org.jboss.injection.PersistenceUnitHandler.loadXml(PersistenceUnitHandler.java:75)

                at org.jboss.web.tomcat.service.TomcatInjectionContainer.processMetadata(TomcatInjectionContainer.java:550)

                at org.jboss.web.tomcat.service.WebCtxLoader.start(WebCtxLoader.java:158)

                at org.apache.catalina.core.StandardContext.start(StandardContext.java:4272)

                at org.jboss.web.tomcat.service.deployers.TomcatDeployment.performDeployInternal(TomcatDeployment.java:310)

                at org.jboss.web.tomcat.service.deployers.TomcatDeployment.performDeploy(TomcatDeployment.java:142)

                at org.jboss.web.deployers.AbstractWarDeployment.start(AbstractWarDeployment.java:461)

                at org.jboss.web.deployers.WebModule.startModule(WebModule.java:118)

                at org.jboss.web.deployers.WebModule.start(WebModule.java:97)

                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

                at java.lang.reflect.Method.invoke(Method.java:597)

                at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:157)

                at org.jboss.mx.server.Invocation.dispatch(Invocation.java:96)

                ...

                at org.jboss.Main.boot(Main.java:221)

                at org.jboss.Main$1.run(Main.java:556)

                at java.lang.Thread.run(Thread.java:619)

      Caused by: java.lang.IllegalArgumentException: Can't find a persistence unit named 'null' in AbstractVFSDeploymentContext@3259467{vfszip:/Java/jboss-5.1.0.GA/server/default/deploy/myear-1.0.0.ear/webapp-1.0.0.war/}

                at org.jboss.jpa.resolvers.BasePersistenceUnitDependencyResolver.resolvePersistenceUnitSupplier(BasePersistenceUnitDependencyResolver.java:107)

                at org.jboss.web.tomcat.service.TomcatInjectionContainer.resolvePersistenceUnitSupplier(TomcatInjectionContainer.java:685)

                at org.jboss.injection.PersistenceUnitHandler.addPUDependency(PersistenceUnitHandler.java:130)

                ... 72 more

       

       

      If I include a "persistence.xml" in the WAR:

       

       

      <?xml version="1.0" encoding="UTF-8"?>

      <persistence version="2.0"

                xmlns="http://java.sun.com/xml/ns/persistence"

                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                >

                <persistence-unit name="myunit">

                          <jta-data-source>java:ds/MYUNIT</jta-data-source>

                          <jar-file>persist-1.0.0.jar</jar-file>

                </persistence-unit>

      </persistence>

       

       

      It will work fine, I can even delete the persistence.xml inside the "persist-1.0.0.jar".

       

       

      I would like it to load "persistence.xml" in the dependent jar, so it would give me a clean way of using the api jar.

       

       

       

       

      Isn't this supposed to work like this? What am I doing wrong? What's the best practice for doing this?

       

       

       

       

      Thanks

        • 1. Re: EAR with WAR accessing a JAR with JPA entities and persistence.xml
          jgautier

          What's the content of your application.xml file ?

          The following structure should make persistence visible from your war.

           

          my.ear

               |-->mypersistence.jar

                    |-->META-INF

                         |-->persistence.xml

                                   <jar-file>lib/mypackagedentities.jar</jar-file>

                         |-->MANIFEST.MF

                                   Class-Path: lib/mypackagedentities.jar

               |-->mywebapp.war

               |-->lib

                    |-->mypackagedentities.jar

               |-->META-INF

                    |-->application.xml

           

           

          Application.xml looks like:

              <module>

                  <ejb>mypersistence.jar</ejb>

              </module>

           

              <module>

                  <web>

                      <web-uri>mywebapp.war</web-uri>

                   </web>

             </module>

           

          Hope this helps,

           

          Jérôme

          • 2. Re: EAR with WAR accessing a JAR with JPA entities and persistence.xml
            zecas

            Hi,

             

            Thanks for the help. If I understand correctly, there is no way for me to do what I want.

             

            My "application.xml" looks like this:

             

            <?xml version="1.0" encoding="UTF-8"?>

            <application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:application="http://java.sun.com/xml/ns/javaee/application_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_5.xsd" id="Application_ID" version="5">

              <display-name>myear</display-name>

              <module>

                <web>

                  <web-uri>webapp-1.0.0.war</web-uri>

                  <context-root>webapp</context-root>

                </web>

              </module>

            </application>

             

             

            As you can see, I have no EJB module configured, and that seems to be the problem.

             

            My "persist-1.0.0.jar" contains the entities, and has maven for build purposes. I was not interested in making it an EJB package, but instead keep it a simple JAR package API. So it can be used as any regular JAR dependency, but if someone wants to, the persistence features could be used.

             

            In fact, they can be used anyway, as all that is required is the use of a "jar-file" reference to the JAR. Anyway, I was looking into a way of not needing to even create a "persistence.xml" in the project that want's to use it.

             

            I read in some manual that I could put the entities and the "persistence.xml" in a JAR, then just put it in the classpath to be used by a java program ... probably that just works for J2SE, and not in JavaEE ... I was in the hope that it would also work there, as the libs will be available to the webapp like classpath reference.

             

            So at the end of the day, I can just create an API with the entities, and if I want to use them, just put a "persistence.xml" in a WAR or EJB project, with "jar-file" to load up all entities from the "persist-1.0.0.jar" (or individually set the entity classes).

             

            That's what I'm thinking ... any more feedback is welcome, as I always like to learn best practices, to make things right, right from the start (as this is the case)

             

            Thanks

            • 3. Re: EAR with WAR accessing a JAR with JPA entities and persistence.xml
              jaikiran

              zecas zecas wrote:

               


              My intentions are that I just use "persist-1.0.0.jar" in the war project without any reference. The "persist-1.0.0.jar" should be in the classpath, with all entity classes and "persistence.xml" definition file, still I cannot use them without creating a specific "persistence.xml" file INSIDE my WAR project, which references the entity classes or just references the jar file for it to search them.

               

               

              Example:

               

               

              public class MyListener implements ServletContextListener {

                        @PersistenceUnit(name="myunit")

                        private EntityManagerFactory emf;

                        ...

              }

               

              Try:

               

              @PersistenceUnit(unitName="persist-1.0.0.jar#myunit")
                        private EntityManagerFactory emf;
              

               

              Note the use of:

               

              1) unitName instead of name

              2) The use of jar name and the symbol # in the unitName value