Maven multi-module project compile - java

I created a C/S framework as a multi-module Maven project. It has three modules: "server", "client" and "common". Classes in "common" module are used both by "server" and "client".
However I don't want a standalone common.jar. Instead, I wish to compile classes in "common" module directly into server.jar and client.jar. Is there any way I can make it?

you can use the maven dependency plugin to unpack the common jar into the other projects.

Use maven assembly plugin with pre-defined descriptor jar-with-dependencies
Option 1:
Include the following in the 'server' project pom.xml:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
This will include other third party dependency as well, if you have any.
Option 2:
This option is to exclude third party libraries, if any.
1.Create an assembly.xml as follows in the same directory of pom.xml.
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>custom</id>
<formats>
<format>jar</format>
</formats>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<scope>runtime</scope>
<includes>
<include>common</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
The include tag must contain <groupId>:<artifactId> format, here just the artifactId 'common' is mentioned as I don't know your groupId.
2.Include the following in the 'server' pom.xml:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
</configuration>
</plugin>
</plugins>
</build>
Run the assembly command (assembly:single).

The best way to accomplish this is to use the maven-shade-plugin.
Add this to your server/client pom:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.7.1</version>
<configuration>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
You will end up with the common classes in the same jar as the server/client.

Related

Maven : Deploy Local Project to Remote Server with dependencies

I know this can sound very noobish and I apologize for that.
My question is simple : I developed a project locally, it contains many external dependencies that are referred to in the pom.xml file.
When I deploy on the remote server using mvn deploy, only the application jar is deployed, but not its dependencies. So I end-up with java.lang.NoClassDefFoundError when I try to execute my program on the remote server.
What do I need to do to make this work in a proper way ?
EDIT : I would rather avoid ending up with a massive sumo jar with all dependences in it. I would prefer to export the dependencies separately to the remote server (if that makes sense)
EDIT 2: Is there a way to "Mavenize" the remote server and execute Maven Dependency lookup directly from there ? And only deploy my "real" jar when I update the code ?
I will have a look at the maven-dependency-plugin with the dependency:copy-dependencies mojo. Looks interesting.
Below my pom.xml : jar-with-dependencies did not work (I must have missed something)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>zylon</artifactId>
<version>HBaseConnect</version>
<name>BaseConnect</name>
<dependencies>
(...)
</dependencies>
<distributionManagement>
<repository>
<id>ssh-repository</id>
<url>scpexe://remote.server/cloud/repo</url>
</repository>
</distributionManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>zylon.myMainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh-external</artifactId>
<version>1.0-beta-6</version>
</extension>
</extensions>
</build>
</project>
The shade plugin below worked though, but it results in a massive Jar file.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<excludes>
<exclude>classworlds:classworlds</exclude>
<exclude>junit:junit</exclude>
<exclude>jmock:*</exclude>
<exclude>*:xml-apis</exclude>
<exclude>org.apache.maven:lib:tests</exclude>
</excludes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
You can achieve this using the maven-assembly-plugin and configuring it to use the jar-with-dependencies descriptor.
You can find examples and more details of this here
EDIT: Make sure to define an execution goal for your plugin and invoke such goal correctly; either by:
Specifying the fully-qualified goal mvn groupId:artifactId:version:goal (you can check how to shorten this reference here)
OR
Attaching the goal to the desired maven phase (such as package). In your particular case:
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
[...]
</project>
As showcased in the original link I attached (https://maven.apache.org/plugins/maven-assembly-plugin/usage.html)

how to create multiple jars with usage specific xml copied to jar - Maven

I am trying to migrate from ANT build to Maven build setup for a very simple codebase setup:
src > Java Classes
conf > META-INF > 3 xml files namely dbConnect-jboss.xml, dbConnect-weblogic.xml, dbConnect-ooc.xml
The goal is to create 3 JARs :
project-jboss.jar, project-weblogic.jar, project-ooc.jar
where each jar will have META-INF/dbConnect.xml, copy of relevant conf/META-INF/dbConnect-xxx.xml.
I tried with [maven-jar-plugin + maven-antrun-plugin ] but the issue is the maven-antrun-plugin does the copy only one time so suppose project-jboss.jar created first then all the rest jars will have same dbConnect.xxx.xml
I need to get a way - how to invoke the copy of dbConnect.xml file via maven-antrun-plugin each time for the respective JAR creation.
screenshot for maven-ant and maven-jar plugin section from pom.xml
Thanks for all those who tried to help me out here, appreciate your helping gesture.
I opted maven-assembly-plugin for the needful.
The following snippet would explain my approach:
<pluginManagement>
<plugins>
<plugin>
<!-- To suppress default JAR creation -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>default-jar</id>
<phase />
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<finalName>${project.artifactId}</finalName>
<useProjectArtifact>false</useProjectArtifact>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
</configuration>
<executions>
<execution>
<id>create-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
Then I created respective assembly xml files for each relevant JAR expected. For example, one of assembly xmls:
<assembly ....>
<id>jboss</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<!-- Avoid getting relevant dependencies included in JAR -->
<includes>
<include>com.vibrant:streamliner.reposerv</include>
</includes>
<useTransitiveDependencies>false</useTransitiveDependencies>
<unpack>true</unpack>
<unpackOptions>
<excludes>
<exclude>META-INF/**</exclude>
</excludes>
</unpackOptions>
</dependencySet>
</dependencySets>
<files>
<file>
<source>${project.basedir}/config/META-INF/dbConnect-jboss.xml</source>
<outputDirectory>META-INF</outputDirectory>
<destName>dbConnect.xml</destName>
</file>
</files>
Then, I added profile in pom.xml:
<profile>
<id>create-all-jars</id>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>pom-assembly-jboss.xml</descriptor>
<descriptor>pom-assembly-weblogic.xml</descriptor>
<descriptor>pom-assembly-ooc.xml</descriptor>
</descriptors>
<appendAssemblyId>true</appendAssemblyId>
</configuration>
</plugin>
</plugins>
</build>
</profile>
And, once we execute following - 3 Jars get created:
mvn -P create-all-jars clean package

Include entire dependency JAR as JAR within maven project

Is it possible to tell Maven, or one of its common plug-ins, to pack one of my dependency JARs within the final assembly as a JAR file?
ie If I depend on org.some-group:some-artifact:1.2.3, the Maven plug-in would just stuff the entire some-artifact-1.2.3.jar into my final JAR file?
If I understood your question clearly, you need to add one specific jar into your generated jar, in this case you might use use classifier with maven-assembly-plugin
POM.xml
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>jar-with-dependencies-module</artifactId>
<version>1.0.0-SNAPSHOT</version>
<classifier>jar-with-dependencies</classifier>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
assembly.xml
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>final-assembly</id>
<formats>
<format>jar</format>
</formats>
<dependencySets>
<!-- Include the jar-with-dependencies -->
<dependencySet>
<includes>
<include>org.some-group:some-artifact:1.2.3</include>
</includes>
<useProjectArtifact>false</useProjectArtifact>
<!-- Don't use transitive dependencies since they are already included in the jar -->
<useTransitiveDependencies>false</useTransitiveDependencies>
</dependencySet>t>
</dependencySets>
</assembly>
Above configurations might give you an idea where to start and how you can include specific jars to your final jar

How do you use the maven shade plugin to include only specific classes from a dependency with scope "provided"?

I am using the maven shade plugin to package my application into a jar file. One of my dependencies is to Tomcat:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>7.0.59</version>
<scope>provided</scope>
</dependency>
The scope of this dependency is provided as the container itself will supply its JAR files. However, I do need to add a few single classes from this dependency to my JAR file. I tried adding a filter and specifying the name of the class that is to be added, but it seems that provided dependencies are ignored by the shade plugin.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>org.apache.tomcat:tomcat-catalina</artifact>
<includes>
<include>org/apache/catalina/deploy/LoginConfig.class</include>
</includes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Any ideas how what I need can be achieved?
The configuration setting you need is <useDependencyReducedPomInJar>true</useDependencyReducedPomInJar>. This will create a file named dependency-reduced-pom.xml with the references to the shaded jar(s) removed. You can also use <promoteTransitiveDependencies>true</promoteTransitiveDependencies> if the shaded jars have their own transitive dependencies to add them to the modified pom.
I had the same issue and If I can suggest a solution it would be to use the maven-assembly-plugin which will address your problem :
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<executions>
<execution>
<id>jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
<archive>
<manifest>
<mainClass>com.mypackage.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
And here is a sample of the assembly.xml which will allow you include "provided" scope artifacts:
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>jar-with-dependencies</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
</dependencySet>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
<useProjectArtifact>false</useProjectArtifact>
<unpack>false</unpack>
<scope>provided</scope>
</dependencySet>
</dependencySets>
I'am just having classpath issues in the generated artifact in the Manifest file!
I'm not very familiar with this plugin, but the best place for finding solutions to these kinds of problems is to have a look at the plugin/ goal documentation.
I guess the parameter keepDependenciesWithProvidedScope is what you are looking for.
I had the same issue, but I found we misunderstood how this plug-in works. If some dependencies are bundled into the shaded jar, they will be removed from the dependencies in the pom.xml in the shaded jar. So you should change nothing, just left their scope runtime.

Include jar-with-dependencies in separate assembly?

I'm using the maven assembly plugin to package a distributable ZIP archive. However, I would like to include the result of a separate assembly, jar-with-dependencies, inside my final archive. How can I do this? I realize that I could probably just include the JAR manually, but how can I ensure that my custom assembly will run after the JAR assembly?
You can use a multimodule project for that:
parent
|- ...
|- jar-with-dependencies-module
|- final-zip-module
In the jar-with-dependencies module, you assemble the "uber-jar" with all dependencies. The build configuration in the POM should look something like this:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
In the final-zip-module you can add the jar-with-dependencies as a dependency and use it in the assembly descriptor for the ZIP file. The POM would look something like this:
<project>
...
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>jar-with-dependencies-module</artifactId>
<version>1.0.0-SNAPSHOT</version>
<classifier>jar-with-dependencies</classifier>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
And the assembly descriptor would look something like this:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>final-assembly</id>
<formats>
<format>zip</format>
</formats>
<dependencySets>
<!-- Include the jar-with-dependencies -->
<dependencySet>
<includes>
<include>com.example:jar-with-dependencies-module:*:jar-with-dependencies</include>
</includes>
<useProjectArtifact>false</useProjectArtifact>
<!-- Don't use transitive dependencies since they are already included in the jar -->
<useTransitiveDependencies>false</useTransitiveDependencies>
</dependencySet>t>
</dependencySets>
</assembly>
Because of the dependency to jar-with-dependency-module, maven will build the final-zip-module always after your uber-jar was built.

Categories

Resources