This is what I would like to achieve:
1 ear-package: all.ear
The ear-package contains two war's (A.war, B.war in the root of the ear)
The ear-package contains 1 self-made jar C and a lot of third party jars (under APP-INF\lib)
This package needs to be deployed on JBoss WildFly 8.2.1
I'm using maven's ear plugin (maven-ear-plugin, version 2.10.1). My configuration in the pom looks like this (this is the 'parent'-project which combines three other projects):
<configuration>
<finalName>All</finalName>
<defaultLibBundleDir>APP-INF/lib</defaultLibBundleDir>
<includeLibInApplicationXml>true</includeLibInApplicationXml>
<version>6</version>
<displayName>All</displayName>
<modules>
<jarModule>
<groupId>project</groupId>
<artifactId>C</artifactId>
<bundleFileName>C.jar</bundleFileName>
<uri>APP-INF/lib/C.jar</uri>
<bundleDir>APP-INF/lib</bundleDir>
</jarModule>
<webModule>
<groupId>project</groupId>
<artifactId>A</artifactId>
<uri>A.war</uri>
<bundleFileName>A.war</bundleFileName>
<contextRoot>/a</contextRoot>
<bundleDir>/</bundleDir>
</webModule>
<webModule>
<groupId>project</groupId>
<artifactId>B</artifactId>
<uri>B.war</uri>
<bundleFileName>B.war</bundleFileName>
<contextRoot>/b</contextRoot>
<bundleDir>/</bundleDir>
</webModule>
</modules>
<archive>
<manifestEntries>
<Implementation-Version>1.0</Implementation-Version>
</manifestEntries>
</archive>
</configuration>
My META.INF/application.xml file loos like this:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="6"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/application_6.xsd">
<display-name>All</display-name>
<initialize-in-order>true</initialize-in-order>
<module>
<java>APP-INF/lib/C.jar</java>
</module>
<module>
<web>
<web-uri>B.war</web-uri>
<context-root>b</context-root>
</web>
</module>
<module>
<web>
<web-uri>A.war</web-uri>
<context-root>a</context-root>
</web>
</module>
<library-directory>APP-INF/lib</library-directory>
</application>
The ear package is made. All third-party jars are under APP-INF/lib, but C.jar is in the root directory.
I have messed around a lot and got different errors when trying to upload the package to JBoss:
Caused by: org.jboss.as.server.deployment.DeploymentUnitProcessingException: JBAS016703: Module may not be a child of the EAR's library directory. Library directory: APP-INF/lib, module file name: APP-INF/lib/[SomeThirthPartyLib].jar"
When I placed every library under root (don't use APP-INF), I've got a ClassNotFoundError for B.war (can't find the classes from C.jar).
I've already tried adding the 'jboss'-tags to the maven-ear-plugin (configuration), but those are not supported for JBoss 8+.
I want a .ear package which can be deployed in JBoss and contains 2 wars and 1 jar, which is referenced from both the wars.
What am I missing? (specific Manifest configuration? specific pom.xml settings for A, B or C? JBoss settings? ...?)
solution for the error "WFLYEE0097: Module may not be a child
of the EAR's library directory": the error is becuase of tag APP-INF/lib in application.xml. If library jars are inside EAR/lib then application.xml will work fine Since it is under EAR/APP-INF/lib, jboss or wildfly will not understand this(appication.xml) deployment descriptor. So use jboss-app.xml which wildfly understands even if the library directory is different. Solution : Simply copy complete content of application.xml to jboss-app.xml and place it META-INF folder (Also make sure to delete application.xml file or not making this get generated through pom.xml)
According to the JAVA EE specs, the container will not scan any deployment descriptors of any jar that is included in the library directory of the ear.
But what I presume you want to do is have access from the WARs to those ejb's you declared in C.jar. Again, according to specs, any ejb-jar sitting in an ear is visible to any other module:
Components in the web container may have access to the following classes and resources. Portable applications must not depend on having or not having access to these classes or resources.
•The classes and resources accessible to any other web modules included in the same ear file, as described above.
•The content of any EJB jar files included in the same ear file.
So, just put the C.jar anywhere else but in the lib directory and you're fine.
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>
Migrating an existing project to maven and wildfly and had to move some files around creating the following situation.
core.jar
ejb1.jar
ejb2.jar
With the ejb-jar.xml for ejb1.jar having the following:
<ejb-jar>
<enterprise-beans>
<session id="Value">
..
<home>path.to.ejb1Home</home>
<remote>path.to.ejb1</remote>
...
The classes referenced in the home and remote tags have moved to be inside core.jar
Meanwhile ejb2.jar has dependencies on other parts of core.jar.
What looked like the easiest resolution was to create a global module and place core.jar in it, creating the appropriate module.xml and entry in standalone.sh to make it accessible to all deployments.
module.xml
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="path.to">
<resources>
<resource-root path="core-1.0.jar"/>
</resources>
<dependencies>
</dependencies>
</module>
With this setup, ejb2.jar deploys as expected but ejb1.jar throws the following error:
Caused by: java.lang.NoClassDefFoundError: Failed to link path.to.ejb1
(Module "path.to" from local module loader #4c40b76e (finder: local
module finder #2ea6137 (roots: /opt/wildfly/modules,
/opt/wildfly/modules/system/layers/base))): javax/ejb/EJBObject
You should carefully think about your requirement. Usually, you don't need to provide common resources, especially application interfaces, as module, especially as global module. Choose the right solution for your requirements, not a solutions that looks easy at first sight without knowing the implications.
I would recommend these possibilities in the order given (see the Class Loading in Wildfly Documentation for more information):
Reconsider your requirement for different EARs. Provide the core jar as library with your EAR.
Even with more than one EAR: provide the core.jar as library. This is no redundancy, this is just separation.
Consider not using a global module. Just install your custom module. Provide a jboss-deployment-structure.xml file, adding this module as additional dependency. If the module contains annotated classes or interfaces, which should be considered upon deployment, set the attribute annotations=true with the module dependency configuration.
Add a global module to your configuration file. Probably you can even use the `annotations' property, but this is something I don't know and I didn't check.
An example for the jboss-deployment-structure.xml file:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.3">
<ear-subdeployments-isolated>false</ear-subdeployments-isolated>
<deployment>
<dependencies>
<module name="my.custom.module" export="true" annotations="true"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
EDIT:
When installing modules, don't forget to provide transitive module dependencies to other modules your own module depends on. User your module.xml file to do so. In your case, you probably need at least a dependency to the javax.ejb.api module.
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!
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.
When I deploy EAR project, I noted that same EJBs appear twice - in WAR and JAR(EJB) modules. Where can be problem?
I build project using Maven. And didn't explicitly define any ejb-jar.xml.
In pom.xml of EJB project I added maven-ejb-plugin:
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<version>2.3</version>
<configuration>
<ejbVersion>3.0</ejbVersion>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
<generateClient>true</generateClient>
<clientExcludes>
<clientExclude>**/core/</clientExclude>
<clientExclude>**/utils/</clientExclude>
</clientExcludes>
</configuration>
</plugin>
And from client I refer to generated EJB-client:
<dependency>
<groupId>orgstructure</groupId>
<artifactId>orgstructure-ejb</artifactId>
<version>1.0.4-SNAPSHOT</version>
<type>ejb-client</type>
<scope>compile</scope>
</dependency>
P.S. I deploy project to WebSphere 8.
UPDATE
Generated .ear file have standard layout:
-project.ear
--web-module.war
--ejb-module.jar
--lib
--META-INF
And generated applcation.xml:
<display-name>orgstructure-ear</display-name>
<module>
<web>
<web-uri>orgstructure-web-1.0.3.war</web-uri>
<context-root>/orgstructure</context-root>
</web>
</module>
<module>
<ejb>orgstructure-ejb-1.0.3.jar</ejb>
</module>
<library-directory>lib</library-directory>
Are you building (except for the EJB and web modules) a standalone Java application that is going to use your EJB? I'm guessing not, since you don't mention it anywhere.
If I'm guessing right, don't generate the EJB client. Remove the option
<generateClient>true</generateClient>
from your POM, and all configuration related to it.
An EJB client in this context means an application deployed outside the application server that wants to use your EJBs directly and therefore it needs a client jar to handle remote calls to the beans on the server.
If I'm guessing wrong, you still should not include a dependency to your a client jar in your web archive, Java EE web applications connect to EJBs using built-in app server mechanisms, not generated client stubs. In that case, remove the option
<type>ejb-client</type>
from your WAR's dependency.