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

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.

Related

Maven : How to package external jars(folder) in Maven project

I am having a group of external jars(in hundreds) which I have added in the build path of my project to make it work.
But while packaging it is failing as these jar's are not available to maven.
I have gone though many articles and all the solutions(like adding the jar at system path) are for a single jar only.
<dependency>
<groupId>com.sample</groupId>
<artifactId>sample</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/Name_Your_JAR.jar</systemPath>
</dependency>
Is there any way we can add the group of jars(folder) to the packaging on the project? or any other solution by which my project can build successfully?
can we create a single jar containing all my jars inside and then use the system scope of maven
I have tried creating jar by jar -cvf my_jar.jar * and placed this jar in the system scope. But it does not worked for me.
My solution : Maven pluggin addjar let us add all jar at a place(projectdirectory/lib in this case).
this enables you to add these jar's in the final package(jar in my case) when you maven build, but to run locally you have to add those jar files directly in the classpath.
<plugin>
<groupId>com.googlecode.addjars-maven-plugin</groupId>
<artifactId>addjars-maven-plugin</artifactId>
<version>1.0.5</version>
<executions>
<execution>
<goals>
<goal>add-jars</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>${basedir}/lib</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
Now create a shade jar using mvn clean install shade:shade
The bad news: For a proper Maven project, you need to add each and every artifact you use as <dependency> in your POM.
The good news: I very much doubt that these 100 jars are all
- directly used in your source code
- not available in a public Maven repository like MavenCentral
So the better strategy would be to figure out what you really need and find that in MavenCentral. Then Maven finds all the transitive dependencies for you. So if you really need 10 of the jars and all other jars are just dependencies of your dependencies, just add these 10 ones (from MavenCentral) and you are done.

Can I use the maven war as a form of overwriting the other projects that already exist?

I am beginner on Spring and Maven.
In Spring Framework,
I want to manage a separate version control flow.
1. Main Project that already exist.
2. Module of the partial use that packaged by maven war.
Two projects should be treated separately when Push and Pull.
But Files on two projects may be present in the same folders.
How can I use this?
This is actually related with version control system you currently use. Git for example supports submodules. You can create a maven module directly in your root project folder and define it as git submodule. So they have different git tracks and may seperately maintained.
I believe what you need might be achievable by using 'war-overlays' as documented here
To summarize, you specify the 'child' project as a dependency in the 'Main' project:
...
<dependencies>
<dependency>
<groupId>com.example.projects</groupId>
<artifactId>documentedprojectdependency</artifactId>
<version>1.0-SNAPSHOT</version>
<type>war</type>
<scope>runtime</scope>
</dependency>
...
</dependencies>
...
And you define the overlay in the maven-war-plugin's configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<overlays>
<overlay>
<id>my-webapp-index.jsp</id>
<groupId>com.example.projects</groupId>
<artifactId>my-webapp</artifactId>
<includes>
<include>index.jsp</include>
</includes>
</overlay>
<overlay>
<!-- empty groupId/artifactId represents the current build -->
</overlay>
</overlays>
</configuration>
</plugin>

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>

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.

Jenkins Maven Plugin: Classloading Feature

Good time!
Our team uses Maven. One of the project modules has a plugin (maven-jibx-plugin) that requires (for our use-case) a dependency on a proprietary jar:
<plugin>
<groupId>org.jibx</groupId>
<artifactId>jibx-maven-plugin</artifactId>
<version>${jibx.version}</version>
<executions>
<execution>
<id>main-schemas</id>
<phase>generate-sources</phase>
<goals>
<goal>schema-codegen</goal>
</goals>
<configuration>
<schemaLocation>
...
</schemaLocation>
<includeSchemas>
...
</includeSchemas>
<customizations>
<customization>${basedir}/src/main/resources/customizations/customization.xml
</customization>
</customizations>
<verbose>true</verbose>
</configuration>
</execution>
<execution>
<id>bind</id>
<phase>process-classes</phase>
<goals>
<goal>bind</goal>
</goals>
<configuration>
<schemaBindingDirectory>
${basedir}/src/main/resources/bindings
</schemaBindingDirectory>
<includeSchemaBindings>
<includeSchemaBinding>*.xml</includeSchemaBinding>
</includeSchemaBindings>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>proprietary-jar</artifactId>
<version>${project.parent.version}</version>
</dependency>
</dependencies>
</plugin>
The problem is when we build the project locally (and even from a command line on the remote machine where jenkins is istalled), everything builds successfully, but when our jenkins instance tries to build it - the build fails with such a message: "Unable to find class 'class-name-from-the-proprietary-jar'". This problem occurred loccally before we added the plugin dependency..
Seems like there is some feature of jenkins maven plugin that do no resolve the plugin dependencies or may be there are some well-known feature of the jenkins maven plugin classloading (JiBX loads proprietary classes with such a construct: SchemaRootBase.class.getClassLoader().loadClass(cname) So that specifing the dependency for the plugin should provide a knowledge for it about the required classes)... Can somebody, please, suggest the workaround?
UPDATE:
it turned out that the jenkins instance's JAVA_HOME variable is set to /usr/java/jdk1.7.0_25, but in my maven-compiler-plugin I have <target>1.6</target>. Could it be that the problem is in the 1.7 java version?
Well, finally I've found an answer! The problem is not actually in Jenkins, but rather in Maven itself.
ATTENTION: the undergoing information is tested only for Maven 2.
It turned out that when you have a multimodule project and several modules use the same plugin (with different dependencies), Maven would get dependencies set for the first plugin (I mean that the plugin is located in the first module, that Maven builds, with this plugin) and use them for other plugins not overriding the dependencies by the local values.
To clarify this lets have an example. Say there are two modules in the maven build - A and B:
<modules>
<module>A</module>
<module>B</module>
</modules>
and the module A has such the code in the pom file:
<plugin>
<dependencies>
<dependency>
<groupId>com.c</groupId>
<artifactId>D-module</artifactId>
<version>1</version>
</dependency>
</dependencies>
<groupId>org.jibx</groupId>
<artifactId>jibx-maven-plugin</artifactId>
<version>${jibx.version}</version>
</plugin>
and the module B has such the code in the pom file:
<plugin>
<dependencies>
<dependency>
<groupId>com.c</groupId>
<artifactId>F-module</artifactId>
<version>1</version>
</dependency>
</dependencies>
<groupId>org.jibx</groupId>
<artifactId>jibx-maven-plugin</artifactId>
<version>${jibx.version}</version>
</plugin>
It turns out that when Maven builds the module B it will use the D-module dependency even though you have specified the F-module dependency.
In our project we made such a workaround: we moved the plugin declaration to the parent pom in a pluginManagement section and declared the D-module and F-module dependencies for the plugin (also removed these dependencies from the local modules). Ok, the code is rather ugly (having child dependencies in the parent pom file), but this works!
If somebody shared this issue and managed to overcome it, please, advice the solution.
Try mvn clean install in your workspace
Then you should have the same error every where. Also try and use the same command line Jenkins is using (if any)

Categories