Bundling different java classes in a single jar files in a single jar
basically what I have is an application server running liferay portal. and we also have custom portlets that have shared custom libraries as well as third party ones. for instance dwr-3.0, several drools jar files, spring-webmvc, spring, etc.
the probl开发者_运维问答em is that is a nightmare for server administration, because when there is a deploy somebody always forgets what version was in the server etc.
We use maven 2, and what I was thinking is to do something like a maven project that pulls the dependencies (using dependencyManagement) from the parent pom and the default goal is something like "unjar all the dependencies and jar them in a unique jar". that way we would have a unique jar with a standard version that is deployed along with the rest of the files instead of having to deploy.
Do you guys know how can I do that if it is at all possible? I have been playing around with maven-assembly-plugin without much success. If assembly is the way to go, do you have an example to give me a kickstart?
Thanks in advance
Another alternative is the maven-shade-plugin or even jarjar. I've used both, together with package renaming without any problems.
It sounds like maybe the Dependency Plugin is what you need.
I'm thinking you can unpack all the dependency jars to a specified location, then repack them into your new jar.
I hope it works out for you.
I think that what you described is possible. First, create a parent POM where you declare dependencies in the <dependencyManagement>
element:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>groupIdA<groupId>
<artifactId>parent</artifactId>
<packaging>pom<packaging>
<version>1-SNAPSHOT</version>
...
<dependencyManagement>
<!-- Standard dependencies used in several build modules. Ensures all modules
use the same version for these dependencies -->
<dependencies>
<dependency>
<groupId>org.directwebremoting</groupId>
<artifactId>dwr</artifactId>
<version>3.0.M1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.0.0.RELEASE</version>
</dependency>
...
</dependencies>
<dependencyManagement>
...
</project>
Then, in a child project, declare the dependencies you need without declaring their version:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>parent</artifactId>
<groupId>groupIdA</groupId>
<version>1-SNAPSHOT</version>
</parent>
<artifactId>childB</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.directwebremoting</groupId>
<artifactId>dwr</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
...
</dependencies>
...
</project>
Finally, use the default jar-with-dependencies
predefined assembly descriptor to create a general assembly of a binary package with all the dependency libraries included unpacked inside the archive.
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</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> <!-- append to the packaging phase. -->
<goals>
<goal>single</goal> <!-- goals == mojos -->
</goals>
</execution>
</executions>
</plugin>
[...]
</plugins>
</build>
</project>
To create the project assembly, trigger the package phase:
mvn package
And this will produce the following assembly in the target directory:
target/child-1.0-SNAPSHOT-jar-with-dependencies.jar
I'm just not sure of what you want to do with this assembly (use it as dependency in portlet projects vs pull dependencies from the parent POM? ease the liferay deployment only?). All options are possible though.
Refer to the Maven Assembly plugin documentation for more details.
I finally was able to resolve it in the following way, I have not tested in the application server, but the resulting archive is a jar file with the content of all the desired dependencies. Thanks Vincent for the tip :)
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test.jarbundle</groupId>
<artifactId>bundle</artifactId>
<version>1.0</version>
<name>bundle</name>
<packaging>jar</packaging>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.directwebremoting</groupId>
<artifactId>dwr</artifactId>
<version>3.0.M1</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<artifactId>cometd</artifactId>
<groupId>org.mortbay.jetty</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>2.5</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>2.5</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
<exclusion>
<artifactId>aopalliance</artifactId>
<groupId>aopalliance</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc-portlet</artifactId>
<version>2.5</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>4.0.3</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>4.0.3</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<artifactId>antlr-runtime</artifactId>
<groupId>org.antlr</groupId>
</exclusion>
<exclusion>
<artifactId>core</artifactId>
<groupId>org.eclipse.jdt</groupId>
</exclusion>
<exclusion>
<artifactId>janino</artifactId>
<groupId>janino</groupId>
</exclusion>
<exclusion>
<artifactId>xercesImpl</artifactId>
<groupId>xerces</groupId>
</exclusion>
<exclusion>
<artifactId>xml-apis</artifactId>
<groupId>xml-apis</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-jsr94</artifactId>
<version>4.0.3</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>4.0.3</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>jar.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>validate</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>${basedir}/target/dependency</directory>
</resource>
</resources>
</build>
And then you run
mvn package
link text
And finally the best solution was using maven-shade-plugin:
(snip)
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<finalName>${artifactId}-${version}-tmp</finalName>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>1.3.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>full</shadedClassifierName>
<artifactSet>
<excludes>
<exclude>classworlds:classworlds</exclude>
<exclude>junit:junit</exclude>
<exclude>jmock:*</exclude>
<exclude>org.apache.maven:lib:tests</exclude>
<exclude>log4j:log4j:jar:</exclude>
</excludes>
</artifactSet>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
(snip)
What is awesome about shade plugin is that it warns you when you are including classes that are overlapping (an example is the spring jar (the full one) with aopalliance classes)
精彩评论