1 Reply Latest reply on Jan 14, 2009 2:49 AM by Andrew Rubinger

    PU Injection across JARs (unrelated DeploymentUnits)

    Andrew Rubinger Master

      Failing is "org.jboss.ejb3.test.hbm.unit.EntityUnitTestCase.testAll".

      Use case is 2 JARs, one declaring a PU and the other has EJBs that want to inject this PU. The JARs are deployed independently (not part of an EAR).

      I've been tinkering with a patch that will enable resolution of PUs no matter where they've been deployed:

      Index: deployers/src/main/java/org/jboss/jpa/resolvers/DefaultPersistenceUnitDependencyResolver.java
      ===================================================================
      --- deployers/src/main/java/org/jboss/jpa/resolvers/DefaultPersistenceUnitDependencyResolver.java (revision 82757)
      +++ deployers/src/main/java/org/jboss/jpa/resolvers/DefaultPersistenceUnitDependencyResolver.java (working copy)
      @@ -21,8 +21,11 @@
       */
       package org.jboss.jpa.resolvers;
      
      +import java.util.Collection;
      +
       import org.jboss.beans.metadata.api.annotations.Inject;
       import org.jboss.deployers.structure.spi.DeploymentUnit;
      +import org.jboss.ejb3.common.deployers.spi.Ejb3DeployerUtils;
       import org.jboss.jpa.javaee.JavaEEModuleInformer;
       import org.jboss.metadata.jpa.spec.PersistenceMetaData;
       import org.jboss.metadata.jpa.spec.PersistenceUnitMetaData;
      @@ -48,6 +51,36 @@
       String unitName = (appName != null ? appName + "/" : "") + modulePath + "#" + persistenceUnitName;
       return "persistence.unit:unitName=" + unitName;
       }
      +
      + /**
      + * Attempts to find the PU with specified persistence unit name
      + * in any of the EJB3 DeploymentUnits registered with the Main
      + * Deployer. Returns the first eligible found.
      + *
      + * @param persistenceUnitName
      + * @return
      + */
      + private String findWithinMainDeployer(String persistenceUnitName)
      + {
      + // Get all deployment units
      + Collection<DeploymentUnit> dus = Ejb3DeployerUtils.getAllEjb3DeploymentUnitsInMainDeployer();
      +
      + // For each DU
      + for(DeploymentUnit du:dus)
      + {
      + // Attempt to find
      + String name = this.findWithinApplication(du, persistenceUnitName);
      +
      + // If found, return
      + if(name!=null)
      + {
      + return name;
      + }
      + }
      +
      + // Not found
      + return null;
      + }
      
       private String findWithinApplication(DeploymentUnit unit, String persistenceUnitName)
       {
      @@ -137,6 +170,8 @@
       String name = findWithinModule(deploymentUnit, persistenceUnitName, true);
       if(name == null)
       name = findWithinApplication(deploymentUnit.getTopLevel(), persistenceUnitName);
      + if(name==null)
      + name = this.findWithinMainDeployer(persistenceUnitName);
       if(name == null)
       throw new IllegalArgumentException("Can't find a persistence unit named '" + persistenceUnitName + "' in " + deploymentUnit);
       return name;


      But the above does not address the issue of dependencies.

      PersistenceUnitDeployments are installed into MC using a bean name that takes the JAR/EAR name into account. Some arbitrary EJB wanting to inject the PU therefore cannot declare a dependency upon the MC bean name, as it doesn't know (or care) which DeploymentUnit is going to supply the PU.

      Thoughts?

      Also it looks like one of our users is running into this: http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4200880

      S,
      ALR

        • 1. Re: PU Injection across JARs (unrelated DeploymentUnits)
          Andrew Rubinger Master

          An update.

          Looks like the dependency issue I illustrated before is handled by the resolver; I must have misread something while debugging/testing. The concept works.

          Carlo has taken the prototype done in my patch and applied InterApplicationPersistenceUnitDependencyResolver in r82833.

          However, this introduces regression in org.jboss.ejb3.test.persistenceunits.unit.MultipleEarTestCase.testBadEar.

          The case is defined by https://jira.jboss.org/jira/browse/JBAS-5043, and shows that InterApplicationPersistenceUnitDependencyResolver is a JBoss-specific extension which is in violation w/ spec:

          "EJB3 Persistence Specification 6.2.2" wrote:
          When referencing a persistence unit using the unitName annotation element or persistence-unit-name deployment descriptor element, the visibility scope of the persistence unit is determined by its point of definition. A persistence unit that is defined at the level of an EJB-JAR, WAR, or application client jar is scoped to that EJB-JAR, WAR, or application jar respectively and is visible to the components defined in that jar or war. A persistence unit that is defined at the level of the EAR is generally visible to all components in the application.


          So "org.jboss.ejb3.test.hbm.unit.EntityUnitTestCase.testAll" is testing a spec violation.

          If we really want to test both cases, we can extract one out into a JBoss-specific test with its own server configs to explicitly set the appropriate PU Resolver. Or we could just Unit Test the cases.

          Which resolver do we want to use as a default? "hbm" and the "persistenceunits.testBadEar" cases are mutually-exclusive.

          S,
          ALR