I'm deploying my EAR on JBoss EAP 7.0.0, which has the following structure:
app.ear
|-- ejb.jar
|-- app.war
|-- lib
|-- hibernate-core-5.2.10.Final.jar
|-- hibernate-hibernate-spatial-5.2.10.Final.jar
|-- hibernate-commons-annotations-5.0.1.Final.jar
|-- META-INF
|-- application.xml
|-- jboss-app.xml
I added a small piece of code in one of my EJB bean that prints org.hibernate.Version.getVersionString() to know which version of Hibernate my application is using and it gives me 5.0.9.Final-readhat-1 instead of something like 5.2.10.Final.
I've read a lot about classloading issues (especially here and here), but after many different trials, I couldn't find a way to make JBoss use the packaged version of Hibernate in my EAR.
It looks like the tag is ignored in EAP 7 ? It seems that the classloading has changed in JBoss AS 7.
Here is the content of my jboss-app.xml:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-app>
<loader-repository>
my.package:archive=app.ear
<loader-repository-config>
java2ParentDelegation=false
</loader-repository-config>
</loader-repository>
</jboss-app>
Is there a way to force JBoss EAP 7 to load the classes from my EAR prior to the bootstrap classloader ?
Note: I also posted this question here.
======================================================= EDIT
I tried with this jboss-deployment-structure.xml:
<jboss-deployment-structure>
<deployment>
<exclude-subsystems>
<subsystem name="org.hibernate" />
</exclude-subsystems>
<exclusions>
<module name="org.hibernate" />
</exclusions>
</deployment>
</jboss-deployment-structure>
During the deployment, I get the following error:
{"WFLYCTL0062: Composite operation failed and was rolled back. Steps that failed:" => {"Operation step-2" => {"WFLYCTL0080: Failed services" => {"jboss.persistenceunit.\"app.ear/ejb.jar#app-ejbPU\"" => "org.jboss.msc.service.StartException in service jboss.persistenceunit.\"app.ear/ejb.jar#app-ejbPU\": java.util.ServiceConfigurationError: org.hibernate.integrator.spi.Integrator: Provider org.hibernate.envers.boot.internal.EnversIntegrator not a subtype
Caused by: java.util.ServiceConfigurationError: org.hibernate.integrator.spi.Integrator: Provider org.hibernate.envers.boot.internal.EnversIntegrator not a subtype"}}}}
JBoss 7 (and WildFly) is using a modules system instead of class loaders to separate different apps and libraries.
Try to disable hibernate in your app: Place a jboss-deployment-stucture.xml file in your EAR's META-INF folder:
<jboss-deployment-structure>
<deployment>
<exclusions>
<module name="org.hibernate" />
</exclusions>
</deployment>
</jboss-deployment-structure>
See: https://docs.jboss.org/author/display/WFLY10/Class+Loading+in+WildFly
Related
I'm working on deploying an EJB project as an EAR in Jboss Wildfly 18. The layout of my ear currently looks like this:
Person.ear->
META-INF->
jboss-deployment-structure.xml
MANIFEST.MF
...
lib->
Common.jar
BugReport.jar
Person-ejb.jar
Person-web.war
with a jboss-deployment-structure.xml like:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="Common.jar" export="TRUE"/>
<module name="BugReport.jar" export="TRUE"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
When I try to start up the server the deployment fails with the following error:
15:00:20,234 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-1) MSC000001: Failed to start service jboss.module.service."deployment.Person.ear".main: org.jboss.msc.service.StartException in service jboss.module.service."deployment.Person.ear".main: WFLYSRV0179: Failed to load module: deployment.Person.ear
at org.jboss.as.server.moduleservice.ModuleLoadService.start(ModuleLoadService.java:116)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1739)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1701)
at org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1559)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1363)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.jboss.modules.ModuleNotFoundException: com.tura.optics.common
at org.jboss.modules.Module.addPaths(Module.java:1266)
at org.jboss.modules.Module.link(Module.java:1622)
at org.jboss.modules.Module.relinkIfNecessary(Module.java:1650)
at org.jboss.modules.ModuleLoader.loadModule(ModuleLoader.java:299)
at org.jboss.modules.ModuleLoader.loadModule(ModuleLoader.java:283)
at org.jboss.as.server.moduleservice.ModuleLoadService.start(ModuleLoadService.java:93)
... 8 more
I have tried defining dependencies via the jboss-deployment-structure.xml and via the MANIFEST.MF with no success. I also tried naming the dependencies with the package name (i.e. com.tura.common) since I have seen both formats used. Still no luck. I'm not quite sure what I'm missing here; it seems like I am following the expected layout. Can anyone help with this?
There is no need of using jboss-deployment-structure.xml as the reference of JAR libraries within the EAR is covered by the Java EE platform specification (JSR 366)
In fact, it should work with your current EAR structure, removing the jboss-deployment-structure.xml
The section EE.8.2.1 Bundled Libraries provides several ways to make JAR libraries available to modules.
You can add a reference to the JAR file with a Class-Path entry in the META-INF/MANIFEST.MF file of the module using the library (not the EAR).
For example, if person-ejb.jar depends on lib/Common.jar and lib/BugReport.jar, you could add:
Class-Path: lib/Common.jar lib/BugReport.jar
in the META-INF/MANIFEST.MF inside de file Person-ejb.jar. Same for Person-web.war
JAR files put in the <library-directory> of the EAR are made available to all modules. And <library-directory> by default is directory lib, so, as you have both Common.jar and BugReport.jar inside the lib directory they should be already available to Person-ejb.jar and Person-web.war.
You can provide a deployment descriptor application.xml in the META-INF directory of the EAR file, and override the <library-directory>. An example application.xml file for your EAR would be:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/application_8.xsd" version="8">
<display-name>Person.ear</display-name>
<module>
<ejb>Person-ejb.jar</ejb>
</module>
<module>
<web>
<web-uri>Person-web.war</web-uri>
<context-root>/person</context-root>
</web>
</module>
<library-directory>lib</library-directory>
</application>
I'm pretty new to JBoss and I'm trying to deploy a .war file on JBoss version 7.0.6 GA.
The .war file is created with the "export as .war file" option in Eclipse.
If I deploy the same .war file on Tomcat, it works without any error.
When I deploy on Jboss, I came across this strange error:
2017-10-20 17:29:26,803 ERROR [stderr] (ServerService Thread Pool -- 106)
Caused by: java.lang.IllegalAccessError: Failed to link
org/apache/log4j/xml/ExtXMLWatchdog (Module "deployment.
[MY_WAR_NAME].war:main" from Service Module Loader): class
org.apache.log4j.xml.ExtXMLWatchdog cannot access its superclass
org.apache.log4j.xml.XMLWatchdog
I'm using the log4j-1.2.17.jar library inside my web app; also, I'm using another custom library named util-log4j.jar.
Inside the log4j-1.2.17.jar is defined the class org.apache.log4j.xml.XMLWatchdog; inside the util-log4j.jar is defined the class
org.apache.log4j.xml.ExtXMLWatchdog.
It seems that the ExtXMLWatchdog cannot see the XMLWatchdog defined in another .jar, but why?
Thank you,
cheers!
Ok, I solved it. Sharing the solution:
inside the .war file, in the WEB-INF folder, I put a file named
jboss-deployment-structure.xml
with this content:
<?xml version="1.0"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<deployment>
<exclusions>
<module name="org.apache.log4j" />
</exclusions>
<exclude-subsystems>
<subsystem name="org.apache.log4j" />
</exclude-subsystems>
</deployment>
It seems that JBoss is equipped with some standard library, but those libraries maybe are loaded by a different ClassLoader (not sure of this, however)
With that file, essentially I'm telling to JBoss to ignore it's own org.apache.log4j library.
The result is that my log4j library is used, and problem is gone!
We want to exclude the modules\system\layers\base\javax\servlet\jstl\api\main\jboss-jstl-api_1.2_spec-1.1.2.Final.jar from our web application deployment (WAR file).
Hence we have the following configuration in src\main\webapp\WEB-INF\jboss-deployment-structure.xml:
<?xml version='1.0' encoding='UTF-8'?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<exclusions>
<module name="javax.servlet.jstl.api"/>
</exclusions>
<dependencies>
<module name="deployment.my-dependencies.jar"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
In the Wildfly log I see that my-dependencies.jar is added as a ModuleDependency. But when searching for javax.servlet.jstl.api I only see this:
2015-04-03 15:22:11,971 DEBUG [org.jboss.modules] (ServerService
Thread Pool -- 12) Module javax.servlet.jstl.api:main defined by local
module loader #1f7c9157 (finder: local module finder #2b29f6e7 (roots:
C:\Users\me\Documents\wildfly-8.2.0.Final\modules,C:\Users\me\Documents\wildfly-8.2.0.Final\modules\system\layers\base))
Why isn't the module excluded?
Update: It seems that modules that are part of a user dependency can not be excluded.
It seems like the mechanism doesn't work as described in the Wildfly documentation. I was not able to exclude that module.
Yep. I was trying to upgrade to Spring Framework to v4.3. It has upped some minimum dependency requirements. One such example is Jackson min version required is 2.6+
Wildfly loads jackson that comes packaged (v2.4.1 in Wildfly 8.2.1), and it won't be excluded using jboss-deployment-structure.xml.
I was trying to see if the upgrade did not involve making changes to the installed server which takes this upgrade out of source control.
I have what is a simple EAR file configured like so:
app.ear
|-- lib/...
|-- META-INF/application.xml
|-- core.jar
| |-- test/MyServiceImpl.class
| `-- META-INF/MANIFEST.MF // Class-Path: core-api.jar
|-- core-api.jar
| `-- test/MyService.class
`-- web.war
`-- META-INF/MANIFEST.MF // Class-Path: core.jar core-api.jar
The application.xml is as follows:
<?xml version="1.0"?>
<application xmlns="http://java.sun.com/xml/ns/javaee" id="app 1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" version="6">
<application-name>MyApp</application-name>
<display-name>My App</display-name>
<module id="mod 1">
<java>core-api.jar</java>
</module>
<module id="mod 2">
<java>core.jar</java>
</module>
<module id="mod 3">
<web>
<web-uri>web.war</web-uri>
<context-root>/</context-root>
</web>
</module>
<library-directory>lib</library-directory>
</application>
When i attempt to deploy the application to the server, I get the following exception:
[*] 00000088 SystemErr R Caused by: org.eclipse.jst.j2ee.commonarchivecore.internal.exception.NoModuleFileException: A file does not exist for module element having uri: core-api.jar
[*] 00000088 SystemErr R at org.eclipse.jst.j2ee.commonarchivecore.internal.impl.ModuleRefImpl.checkType(ModuleRefImpl.java:591)
[*] 00000088 SystemErr R at org.eclipse.jst.j2ee.commonarchivecore.internal.impl.ModuleRefImpl.initModuleFileFromEAR(ModuleRefImpl.java:167)
[*] 00000088 SystemErr R at org.eclipse.jst.j2ee.commonarchivecore.internal.impl.ModuleRefImpl.getModuleFile(ModuleRefImpl.java:120)
[*] 00000088 SystemErr R at org.eclipse.jst.j2ee.commonarchivecore.internal.impl.EARFileImpl.getModuleFile(EARFileImpl.java:165)
[*] 00000088 SystemErr R at org.eclipse.jst.j2ee.commonarchivecore.internal.impl.EARFileImpl.getDeploymentDescriptor(EARFileImpl.java:817)
[*] 00000088 SystemErr R at org.eclipse.jst.j2ee.commonarchivecore.internal.impl.ModuleRefImpl.getDeploymentDescriptor(ModuleRefImpl.java:230)
[*] 00000088 SystemErr R ... 49 more
I am using Websphere Test Environment v8.5.5.0
UPDATE: I suspected maybe the compression algorithm used to zip the ear file may be to blame and it seems as though I was right; unzipping and rezipping the ear file using 7zip caused the deployment to work without errors.
I am using gradle as a build tool which provides it's own mechanism for zipping archives. I have tried setting the entryCompression mode to ZipEntryCompression.STORED without success.
This leads me to a new question:
How can i control the assembly/compression of the ear file to conform with what Websphere expects?
and
What method does gradle use to compress the ear?
UPDATE 2: Looking at the gradle source code, I can see the Zip implementation uses ant's org.apache.tools.zip.ZipOutputStream (1.9.3). has anyone had difficulty with this process before?
UPDATE 3: It seems as if I've been chasing a red herring. I have inspected the file that supposedly deployed correctly and saw that the ear contained an extra folder level above the root of the ear (that is app.ear!app/<root>).
assuming that compression algorithms have nothing to do with it, does anyone have any ideas?
UPDATE 4: Ok, I'm really close, I managed to get the deployment working after inspecting some sample ear files and testing various theories. I did these things and it worked (see Update 5).
Instead of java modules in the application.xml i have ejb modules
I included a basic META-INF/ejb-jar.xml file in the core.jar (even though the spec says you don't need them) as websphere apparently does not like it when it's missing
I removed the core-api.jar module from the application.xml
So i now have the following application.xml:
<?xml version="1.0"?>
<application ...>
<application-name>MyApp</application-name>
<display-name>My App</display-name>
<module id="mod 1">
<ejb>core.jar</ejb>
</module>
<module id="mod 2">
<web>
<web-uri>web.war</web-uri>
<context-root>/</context-root>
</web>
</module>
<library-directory>lib</library-directory>
</application>
One last question: how can i 'deploy' an artifact to an ear project without adding it to the application xml? alternatively, how can i customize the application.xml after the deployments have been resolved?
UPDATE 5: Apologies for the fluctuating state of my question.
Although the application successfully deployed, it did not start up, giving me an error saying that my ejb jars had no ejbs. I have since decided, following the advice I have received and also an answer below, that my spring-based jars are classed as "utility" jars and should live in the lib folder.
I am expecting to use these jars in EJBs in the future and so wish to keep them in the lib folder instead of directly in the war.
this is my final application.xml:
<?xml version="1.0"?>
<application ...>
<application-name>MyApp</application-name>
<display-name>My App</display-name>
<module>
<web>
<web-uri>web.war</web-uri>
<context-root>/</context-root>
</web>
</module>
<library-directory>lib</library-directory>
</application>
Thank you for your time and patience.
I can see by your application.xml header that you're using JavaEE 6 packaging and you also mentioned you're using WebSphere 8.5.5 so follow some ear packaging information.
You do not need the application.xml at all if you're using annotated EJB 3.x and then follow the standard packaging convention:
app.ear
|-- lib/$UTILITY_JARS_HERE
|-- EJB.jars
|-- web.war
Notice that this is the default packaging for Java EE 6 structures and following this all utility jars that you place inside the lib directory will be available to both the EJBs and WARs you have there so you should use this directory only if your utility jars are required by both EJBs and web applications. If your utility jar is used only by your web application then you should package them inside the standard WEB-INF/lib folder in you war package only.
Now if you're using EJBs 2.x together with your packaging than you'll need to have the application.xml and declare your ejbs and war, you should keep the recommended approach of leaving the utilities jars inside the lib folder and the ones required only by the web layer inside the lib folder of the war package.
If for any reason you want to keep your utilities jars at the root level or the ear you can use the approach of declaring them at the Manifest for the EAR but than you DON'T and can't declare them again in the manifest for the war package. All declared jars on the ear manifest will be automatically visible by the classloader of the war file and EJBs.
The javaEE 6 specification Chapter 8 "Application Assembly and Deployment" has the complete explanation on this subject. You can download the document here.
I am trying to connect my j2ee application with SAP using ABAP function calls. When I run it as a single class in eclipse with hot coded values , it works fine. When I try to run it in JBoss server , where I am getting some values from my front end and passing it to my java class which is the same class I referred before, it shows this following exception
java.lang.NoClassDefFoundError: com/sap/conn/jco/JCoException
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.privateGetPublicMethods(Unknown Source)
at java.lang.Class.getMethods(Unknown Source)
at org.jboss.aop.ClassContainer.createMethodMap(ClassContainer.java:182)
09:35:42,326 INFO [EARDeployer] Started J2EE application: file:/F:/jboss/jboss- 4.2.3.GA/server/default/deploy/MPCS.ear
09:35:42,326 ERROR [URLDeploymentScanner] Incomplete Deployment listing:
--- MBeans waiting for other MBeans ---
ObjectName: jboss.j2ee:service=EJB3,module=MPCS.jar
State: FAILED
Reason: java.lang.NoClassDefFoundError: com/sap/conn/jco/JCoException
--- MBEANS THAT ARE THE ROOT CAUSE OF THE PROBLEM ---
ObjectName: jboss.j2ee:service=EJB3,module=MPCS.jar
State: FAILED
Reason: java.lang.NoClassDefFoundError: com/sap/conn/jco/JCoException
I have my sapjco3.jar in F:/jar where I also have ejb3-persistence.jar, jboss-ejb3x.jar etc and they are properly recognized. I have added the jar in build path also. But nothing helps.
I had a similar problem with the NoClassDefFoundError in JBoss EAP 6.1 when using classes from sapjco3.jar in an EJB (annotated with #Singleton and #Startup).
Besides that I also received an error saying that the native library was already loaded in another classloader when republishing to EAP or restarting the deployed module.
My solution to both problems was to include sapjco3.jar as a global JBoss module.
Step 1
I created the following structure inside EAPS's \modules folder:
com
--> sap
--> conn
--> jco
--> main
--> module.xml
--> sapjco3.jar
The contents of module.xml:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="com.sap.conn.jco">
<resources>
<resource-root path="sapjco3.jar"/>
</resources>
</module>
Step 2
Adding the module as a global module in standalone.xml:
<subsystem xmlns="urn:jboss:domain:ee:1.1">
...
<global-modules>
<module name="com.sap.conn.jco" />
</global-modules>
...
</subsystem>
Step 3
Create or edit file jboss-deployment-structure.xml inside EJB projects META-INF to contain the module.
My file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="com.sap.conn.jco" export="TRUE" />
</dependencies>
</deployment>
</jboss-deployment-structure>
Step 4
Configure Maven dependency as scope provided, so that we can work with sapjco3.jar inside the workspace but not have it inside the deployment.
<dependency>
<groupId>com.sap.conn.jco</groupId>
<artifactId>sapjco3</artifactId>
<version>3.0.10</version>
<scope>provided</scope>
</dependency>
That is what I recall so far to make it work, maybe this is helpful for you or anybody else.
Besides that, could be necessary to add the dependency to the javax.api if are you using a newer version of sapjco3. This dependency is necessary to load the crypto library from Java.
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.3" name="com.sap.conn.jco">
<resources>
<resource-root path="sapjco3.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
</dependencies>
</module>