2 Replies Latest reply on Jun 25, 2012 8:13 AM by Craig Ringer

    Excluding automatic persistence provider dependencies?

    Craig Ringer Newbie

      Hi all

       

      I'm working on an integration test for https://github.com/ringerc/as7-eclipselink-integration that doesn't require the user to manually install the modules before running the tests. It's tricker than I expected, and I'm hoping I'm missing something obvious, as I want to reduce the needed instructions for https://community.jboss.org/wiki/HowToUseEclipseLinkWithAS7 down to a couple of lines using a simple integration library.

       

      The library works, I just can't get the integration tests to work properly because JBoss AS 7 is being a little too clever.

       

      I want to produce a self-contained deployment (from ShrinkWrap, but that doesn't matter for this purpose) that includes EclipseLink and my integration code so it can be tested with a simple "mvn integration-test" on a bare AS7 install. It shouldn't be necessary to copy build output to $JBOSS_HOME/modules and restart the server before running the integration tests! Most importantly, it's important not to modify the server install or leave modules installed once the tests complete.

       

      To do this I need to be able to get one of these options working:

       

      1. Bundle an org.eclipselink.persistence:main module within my ShrinkWrap war or jar deployment for the Arquillian tests;
      2. Exclude JBoss AS 7's automatically added dependency on org.eclipselink.persistence:main and bundle EclipseLink in /WEB-INF/lib/, old-school style; or
      3. Get Arquillian to temporarily add extra modules and remove them when testing is done, in a way that won't require server restarts and won't leave the modules lying around if testing is aborted by the user part-way through.

       

      I haven't been able to find out if it's possible to provide conventional AS7 modules within a deployment - modules with a module.xml, etc. I doubt it. I know you can refer to deployments as modules using the deployment.[deployment-archive] syntax, but that won't let me define a module named "org.eclipselink.persistence" to satisfy the dependency JBoss is automatically adding when it sees             <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> in persistence.xml .

       

      I haven't seen any sign of support for #3 in Arquillian. I could probably hack something together with maven-failsafe-plugin and maven-resource-plugin, but it'd be fragile at best.

       

      That leaves me with the second option, which should be as simple as adding EclipseLink to /WEB-INF/lib and adding a /WEB-INF/jboss-deployment-structure.xml like:

       

      <?xml version="1.0" encoding="UTF-8"?>
      <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
        <deployment>
          <exclusions>
             <!-- AS7 will add a dependency on EclipseLink if we don't tell it not to.
                  Since we're bundling it in our jar, we really don't want it to. -->
             <module name="org.eclipse.persistence"/>
          </exclusions>
        </deployment>
      </jboss-deployment-structure>
      

       

      ... however this appears not to actually exclude the dependency Hibernate has added automatically. Deployment still fails with org.jboss.modules.ModuleNotFoundException: Module org.eclipse.persistence:main is not found in local module loader:

       

       

      02:18:04,988 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-4) MSC00001: Failed to start service jboss.deployment.unit."4ab4b7d7-4f04-463f-841c-951420217cd7.war".INSTALL: org.jboss.msc.service.StartException in service jboss.deployment.unit."4ab4b7d7-4f04-463f-841c-951420217cd7.war".INSTALL: Failed to process phase INSTALL of deployment "4ab4b7d7-4f04-463f-841c-951420217cd7.war"
                at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:119) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final]
                at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811) [jboss-msc-1.0.2.GA.jar:1.0.2.GA]
                at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746) [jboss-msc-1.0.2.GA.jar:1.0.2.GA]
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) [rt.jar:1.7.0_03-icedtea]
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) [rt.jar:1.7.0_03-icedtea]
                at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_03-icedtea]
      Caused by: org.jboss.as.server.deployment.DeploymentUnitProcessingException: JBAS011434: Persistence provider module load error org.eclipse.persistence (class org.eclipse.persistence.jpa.PersistenceProvider)
                at org.jboss.as.jpa.processor.PersistenceUnitDeploymentProcessor.lookupProvider(PersistenceUnitDeploymentProcessor.java:549)
                at org.jboss.as.jpa.processor.PersistenceUnitDeploymentProcessor.deployPersistenceUnit(PersistenceUnitDeploymentProcessor.java:295)
                at org.jboss.as.jpa.processor.PersistenceUnitDeploymentProcessor.addPuService(PersistenceUnitDeploymentProcessor.java:258)
                at org.jboss.as.jpa.processor.PersistenceUnitDeploymentProcessor.handleWarDeployment(PersistenceUnitDeploymentProcessor.java:194)
                at org.jboss.as.jpa.processor.PersistenceUnitDeploymentProcessor.deploy(PersistenceUnitDeploymentProcessor.java:118)
                at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:113) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final]
                ... 5 more
      Caused by: org.jboss.modules.ModuleNotFoundException: Module org.eclipse.persistence:main is not found in local module loader @15d82219 (roots: /home/craig/java/jboss-as-7.1.1.Final/modules)
                at org.jboss.modules.LocalModuleLoader.findModule(LocalModuleLoader.java:126)
                at org.jboss.modules.ModuleLoader.loadModuleLocal(ModuleLoader.java:275)
                at org.jboss.modules.ModuleLoader.preloadModule(ModuleLoader.java:222)
                at org.jboss.modules.LocalModuleLoader.preloadModule(LocalModuleLoader.java:94)
                at org.jboss.modules.ModuleLoader.loadModule(ModuleLoader.java:204)
                at org.jboss.as.jpa.persistenceprovider.PersistenceProviderLoader.loadProviderModuleByName(PersistenceProviderLoader.java:59)
                at org.jboss.as.jpa.processor.PersistenceUnitDeploymentProcessor.lookupProvider(PersistenceUnitDeploymentProcessor.java:546)          ... 10 more
      

       

      if no EclipseLink module has been installed, even if EclipseLink is present in WEB-INF/lib .

       

      Even stranger, if I add a module for EclipseLink but leave the exclusion in place, the error changes to one indicating that EclipseLink has been excluded from visibilty to my deployment and its classloader, so eclipselink gets activated as a persistence provider, but then can't even load its own classes from my classloader!.

       

      Internal Exception: java.lang.ClassNotFoundException: org.eclipse.persistence.platform.server.jboss.JBossPlatform from [Module "deployment.b55d1046-0719-4f9e-88a7-92dc6d21412f.war:main" from Service Module Loader]
                at org.eclipse.persistence.exceptions.EntityManagerSetupException.predeployFailed(EntityManagerSetupException.java:221)
                ... 10 more
      Caused by: Exception [EclipseLink-28006] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.EntityManagerSetupException
      Exception Description: ClassNotFound: [org.eclipse.persistence.platform.server.jboss.JBossPlatform] specified in [eclipselink.target-server] property.
      Internal Exception: java.lang.ClassNotFoundException: org.eclipse.persistence.platform.server.jboss.JBossPlatform from [Module "deployment.b55d1046-0719-4f9e-88a7-92dc6d21412f.war:main" from Service Module Loader]
                at org.eclipse.persistence.exceptions.EntityManagerSetupException.classNotFoundForProperty(EntityManagerSetupException.java:133)
                at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.findClassForProperty(EntityManagerSetupImpl.java:966)
                at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.updateServerPlatform(EntityManagerSetupImpl.java:736)
                at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:1287)
                ... 8 more
      Caused by: java.lang.ClassNotFoundException: org.eclipse.persistence.platform.server.jboss.JBossPlatform from [Module "deployment.b55d1046-0719-4f9e-88a7-92dc6d21412f.war:main" from Service Module Loader]
                at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190)
                at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:468)
                at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:456)
                at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
                at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:120)
                at java.lang.Class.forName0(Native Method) [rt.jar:1.7.0_03-icedtea]
                at java.lang.Class.forName(Class.java:264) [rt.jar:1.7.0_03-icedtea]
                at org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(PrivilegedAccessHelper.java:124)
                at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.findClass(EntityManagerSetupImpl.java:956)
                at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.findClassForProperty(EntityManagerSetupImpl.java:962)
                ... 10 more
      

       

      If I remove the exclusion from jboss-deployment-structure.xml and have org.eclipse.persistence installed as a module, all works as expected - but that requires users to install a module before the integration tests can pass, which is kind of backwards when I generate that module.

       

      This looks like a plain-and-simple bug, that exclusions in jboss-deployment-structure.xml should prevent the automatic activation of that persistence provider module too. JBoss AS 7 should fall back to the classic behaviour of getting the persistence provider from WEB-INF/lib, and certainly shouldn't be doing this excluded-but-not-really trick.

       

      UPDATE: Bug filed as https://issues.jboss.org/browse/AS7-5064 .