3 Replies Latest reply on Jul 17, 2008 10:51 AM by Sascha Goldsmith

    Chicken-Egg with PersistenceAnnotationBeanPostProcessor

    Sascha Goldsmith Newbie

      I have been trying to set-up a PersistenceAnnotationBeanPostProcessor using "vanilla" JNDI lookups to leverage all of the configuration we already have in JBoss (e.g., persistence.xml, JPA entites, etc.) I have run into what seems to be a chicken-egg issue with the ordering of the Spring-JBoss Deployer.

      If I use something like the following in an application context loaded by the deployer:

       <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" lazy-init="true">
       <property name="persistenceUnits">
       <map>
       <entry key="foo" value="java:/persistence-units/foo"/>
       </map>
       </property>
       </bean>
      


      And specifically instruct JBoss to expose its EJB3 EntityManagerFactory via the following in persistence.xml:

       <persistence-unit name="foo">
       <provider>org.hibernate.ejb.HibernatePersistence</provider>
       <jta-data-source>java:/Foo</jta-data-source>
       <properties>
       <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect" />
       <property name="jboss.entity.manager.factory.jndi.name" value="java:/persistence-units/foo"/>
       </properties>
       </persistence-unit>
      


      I get a javax.naming.NamingException (unable to find 'java:/persistence-units/foo"). Looking at the logs, I noticed that the Spring-JBoss Deployer deploys *before* the EJB-managed JPA entities are loaded and then bound to JNDI by the EJB3 deployer.

      So... I thought I would control the ordering of the Spring-JBoss MBean by tinkering with jboss-service.xml:

      <server>
       <mbean
       code="org.jboss.spring.deployment.SpringApplicationContextDeployer"
       name="jboss.spring:service=SpringApplicationContextDeployer">
      
       <depends>jboss.j2ee:service=EJB</depends>
      
       </mbean>
      </server>
      


      This allowed the EJB entities to be loaded and bound to JNDI before the application context beans were loaded, and all was well. Except that must have done something else somewhere because the WAR stopped loading properly.

      Is there a simple way to use PersistenceAnnotationBeanPostProcessor and JNDI to allow for multiple persistence units already initialized by the EJB3 deployer in JBoss?

      Thanks!

      Saish

        • 1. Re: Chicken-Egg with PersistenceAnnotationBeanPostProcessor
          Sascha Goldsmith Newbie

          Realized I was somewhat think in my snippit, "the WAR stopped working properly". What happened there was that beanRefContext.xml could no longer locate the ApplicationContext mounted by the Spring Deployer. (JNDI javax.naming.NamingException). So, I attempted to add a dependency within the jboss-web.deployer (to have a dependency on the Spring deployer), and at that point, the WAR would not load. There were no errors, but localhost:8080 never returned anything.

          So, in an ideal world:

          1. Load EJB JPA entities managed by JBoss and bind EntityManagerFactory to JNDI.

          2. Load the EAR ApplicationContext and bind to JNDI via Spring JBoss Deployer

          3. Finally load the WAR so that context.ear in beanRefContext.xml finds the JNDI ApplicationContext.

          Saish

          • 2. Re: Chicken-Egg with PersistenceAnnotationBeanPostProcessor
            Ales Justin Master

            Since you're probably talking about JBossAS4.x, this is what you can do:

            Default deployers order:

             <!--
             Statically set one or more enhanced suffix orders, independent of the value proposed by subdeployers.
             Some deployers may also allow the suffixes/orders to be set locally, so that's preferable too.
             For reference, this is the list of enhanced suffixes likely to be set by deployers (it may not
             be completely up-to-date, or there can be user-defined deployers).
            
             050:.deployer,050:-deployer.xml,100:.aop,100:-aop.xml,150:.sar,150:-service.xml,200:.beans,250:.rar,300:-ds.xml,350:.har,400:.jar,400:.ejb3,400:.par,500:.war,600:.wsr,650:.ear,700:.jar,750:.zip,800:.bsh,900:.last
            
             Until we resolve some startup issues, we'll setup some static enhanced suffix orders bellow
             and leave the rest of the suffixes contributed dynamically by registering deployers.
             -->
             <descriptors>
             <value value="250:.rar,300:-ds.xml,400:.jar,500:.war,550:.jse,650:.ear,800:.bsh"/>
             </descriptors>
            

            SpringDeployer defines #350:
             public SpringDeployer()
             {
             initializeMainDeployer();
             }
            
             protected void initializeMainDeployer()
             {
             setSuffixes(new String[]{".spring", "-spring.xml"});
             setRelativeOrder(350); //after -ds, before ejb3
             }
            


            Just change that property in SpringDeployer's -service.xml and you should be fine. ;-)

            • 3. Re: Chicken-Egg with PersistenceAnnotationBeanPostProcessor
              Sascha Goldsmith Newbie

              Thanks so much Ales! That is exactly what I was looking for.

              As an aside, I did manage to get things set up "manually" by using LocalContainerEntityManagerFactoryBean. The "trick" in that instance was to set up one for each of my persistence units. I also got hung up by using 'name' rather than 'unitName' for @PersistenceContext injection. (Writing this in the hope of saving others pain, as none of the examples I could find set up more than one PU).

              The downside to this is that JBoss scans persistence.xml and maps all the JPA entity beans. Then, Spring does the same thing. A bit inefficient, which is why I wanted to simply use JNDI to grab the EMF's that JBoss already bound.

              That ordering snippit should do the trick. Thanks again!

              Saish