maven - not copying project jar outside /lib while EAR packaging - maven

This is happening while packaging the EAR
My pom.xml is packaging the ear file where it should include projectA.jar file and projectB.war outside the /lib folder. Apparently, projectA.jar file is going inside the /lib folder which is not supposed to be. I have my application.xml which tells that these two projects should be outside the lib.
Question : how do i instruct maven not to bundle projectA.jar inside the /lib folder but to bundle it outside the /lib folder?.
My EAR structure should be:
MyWebEAR
\lib
\META-INF
projectA.jar
ProjectB.war
Below is my pom.
<dependencies>
<dependency>
<groupId>com.xxx.sms</groupId>
<artifactId>projectA</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.xxx</groupId>
<artifactId>projectB</artifactId>
<version>1.0-SNAPSHOT</version>
<type>war</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<earSourceDirectory>${basedir}</earSourceDirectory>
<earSourceIncludes>META-INF/*</earSourceIncludes>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
<generateApplicationXml>false</generateApplicationXml>
<applicationXML>${basedir}/META-INF/application.xml</applicationXML>
</configuration>
</plugin>
</plugins>
<finalName>MyWebEAR</finalName>
</build>
Thanks for your time.

You need to specifically define a jarModule configuration in the modules section of your maven-ear-plugin configuration for the projectA dependency and explicitly set where you want the jar placed.
So your POM would be:
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<earSourceDirectory>${basedir}</earSourceDirectory>
<earSourceIncludes>META-INF/*</earSourceIncludes>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
<generateApplicationXml>false</generateApplicationXml>
<applicationXML>${basedir}/META-INF/application.xml</applicationXML>
<modules>
<jarModule>
<groupId>com.xxx.sms</groupId>
<artifactId>projectA</artifactId>
<bundleDir>/</bundleDir>
</jarModule>
</modules>
</configuration>
</plugin>
The value (/) in the bundleDir tells the maven-ear-plugin to place projectA's jar in the root folder of the ear instead of the default location of lib.
You can see details on this in the plugins documentation here:
http://maven.apache.org/plugins/maven-ear-plugin/examples/customizing-module-location.html

I had the same problem in my project.
In my case, I was using an MDB so it was needed to be declared as <**ejbModule**> instead of jarModule. I also had to declare my dependency as of type ejb to be picked up Jboss (6.4):
<dependency>
<groupId>ab.cd</groupId>
<artifactId>mdb-publisher</artifactId>
<version>xxx-SNAPSHOT</version>
<type>**ejb**</type>
</dependency>

Related

Maven EAR plugin: Generated EAR file does not contain WAR or EJB or RAR modules

I've been using the EAR plugin to package a WAR, EJB & RAR module, however, while they all package successfully when i run mvn clean package, I notice the following gets output in the target directory.
application.xml (generated application.xml)
my-application-ear-1.0-SNAPSHOT (directory with correctly packaged WAR, EJB & RAR dependencies, META-INF with generated application.xml and additional resources from the EAR project)
my-application-ear-1.0-SNAPSHOT.ear (9kb .ear file that only has the META-INF with the generated application.xml & additional resources from the EAR project)
None of the modules are packaged in the final EAR file.
Here is the <build> node of the EAR project's POM.
<build>
<plugins>
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<finalName>my-application-ear</finalName>
<version>7</version>
<earSourceDirectory>src/main/application</earSourceDirectory>
<packagingIncludes>**/*</packagingIncludes>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<filtering>false</filtering>
<packagingIncludes>Default_HTTP_WC/**,Default_IIOP_WC/**,Default_JMS_WC/**,META-INF/**,</packagingIncludes>
<modules>
<ejbModule>
<groupId>com.abc.def</groupId>
<artifactId>ejb-module</artifactId>
<bundleDir>/</bundleDir>
<bundleFileName>ejbModule.jar</bundleFileName>
<moduleId>EjbModule_1</moduleId>
</ejbModule>
<rarModule>
<groupId>com.abc.def</groupId>
<artifactId>rar-module</artifactId>
<bundleDir>/</bundleDir>
<bundleFileName>RARModule</bundleFileName>
<uri>/RARModule.rar</uri>
<unpack>true</unpack>
<moduleId>RARModule_1</moduleId>
</rarModule>
<webModule>
<groupId>com.abc.def</groupId>
<artifactId>my-web-app</artifactId>
<uri>/WebApplication.war</uri>
<bundleDir>/</bundleDir>
<bundleFileName>WebApplication.war</bundleFileName>
<contextRoot>/foo</contextRoot>
<moduleId>WebModule_1</moduleId>
</webModule>
</modules>
</configuration>
<goals>
<goal>ear</goal>
</goals>
</plugin>
</plugins>
Am i missing something? Any assistance is appreciated.
I figured out my problem, I had completely overlooked the use of <packagingIncludes> from an earlier iteration. removed it and its fine.

Maven - error while deploying ear to jboss 6.x - ClassFormatError

I have a maven project where i am package to EAR file and including all dependencies in /lib folder. But while deploying EAR file i am getting below 2 errors in jboss.
1)java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/jms/JMSException
For above error i learnt that i need to remove j2ee related jar files going inside the /lib folder.
2)java.lang.ClassCastException: com.xx.sms.ejb.ws.xxx.CoordinatorServiceBean cannot be cast to javax.servlet.Servlet
And this error i believe i should remove javax.servlet related jar files from /lib folder. Because this may be already provided by jboss servletContainer and you should exclude from your /lib folder.
I am new to maven world and somehow i managed to create a EAR.
Let me know how to exclude j2ee related and servlet related jar files during packing EAR.
Below is my pom.xml
<dependencies>
<dependency>
<groupId>com.xxx.sms</groupId>
<artifactId>CoordinatorBeans</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.xxx</groupId>
<artifactId>CoordinatorWeb</artifactId>
<version>1.0-SNAPSHOT</version>
<type>war</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<earSourceDirectory>${basedir}</earSourceDirectory>
<earSourceIncludes>META-INF/*</earSourceIncludes>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
<generateApplicationXml>false</generateApplicationXml>
<applicationXML>${basedir}/META-INF/application.xml</applicationXML>
<modules>
<jarModule>
<groupId>com.xxx.sms</groupId>
<artifactId>CoordinatorBeans</artifactId>
<bundleDir>/</bundleDir>
<bundleFileName>CoordinatorBeans.jar</bundleFileName>
</jarModule>
<webModule>
<groupId>com.xxx</groupId>
<artifactId>CoordinatorWeb</artifactId>
<bundleDir>/</bundleDir>
<bundleFileName>CoordinatorWeb.war</bundleFileName>
</webModule>
</modules>
</configuration>
</plugin>
</plugins>
<finalName>CoordinatorApp</finalName>
</build>
After adding exclusions for below dependency it worked.
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>2.2</version>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>

Rename profile activated dependency when building executable JAR

I am fairly new to working with Maven to build my Java projects, and have run into a situation I don't know how to handle.
I have a Java application that has 3 dependencies, let's call them a, b, and c. However, c will be a different artifact depending on the platform we are building on, so I've used profiles to achieve this. Here is a snippet from my pom.xml:
<profiles>
<profile>
<id>win32</id>
<activation>
<os>
<family>windows</family>
<arch>x86</arch>
</os>
</activation>
<dependencies>
<dependency>
<groupId>com.seanbright</groupId>
<artifactId>c-win32-x86</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>win64</id>
<activation>
<os>
<family>windows</family>
<arch>amd64</arch>
</os>
</activation>
<dependencies>
<dependency>
<groupId>com.seanbright</groupId>
<artifactId>c-win32-x86_64</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</profile>
</profiles>
The a and b artifacts are listed as dependencies at the POM level as they are platform agnostic and aren't activated along with the profile. They aren't shown here for the sake of brevity.
Now I want to build an executable JAR of my project, and include a, b, and c in a lib/ directory along side the generated JAR from my code, so I would end up with something like this:
target/my-project-1.0.0.jar
target/lib/a-1.0.0.jar
target/lib/b-1.0.0.jar
target/lib/c-1.0.0.jar
The manifest in my-project-1.0.0.jar will have the appropriate classpath so that it can be double clicked on and the application will launch. I use the dependency:copy-dependencies and jar:jar goals to make all of this work:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-dependencies</id>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<mainClass>com.seanbright.myproject.Launch</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
And... it works. The only problem, is that c is copied to the lib/ directory (and added to the Class-Path in the manifest) as c-win32-x86-1.0.0.jar or c-win32-x86_64-1.0.0.jar depending on the active profile, and I want it to end up as c-1.0.0.jar instead.
Using dependency:copy with destFileName instead of dependency:copy-dependencies results in the correct filename, but the entry in the Class-Path still refers to the "fully qualified" artifact name (i.e. lib/c-win32-x86-1.0.0.jar).
Am I going about this the wrong way? Is there an easier way to accomplish what I am trying to do?
The Set Up The Classpath:Altering The Classpath: Using a Custom Classpath Format told us as the following: -
At times, you may have dependency archives in a custom format within your own archive, one that doesn't conform to any of the above classpath layouts. If you wish to define a custom layout for dependency archives within your archive's manifest classpath, try using the <classpathLayoutType> element with a value of 'custom', along with the <customClasspathLayout> element, like this:
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathLayoutType>custom</classpathLayoutType>
<customClasspathLayout>WEB-INF/lib/$${artifact.groupIdPath}/$${artifact.artifactId}-$${artifact.version}$${dashClassifier?}.$${artifact.extension}</customClasspathLayout>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
...
<dependencies>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
...
</project>
This classpath layout is a little more involved than the previous examples. To understand how the value of the <customClasspathLayout> configuration is interpreted, it's useful to understand the rules applied when resolving expressions within the value:
If present, trim off the prefix 'artifact.' from the expression.
Attempt to resolve the expression as a reference to the Artifact using reflection (eg. 'artifactId' becomes a reference to the method 'getArtifactId()').
Attempt to resolve the expression as a reference to the ArtifactHandler of the current Artifact, again using reflection (eg. 'extension' becomes a reference to the method 'getExtension()').
Attempt to resolve the expression as a key in the special-case Properties instance, which contains the following mappings:
'dashClassifier': If the Artifact has a classifier, this will be '- $artifact.classifier', otherwise this is an empty string.
'dashClassifier?': This is a synonym of 'dashClassifier'.
'groupIdPath': This is the equivalent of '$artifact.groupId', with all '.'characters replaced by '/'.
The manifest classpath produced using the above configuration would look like this:
Class-Path: WEB-INF/lib/org/codehaus/plexus/plexus-utils-1.1.jar WEB-INF/lib/commons-lang/commons-lang-2.1.jar
I hope this may help.

How to make the Maven EAR Plugin automatically manage the classpath for dependencies?

I started using the maven ear plugin about 12 months ago and want to find out if there are any alternatives. One of the benefits of Maven is the dependency management however you seem to almost completely lost this with the ear plugin. It builds all the dependant jar's into the ear but won't actually put any of them on the classpath with out adding the configuration below:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.4</version>
<configuration>
<version>6</version>
<modules>
<ejbModule>
<groupId>com.mycompany.app</groupId>
<artifactId>MyApplication-ejb</artifactId>
</ejbModule>
<jarModule>
<groupId>axis</groupId>
<artifactId>axis</artifactId>
<bundleDir>lib</bundleDir>
</jarModule>
<jarModule>
<groupId>commons-discovery</groupId>
<artifactId>commons-discovery</artifactId>
<bundleDir>lib</bundleDir>
</jarModule>
<jarModule>
<groupId>axis</groupId>
<artifactId>axis-wsdl4j</artifactId>
<bundleDir>lib</bundleDir>
</jarModule>
</modules>
</configuration>
</plugin>
Am I missing something does a more recent version of the plugin eliminate the need for this, is there an alternative that manages this for you? I can't believe each time I add a dependency to a module I need to add it to the ear pom configuration. The most frustrating thing is even if I remember to add a dependant library to the above configuration, if that is in turn dependent on something else (as was the case with axis) I am only finding out when I deploy the ear.
First you should have a separate module for the ear (and of course ear ) which looks like the following:
root
+-- client
! +--- pom.xml
+-- service
! +--- pom.xml
+-- ear
+--- pom.xml
Second you should update the version of the ear plugin, cause the current version is 2.6. Furthermore define your parts as dependencies
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.5</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>webgui</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>service</artifactId>
<version>${project.version}</version>
<type>ejb</type>
</dependency>
</dependencies>
The configuration you are using is intended for supplemental 3rd party libs which should be packaged.
In addition to the answer of khmarbaise I want to note that in order for your EJB Module to be able to access the libraries you have to configure it to include the dependencies inside the META-INF/MANIFEST.MF like this:
<plugin>
<artifactId>maven-ejb-plugin</artifactId>
...
<configuration>
...
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
...
</plugin>

Custom jboss-app.xml using Maven

I declared a custom jboss-app.xml in my pom.xml, but the plugin is generating an internal and empty jboss-app.xml file into ear/META-INF.
I created my pom.xml based on this article with the following definition:
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<data-sources>
<data-source>${artifactId}/src/main/resources/mytest-ds.xml</data-source>
</data-sources>
<jboss>${artifactId}/src/main/resources/jboss-app.xml</jboss>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
<modules>
<ejbModule>
<groupId>com.testproject</groupId>
<artifactId>ejb-project</artifactId>
</ejbModule>
</modules>
</configuration>
</plugin>
But, I can't handle my custom jboss-app.xml. A new is empty descriptor (without defined ejbs) is generated every time.
You should be able to simply include your jboss-app.xml in your source tree and Maven will pull it in.
Your project directory structure for the maven-ear-plugin should look like:
|-- pom.xml
`-- src
`-- main
`-- application
`-- META-INF
|-- application.xml
`-- jboss-app.xml
Then just run mvn package to create your EAR. Assuming the packaging for your pom.xml is 'ear' it will pull jboss-app.xml into your resulting ear.
Also, I believe your <datasources>...</datasources> configuration needs to be within the <jboss>...</jboss> tags.
See also: http://maven.40175.n5.nabble.com/Deployment-of-the-jboss-app-xml-file-td45009.html
From the docs, it looks like jboss tag triggers the generation of jboss-app.xml. How about omitting this tag and generating the ear?
Alternative would be to pull datasources via application.xml as described here. But as <jarModule> requires are full-blown maven artifact, that is longer way (perhaps for application servers other than JBoss):
• project/ds/pom.xml:
<artifactId>project-ds</artifactId>
<packaging>jar</packaging>
<name>My DataSource</name>
• project/ds/src/main/resources/my-ds.xml:
<datasources>
<local-tx-datasource>
...
• project/ear/pom.xml (assuming that driver is also packaged in EAR):
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>project-ds</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>project-war</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>net.sourceforge.jtds</groupId>
<artifactId>jtds</artifactId>
<version>${jtds.driver.version}</version>
</dependency>
</dependencies>
...
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<modules>
<jarModule>
<groupId>net.sourceforge.jtds</groupId>
<artifactId>jtds</artifactId>
<includeInApplicationXml>true</includeInApplicationXml>
</jarModule>
<jarModule>
<groupId>${project.groupId}</groupId>
<artifactId>project-ds</artifactId>
<unpack>true</unpack>
<uri>/</uri>
<bundleFileName>my-ds.xml</bundleFileName>
<includeInApplicationXml>true</includeInApplicationXml>
</jarModule>
<webModule>
<groupId>${project.groupId}</groupId>
<artifactId>project-war</artifactId>
<contextRoot>${context.path}</contextRoot>
</webModule>
</modules>
</configuration>
</plugin>
Will generate META-INF/application.xml:
<application>
<display-name>project-ear</display-name>
<description>...</description>
<module>
<java>jtds-1.2.4.jar</java>
</module>
<module>
<java>my-ds.xml</java>
</module>
<module>
<web>
<web-uri>project-war-1.0.0.war</web-uri>
<context-root>/</context-root>
</web>
</module>
</application>

Resources