war project dependency in maven - java

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.

Related

maven-jar-plugin: How to create a different artifact name for tests?

Let's say that I put the following plugin in my pom.xml file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>make-a-jar</id>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<finalName>my-artifact-name</finalName>
</configuration>
</execution>
</executions>
</plugin>
and I run "mvn clean install".
Maven creates two jar files in target library.
The first jar file compiles the source files and the second jar compiles the test files. Both of these jar will have the same artifact name.
If I want to use the jar of source code as a dependency in another project, I can put the following dependency in the other project:
<dependency>
<groupId>groupId</groupId>
<artifactId>my-artifact-name</artifactId>
<scope>system</scope>
<type>jar</type>
<systemPath>${basedir}/lib/my-artifact-name.jar</systemPath>
</dependency>
So far so good.
A problem arises if I also want to add a dependency for the test files. In this case I will have two dependencies with the same groupId and artifactId and different systemPath. Maven will not read two dependencies with same groupId and artifactId. Only one of them will be read.
One solution that I can think of is to make Maven to give a different artifact name for test.
Do you know how to do it?
My general answer to that would be:
The tests in src/test/java are only for running them during the build. They need not be put into any jar.
If you need classes as helper classes for your tests, you can create a separate jar which contains these classes. This can then be used as test dependency.
In any case, try to avoid <systemPath>. If you build your project with mvn clean install on your computer, you can reference the resulting jar with a dependency like
<dependency>
<groupId>groupId</groupId>
<artifactId>my-artifact-name</artifactId>
<version>1.2.3</version>
</dependency>
anywhere on the same account/computer without giving a <systemPath>.

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.

maven: Adding classes in war/web-inf/classes as dependency to a Jar module

The task is to create customization to the core project. The core project can not be modified by my team.
The requirement is to change the control flow to the core and implement controller and services extending or using the core classes. Here the customization will be delivered as Jar and Core product will be war. That means the classes that i am going to extend are in web-inf/classes folder of a war. Both customization and core product uses maven.
The problem I am facing here is that, I am not sure how to add war as dependency to my jar (customization)
Any thought please. Also please let me know if there is a good design to do.
Maybe not for your case - but solved my problems, you can create a separate jar from the war, that will contain only classes
https://pragmaticintegrator.wordpress.com/2010/10/22/using-a-war-module-as-dependency-in-maven/
<build>
...
<plugins>
...
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1-beta-1</version>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
...
</plugins>
...
</build>
produces xxx.war and xxx.classes.jar that you can include
<dependency>
<groupId>net.pascalalma.adapters</groupId>
<artifactId>my-adapter</artifactId>
<version>1.0-SNAPSHOT</version>
<classifier>classes</classifier>
<scope>test</scope>
</dependency>

Custom second packaging artifact from single pom.xml, like jar and test-jar?

I have a group of projects that have (a) generated beans, and (b) code to work with those beans. I'd like each such project to create two different artifacts: a regular jar artifact that contains all classes, and a custom beans artifact that contains only the generated types.
I put together a quick plugin that creates a second beans artifact using artifact attachments and the "beans" classifier, but it doesn't work well in m2e. For this reason, I think creating a custom packaging type (e.g., "test-jar") is The Right Thing.
To be totally clear about what I'm imagining, this pom would works today and creates two different artifacts with two different packaging types:
<project>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
which you could import with either of the following:
<dependency>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
<!-- <type>jar</type> -->
</dependency>
<dependency>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
<type>test-jar</type>
</dependency>
I'd like to create a plugin that will let me use (for example) beans instead of test-jar to create a similar "paired" artifact.
I've poked around in the maven source code, and you can create custom types. However, "test-jar" seems to be "baked in" to maven, so I can't tell if it has some special features and I can't duplicate this behavior with my own plugin.
Of course, if there's another way to handle this kind of behavior without custom types that m2e understands -- for example, but getting m2e to understand my classifier, although that seems hard -- I'm all ears! :)
How can I make a similar paired packaging type? I've seen this answer regarding how to create custom types, but it only seems to create one artifact from a pom with the given custom packaging type.
OK, figured out how to get a custom type working with an additional artifact from the same POM.
You do use attached artifacts to generate the additional artifact. For my example, I used this call in my goal in my plugin (after I was done building my JAR file):
#Mojo(name="goal-name", defaultPhase=LifecyclePhase.PACKAGE)
public class MyMojo
extends AbstractMojo
{
#Component
private MavenProject project;
#Component
private MavenProjectHelper projectHelper;
#Component(role=Archiver.class, hint="jar")
private JarArchiver archiver;
public void execute() throws MojoExecutionException {
// Do work...
// Create JAR file...
File jarFile=createJarFile(archiver);
projectHelper.attachArtifact(project, "beans-jar", jarFile);
}
}
Note that I specified my custom type beans-jar, and no classifier.
Next, I dropped a components file into my plugin at src/main/resources/plexus/components.xml:
<component-set>
<components>
<component>
<role>org.apache.maven.artifact.handler.ArtifactHandler</role>
<role-hint>beans-jar</role-hint>
<implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation>
<configuration>
<classifier>beans</classifier>
<extension>jar</extension>
<type>beans-jar</type>
<packaging>jar</packaging>
<language>java</language>
<addedToClasspath>true</addedToClasspath>
</configuration>
</component>
</components>
</component-set>
Here, I specify my custom type beans-jar and a classifier, which appears to be used to name the new attribute in the repository.
This file was based on artifact-handlers.xml from the maven-core project in the main maven repository. At the moment, that file is located here. (I found this file by grepping for test-jar in all .xml files in the maven repository.)
To import that dependency, you use:
<dependency>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<type>beans-jar</type>
</dependency>
To import the dependency, you don't need to include the custom plugin.
I would suggest to try a simpler way like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>second-jar</id>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>second</classifier>
<includes>
<include>**/service/*</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
Via the <include> you can defined which classes would be packaged into the supplemental jar file.

Publish test utils from maven project

I created a library in maven that can be extended by implementing some interfaces. To test the default implementation I have written some hamcrest matchers that currently live in src/test/java.
However, I think they might be useful for users of the library if they want to test their customization.
So how can I make them available? Moving them to src/main would require to make hamcrest a runtime dependency and I don't want that.
There is a way to create a test jar and install it into the repository using the command 'mvn jar:test-jar'. This jar can then be referenced by other projects using the test-jar modifier in the dependency block.
If you want to have this jar built and installed as part of your your normal 'mvn install' build add the following plugin config to your pom:
From http://maven.apache.org/guides/mini/guide-attached-tests.html
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Then other projects can reference the test jar as follows:
<dependency>
<groupId>com.myco.app</groupId>
<artifactId>foo</artifactId>
<version>1.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
As you said, move it to src/main in a new project. Let that project only be used in a test dependency and you don't pollute your module's classpath.
It sounds like you need to move them to their own project and release it. From there you can determine in the original project what scope you'd like.

Categories