Include libraries in EAR with Maven - java

I'd like to use maven to include jar/war's libraries in my EAR project's lib folder.
Currently my ear looks like this :
lib
lib/<entities>.jar
lib/<ejb-client>.jar
<ejb-impl>.jar
<web-app-project>.war
Each jar/war have maven dependencies which are declared with scope provided.
Why scope provided? I'm using Glassfish 3.1.2 and having issue when I put libraries in /WEB-INF/lib. I fixed the issue by copying libs in ear/lib instead (see Spring / Glassfish 3.1.2 stale files).
What I want to do is to tell to maven he has to put thoses librairies in the ear's lib folder.
I tried to put all projects in the ear's maven dependencies but it's not working actually.
Could someone help me ?
Thanks,
Smoky

This is similar to Including A Third Party Library In application.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.9</version>
<configuration>
[...]
<modules>
<jarModule>
<groupId>artifactGroupId</groupId>
<artifactId>artifactId</artifactId>
<bundleFileName>entities.jar</bundleFileName>
</jarModule>
</modules>
</configuration>
</plugin>
</plugins>
</build>

Related

Maven project doesn't recognize any classes from included sibling dependency [duplicate]

I am writing a project for acceptance testing and for various reasons this is dependent on another project which is packaged as a WAR. I have managed to unpack the WAR using the maven-dependency-plugin, but I cannot get my project to include the unpacked WEB-INF/lib/*.jar and WEB-INF/classes/* to be included on the classpath so the build fails. Is there a way to include these files into the classpath, or is there a better way of depending on a WAR?
Many thanks.
There's another option since maven-war-plugin 2.1-alpha-2. In your WAR project:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
This creates a classes artifact which you can use in the acceptance tests project with:
<dependency>
<groupId>your-group-id</groupId>
<artifactId>your-artifact-id</artifactId>
<version>your-version</version>
<classifier>classes</classifier>
</dependency>
Indeed, by design, Maven doesn't resolve transitive dependencies of a war declared as dependency of a project. There is actually an issue about that, MNG-1991, but it won't be solved in Maven 2.x and I'm not sure that I don't know if overlays allow to workaround this issue. My understanding of the suggested solution is to duplicate the dependencies, for example in a project of type pom.
(EDIT: After some more digging, I found something interesting in this thread that I'm quoting below:
I have been helping out with the development of the AppFuse project over
the last month where we make heavy use of the war overlay feature in the
Maven war plugin. It is a really nifty feature!
To get max power with war overlays I have developed the Warpath plugin
that allows projects to use war artifacts as fully fledged dependencies.
In brief:
1) The contents of the /WEB-INF/classes directory in the war dependency
artifacts can be included in the project's classpath for normal compile,
etc tasks.
2) Transitive dependencies from the war dependency artifacts become
available for use by other plugins, e.g. compile and ear - so no more
having to include all the dependencies when creating skinny wars!
The plugin has now been actively used in the AppFuse project for the
last few months, and I feel it is at a point where it is both usable and
stable.
Would the war plugin team be interested in including the warpath
functionality inside the war plugin? It would seem to be the most
natural place to host it.
So, I don't have any experience with it, but the maven warpath plugin actually looks nice and simple and is available in the central repo. To use it,include the following plugin configuration element in your pom.xml file:
[...]
<build>
<plugins>
<plugin>
<groupId>org.appfuse</groupId>
<artifactId>maven-warpath-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>add-classes</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
And add the war dependencies you want included in the classpath as warpath type dependencies:
[...]
<dependencies>
<dependency>
<groupId>org.appfuse</groupId>
<artifactId>appfuse-web</artifactId>
<version>2.0</version>
<type>war</type>
</dependency>
<dependency>
<groupId>org.appfuse</groupId>
<artifactId>appfuse-web</artifactId>
<version>2.0</version>
<type>warpath</type>
</dependency>
</dependencies>
[...]
Both the war and warpath dependency types are needed: the war type is used by the Maven war plugin to do the war overlay, the warpath type is used by the Warpath plugin to determine the correct list of artifacts for inclusion in the project classpath.
I'd give it a try.)
Use overlays. First, your test project need to have also packaging war.
Declare dependency of war project you want to test:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>your-project-arftifactId</artifactId>
<version>${project.version}</version>
<type>war</type>
<scope>test</scope>
</dependency>
then configure maven-war-plugin overlay:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>${basedir}/src/main/webresources</directory>
<filtering>true</filtering>
</resource>
</webResources>
<overlays>
<overlay/>
<overlay>
<groupId>your.group</groupId>
<artifactId>your-project-artifactId</artifactId>
</overlay>
</overlays>
</configuration>
</plugin>
In the above example in test project I overwrite webresources configuration files (like conxtext etc.).
EDIT: This solution wasn't tested with Maven 3.
Good point, Justin. That got me actually solving my problem, namely: including a war into an assembly AND including all its transitive dependencies.
I could not duplicate the war-dependency as 'jar' as you suggested since the assembly plugin would not find a jar referenced by that groupId/artefactId, but
duplicating the war-dependency as type pom
works!
The war and its transitive dependencies are not included in the assembly.
To exclude the (now also appearing) pom file I had to add an exclude element like this:
<excludes>
<exclude>*:pom</exclude>
</excludes>
into my assembly.xml file.
I think this could also be a workaround for the original question of this thread.
If you list the dependency on the war project as a jar dependency it seems to pickup the required jars/resources. I'm using Maven 2.2 + m2eclipse.

How to package a message-driven bean using Maven?

I want to package a message-driven bean using Maven. The bean has various dependencies (external libraries) that should be packaged with it. In the end, the resulting package should be deployed on an application server (such as Wildfly).
I tried to create multi-module Maven project where I have a module with "ear" packaging that depends on the actual message-driven bean module which uses "jar" packaging (I also tried "ejb" here). However, when the message-driven bean is called it is not able to acccess its dependencies (no NoClassDefFoundError).
The following change to my "ear" pom fixed this issue because the dependencies are now accessible to the message-driven bean.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.9.1</version>
<configuration>
<defaultLibBundleDir>lib</defaultLibBundleDir>
</configuration>
</plugin>
</plugins>
</build>
While it basically works now, I feel like I am doing something wrong. Do I really need to change my pom like this? If I have to place the dependencies in the lib directory, why is Maven not doing this by default when building an EAR file.
the EAR/lib folder is the default folder for libraries and every *.jar file inside this folder is automatically loaded by the ear classloader (Java EE 7 Specification)
i think that the EAR/lib folder is come in later specifications of java ee and the maven ear plugin is not updated to this "java ee defaults".
with "defaultLibBundleDir" in maven-ear-plugin all the transitive dependencies are put inside this declared folder. the second is that inside the application.xml folder maven is configuring the "library-directory" element. and this is not required because the "lib" folder is default loaded with the ear classloader.
and this can solved by the setting the maven ear configuration libraryDirectoryMode to NONE
i think it is also best practice to use the fileNameMapping to no-version configuration. this removes the maven versions out of the file names. the maven version is also inside the jar/META-INF/MANIFEST.MF
this is for the jndi name of the modules because the module name came from the jar/war name without the file ending.
your configuration whould look like this:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.9.1</version>
<configuration>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<libraryDirectoryMode>NONE</libraryDirectoryMode>
<fileNameMapping>no-version</fileNameMapping>
</configuration>
</plugin>
</plugins>
</build>

maven-war-plugin : exclude many dependencies from lib folder

I'm using maven-war-plugin to generate a WAR file.
In the dependency hierarchy, I can see many transitive dependencies, which are extract in the lib folder.
After many research, I saw that the easiest way to exclude them from the war lib folder is to declare them as 'provided' in my dependencies.
However, I have a lot of dependencies to exclude, and I have to do this in many WAR pom file.
My question is :
Is there a way to group all these dependencies in a 'pom' packaging, and use this new artifact in my WAR pom file ?
If I understand your needs...
try this--> http://maven.apache.org/plugins/maven-war-plugin/examples/including-excluding-files-from-war.html
when you build the war you can exclude all dependencies you want in this way:
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<!--
Exclude JCL and LOG4J since all logging should go through SLF4J.
Note that we're excluding log4j-<version>.jar but keeping
log4j-over-slf4j-<version>.jar
-->
<packagingExcludes>
WEB-INF/lib/commons-logging-*.jar,
%regex[WEB-INF/lib/log4j-(?!over-slf4j).*.jar]
</packagingExcludes>
</configuration>
</plugin>
</plugins>

war project dependency in maven

I need to access one bean class from war project into my another war project. The bean class is exists in MyProject. I wrote pom of another project called NewProject as follows.
<groupId>MyProject</groupId>
<artifactId>MyProject</artifactId>
<version>1</version>
</parent>
<artifactId>MyProject</artifactId>
<packaging>war</packaging>
Is it possible to add war dependency in another war project?
If you configure the maven-war-plugin with the following attribute:
<attachClasses>true</attachClasses>
you would get an supplemental artifact with the following coordinates:
<dependency>
<groupId>myGroup</groupId>
<artifactId>myArtifact</artifactId>
<version>myVersion</myVersion>
<classifier>classes</classifier>
</dependency>
which contains all classes within your war project which can be used as dependency which is a jar file which will solve your problem.
In your war project
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<attachClasses>true</attachClasses>
</configuration></plugin>
It creates a classes artifact which you can use in the required project
<dependency>
<groupId>your-group-id</groupId>
<artifactId>your-artifact-id</artifactId>
<version>your-version</version>
<classifier>classes</classifier>
refer maven war plugin
hope it helps...
Dependencies work using jars, and you would normally define a common dependency in a .jar file that can be accessed by both .wars. That's not Maven-specific, but how dependencies in Java work. The internal structure of a .war is different from a .jar in terms of how the classes are laid out.
Consequently in Maven, I would expect to define a .jar project, and then two .war projects both depending on the initial project.
You are better off IMHO creating a jar with your war classes that are needed in your project.
And then just add the dependency to your project configuration (classifier classes).
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>classes</id>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>classes</classifier>
</configuration>
</execution>
</executions>
</plugin>
Move your re-usable classes into a separate module. This will help:
Test things quicker.
Use the code as a dependency in other projects.
Alternatively, you could produce a classes only jar by using the maven-jar-plugin and producing a classifier-based artifact. However, I think my suggestion is better in the fact that it give you a clear separation of the code and forces you to organize your code better.

How to use bundleFileName of maven-ear-plugin in IntelliJ?

I have a maven ear module with the following configuration for my ear file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.6</version>
<configuration>
<displayName>app</displayName>
<description>app</description>
<modules>
...
<ejbModule>
<groupId>com.example</groupId>
<artifactId>example-client</artifactId>
<bundleFileName>example-client.jar</bundleFileName>
</ejbModule>
..
</modules>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<version>5</version>
</configuration>
</plugin>
When I use Intellij (ultimate 12.1.4) to deploy my ear to a jboss as, the bundleFileName is ignored.
It creates a jar file with version number, but in the application.xml the jar file is defined without version.
Is there a way to fix this? I deploy using the "exploded" ear.
Thanks!
The issue is fixed in Intelij 13 (currently not yet release): see http://youtrack.jetbrains.com/issue/IDEA-114355

Categories