9 Replies Latest reply on Oct 26, 2011 3:33 PM by smarlow

    Alternative Persistence Providers?

    hwellmann.de

      According to https://docs.jboss.org/author/display/AS7/JPA+Reference+Guide, the only "alternative" persistence provider supported by AS 7 is Hibernate 3.x.

       

      This amounts to a no-go for using AS7 for Java EE 6 projects that rely on advanced JPA 2.0 features like persistent maps and order columns, which are buggy in HIbernate and have not been fixed for more than a year now.

       

      For this reason, I've switched from Hibernate to OpenJPA 2.x in most of my projects.

       

      Changing the persistence provider for a Java EE 6 server should not be harder than dropping a number of JARs into an appopriate folder and restarting the server. That's the way it works with GlassFish 3.x and Resin 4.x.

       

      So I'm quite surprised that AS 7 requires an adapter per provider - rather than trying to implement these adapters, wouldn't it be a more sustainable solution to redesign the container/provider interface so that AS 7 works with any JPA 2.0 provider out of the box?

       

      Anyway, as a short term solution, I would be happy with an OpenJPA adapter (Eclipselink also had blocker bugs last time I checked).

       

      Best regards,

      Harald

        • 1. Re: Alternative Persistence Providers?
          alaisi

          Currently OpenJPA works with AS7.1 nightly snapshot, but it requires build time enhancement of persistent classes.

           

          I have filed a JIRA for this (AS7-2209) and added pull request (https://github.com/jbossas/jboss-as/pull/489)  that contains an implementation of an OpenJPA adaptor.

           

          Eclipselink seems to work out of the box with nightly snapshot, but you have to set persistence unit property 'jboss.as.jpa.providerModule' to 'application' if Eclipselink is bundled with the EAR. Eclipselink can also be loaded from a module (org.eclipse.persistence:main) but the libs are not shipped with AS.

           

          -Antti

          • 2. Re: Alternative Persistence Providers?
            smarlow

            Thanks for the feedback on this.  I made changes a few weeks ago, to make the adaptor optional, which works in a limited fashion (the persistence provider needs to figure out on its own, how to get the JTA transaction manager or just be used for read-only support).

            • 3. Re: Alternative Persistence Providers?
              hwellmann.de

              Scott and Antti, thanks for your replies so far!

               

              So if I get you right, there are (at least) two issues:

               

              1) The persistence provider needs to look up a TransactionManager, and the Java EE specs do not standardize a lookup method.

               

              2) Load-time enhancement or byte-code weaving must be taken care of.

               

              Regarding 1), looking at the OpenJPA sources, I can see a number of hard-coded JNDI names that will be tried, including java:/TransactionManager, but since JBoss AS 7 now uses java:jboss/TransactionManager, I don't think this will work.

               

              There's another method using the TransactionSynchronizationRegistry, which looks a bit mysterious to me, using java:comp/ /TransactionSynchronizationRegistry as entry point.

               

              The [Migration Guide|https://docs.jboss.org/author/display/AS7/How+do+I+migrate+my+application+from+AS5+or+AS6+to+AS7] lists java:/TransactionSynchronizationRegistry as the old name and java:jboss/TransactionSynchronizationRegistry as the new name - does that mean the the official name java:comp/ /TransactionSynchronizationRegistry defined in the JTA spec is not supported by JBoss?

               

              If all these methods should fail, looking at Antti's patch, there's a line

               

              {code}

              properties.put("openjpa.ManagedRuntime", "jndi(TransactionManagerName=java:jboss/TransactionManager)");

              {code}

               

              so it seems I could simply set a property in my persistence.xml to tell OpenJPA where to find the TransactionManager...?

               

              2) I may be wrong, but I was under the impression that javax.persistence.spi.PersistenceUnitInfo.addTransformer() provides the contract between container and persistence provider for load-time weaving. Why is this not sufficient for JBoss?

               

              And my biggest question is

               

              3) How do I package OpenJPA to work with JBoss?

               

              Can I simply include all the required JARs in my WAR? Do I have to set the jboss.as.jpa.providerModule property? Or do I have to define a JBoss module - if so, how...?

               

              Best regards,

              Harald

              • 4. Re: Alternative Persistence Providers?
                alaisi

                properties.put("openjpa.ManagedRuntime", "jndi(TransactionManagerName=java:jboss/TransactionManager)");


                so it seems I could simply set a property in my persistence.xml to tell OpenJPA where to find the TransactionManager...?

                Correct.

                 

                2) I may be wrong, but I was under the impression that javax.persistence.spi.PersistenceUnitInfo.addTransformer() provides the contract between container and persistence provider for load-time weaving. Why is this not sufficient for JBoss?

                This apparently hasn't been implemented yet (or is a bug?) as there are no references to org.jboss.as.jpa.config.PersistenceUnitMetadataImpl::transformers? I'm assuming the reason is that ModuleClassloader doesn't expose a way to add ClassFileTransformers? I used an ugly reflection hack to to get the transformer in place.

                 

                3) How do I package OpenJPA to work with JBoss?

                 

                Can I simply include all the required JARs in my WAR? Do I have to set the jboss.as.jpa.providerModule property? Or do I have to define a JBoss module - if so, how...?

                You can package OpenJPA with the war/ear as usual and it should work without setting providerModule.

                 

                So this should work with an unmodified AS7.1 nightly snapshot.

                1. Set provider in persistence.xml to org.apache.openjpa.persistence.PersistenceProviderImpl
                2. Set persistence unit property openjpa.ManagedRuntime to jndi(TransactionManagerName=java:jboss/TransactionManager)
                3. Enhance the entity classes at build time (use OpenJPA Maven/Ant task)
                4. Package OpenJPA in the war/ear as normal
                • 5. Re: Alternative Persistence Providers?
                  smarlow

                   

                  2) I may be wrong, but I was under the impression that javax.persistence.spi.PersistenceUnitInfo.addTransformer() provides the contract between container and persistence provider for load-time weaving. Why is this not sufficient for JBoss?

                  This apparently hasn't been implemented yet (or is a bug?) as there are no references to org.jboss.as.jpa.config.PersistenceUnitMetadataImpl::transformers? I'm assuming the reason is that ModuleClassloader doesn't expose a way to add ClassFileTransformers? I used an ugly reflection hack to to get the transformer in place.

                   

                  Sounds like a bug.  Could you create a jira for adding support for ClassTransformer?  I think a delegate classloader needs to handle this that would use the  application ModuleClassloader (which is returned from PersistenceUnitInfo.getClassLoader()). 

                  • 6. Re: Alternative Persistence Providers?
                    alaisi

                    Created AS7-2233: JPA ClassTransformers are ignored.

                     

                    Scott: I can work on a patch if you can explain a bit more what you mean by using a delegate classloader?

                    • 7. Re: Alternative Persistence Providers?
                      smarlow

                      After looking closer, I'm not sure.  Could you paste a link to your ugly reflection hack to to get the transformer in place.

                      • 8. Re: Alternative Persistence Providers?
                        alaisi
                        // Get org.jboss.modules.ModuleClassLoader::transformer
                        Field transformer = moduleClassLoader.getClass().getDeclaredField("transformer");
                        transformer.setAccessible(true);
                        Object delegatingClassFileTransformer = transformer.get(moduleClassLoader);
                        
                        // Call org.jboss.as.server.deployment.module.DelegatingClassFileTransformer::addTransformer
                        Method addTransformer = delegatingClassFileTransformer.getClass().getMethod("addTransformer", ClassFileTransformer.class);
                        addTransformer.invoke(delegatingClassFileTransformer, createPCTransformer(pu));
                        

                        The code is the same as what snowdrop uses

                         

                        So JBoss modules has the functionality to support ClassFileTransformers, it's just not apparently in the public API

                        • 9. Re: Alternative Persistence Providers?
                          smarlow

                          I was just looking at the temp classloader issue when I saw your pull request.  I got sidetracked from looking at your changes but will soon.