I am finishing migrating a standalone multi-project java from Ant to Maven. The structure of my projects is similar to the following:
parent-project
|_ Project A
| |
|_Project B
|_Project C
In parent-project there is no code but I define in the DependencyManager the most common used dependencies and their versions. ProjectA POM uses the depedencies defines in parent-project and ProjectB too and calls methods from ProjectA.
I can perfectly execute my desktop application from Eclipse as a Maven project (Goals: exec:java). The Dependency Hierarchy tab provided by m2e shows the right dependency order and it's the same shown as dependency:build-classpath.
dependency:build-classpath tells Maven to output the path of the dependencies from the local repository in a classpath format to be used in java -cp. The classpath file may also be attached and installed/deployed along with the main artifact.
However, despite my project depedencies seems correct when I launch the standalone application as a Maven main project from Eclipse, it is not the same when I package the jar with its jar dependencies in a sub-directory (created with maven-jar-plugin).
MyApp.jar
|_ \lib
|_ MyApp dependencies
|_ Maven projects jars
|_ Maven projects jars dependencies
My manifest file include a classpath that is the equivalente to execute "mvn dependency:resolve" but I still don't manage to figure out where the order of these jars come from (even changing the POM doesn't seem to have any effect on it). My application manage to run but I have many problem with runtime libraries because it doesn't use the one that it is meant to use.
dependency:resolve tells Maven to resolve all dependencies and displays the version
If there is someone out there that could point out the source of this problem, I would be eternally greatful.
I have found myself the solution after all.
The problem appeared only when invoking maven-dependency-plugin for copying the dependencies. I remove the execution of that plugin and replace the copy-resource with maven-resources-plugin.
Before (not working):
<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>jar-with-dependencies</id>
<formats>
<format>dir</format>
</formats>
<!-- Dependencies properties -->
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<useProjectArtifact>false</useProjectArtifact>
<unpack>false</unpack>
</dependencySet>
</dependencySets>
<!-- To avoid include the target name as a root directory -->
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<!-- Copy resources from resources to target -->
<fileSet>
<directory>../AnotherJavaProject/src/main/resources/utils/</directory>
<outputDirectory>utils</outputDirectory>
</fileSet>
<!-- ...more resources here -->
<!-- Copy the .exe to the target folder -->
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory></outputDirectory>
<includes>
<include>*.exe</include>
</includes>
</fileSet>
</fileSets>
</assembly>
After (working):
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/${project.build.finalName}</outputDirectory>
<resources>
<resource>
<!-- Copy resources from resources to target --> <directory>../AnotherJavaProject/src/main/resources/utils/</directory>
<targetPath>utils</targetPath>
</resource>
<!-- ...more resources here -->
<!-- Copy the .exe to the target folder -->
<resource>
<directory>${project.build.directory}</directory>
<include>*.exe</include>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
Hope this help somebody.
Related
Using this command : mvn clean install assembly:single
With this maven plugin configuration :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/descriptor.xml</descriptor>
</descriptors>
<!-- Configures the created archive -->
<archive>
<!-- Configures the content of the created manifest -->
<manifest>
<!-- Adds the classpath to the created manifest -->
<addClasspath>true</addClasspath>
<!-- Specifies that all dependencies of our application are found from the lib directory.-->
<classpathPrefix>lib/</classpathPrefix>
<!-- Configures the main class of the application -->
<mainClass>${main.class}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
With this assembly descriptior file config:
<assembly
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/xsd/assembly-2.1.1.xsd https://maven.apache.org/xsd/assembly-component-2.1.1.xsd">
<!-- Specifies the suffix name previusly of .jar -->
<id>uber</id>
<!-- Specifies that our binary distribution is a jar package -->
<formats>
<format>jar</format>
</formats>
<!-- Avoids generating a folder of this project on base directory. Making unable to find mainClass -->
<includeBaseDirectory>false</includeBaseDirectory>
<!-- Adds the dependencies of our application to the lib directory -->
<dependencySets>
<dependencySet>
<!-- Coppying third party libraries into lib folder -->
<outputDirectory>lib</outputDirectory>
<useProjectArtifact>false</useProjectArtifact>
<!-- Decides if thirdparties are unpacked or stored in .jars -->
<unpack>true</unpack> <!--I have tried to set as false but same result -->
<!-- <useTransitiveDependencies>false</useTransitiveDependencies>-->
<!-- <scope>runtime</scope>-->
</dependencySet>
</dependencySets>
<fileSets>
<!-- Adds the application classes to the .jar file created. -->
<fileSet>
<directory>target/classes</directory>
<outputDirectory/>
</fileSet>
</fileSets>
</assembly>
Generates the next .jar
Where added package contains my project sources and lib contains third parties libraries as I wish. Also the manifest file contains what I should have according this file structure.
Anyways I am returning this error:
It looks like it does not found the third part libraries for some reason. I am starting to learing a little more about maven but this things creepy me a little bit.
I also tested configurate assembly plugin like this :
Then the .jar file generated have the third party libraries but not project sources and when launching it. It does not found the main class.
What could I be doing wrong?
Thanks in advance
Edit: I'am ensured this error is because at the start of the program is trying to initialize the log library.
Edit2: Trying to debug. I have find that java.classpath may contain the path to the class path. Making a foreach of System.getProperties(). At least java.class.path has this content:
Does the classpath may refer to this folder? I supposed it had to refer like a relative path to the inside lib folder. As MANIFEST.MF file is configured.
I've maven project. I use maven-assembly-plugin to create zip files with all module dependencies packed in it.
Need to create zip with following structure:
/my-libs
/other-libs
To my-libs need to pack dependencies from my-lib depenency + all its transitive dependencies.
TO other-libs need to pack all other dependencies from current maven module.
Basically I need conditionally select target folder:
if (dependency in transitive-dependencies(my-lib))
copy to /my-libs
else
copy to /other-libs
Is it possible to do with maven-assembly-plugin ? Are there any alternative maven plugins to do so?
You need to define two dependencySet in the assembly XML file
<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">
...
<dependencySets>
<dependencySet>
<useProjectArtifact>false</useProjectArtifact>
<useTransitiveFiltering>false</useTransitiveFiltering>
<includes>
<include>com.example:dependency1:jar</include>
<include>com.example:dependency2:jar</include>
...
</includes>
<outputDirectory>/my-libs</outputDirectory>
</dependencySet>
<dependencySet>
<useProjectArtifact>false</useProjectArtifact>
<useTransitiveFiltering>false</useTransitiveFiltering>
<includes>
<include>com.example:other1:jar</include>
<include>com.example:other2:jar</include>
...
</includes>
<outputDirectory>/other-libs</outputDirectory>
</dependencySet>
</dependencySets>
...
</assembly>
Docs:
http://maven.apache.org/plugins/maven-assembly-plugin/usage.html
http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html
I got the impression that you started the wrong way. You say that only some programs need other-libs on the classpath, others not. So these seem not to be "real" dependencies of your project, at most optional ones.
I would suggest to use the my-lib project to create an assembly zip of my-lib with all dependencies. This can be used in all contexts where otherlibs are not necessary.
On the other hand, you can create a second zip from your original project, containing all the libs. This way, you have two different zips for two different purposes, but you do not need to create a directory structure inside the zip.
You can split your dependencies into two modules:
- ModuleX
pom.xml (contain my-libs)
- ModuleY
pom.xml (contain my-libs + other-libs)
Then use maven-dependency-plugin to copy transitives dependencies into respective folder.
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.parent.basedir}/build/other-lib</outputDirectory>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Now you each module build will contains exactly only the jars you need, no duplicate INSIDE. (I think we can ignore the duplication of my-libs BETWEENboth build because you don't gonna use both in the same platform anyway)
I'm creating a distribution assembly (with format "dir") for my multi module project using the maven-assembly-plugin. The project looks like this:
+ my-project
+-- my-child-project-1
+-- my-child-project-2
The child projects inherit from my-project. my-project is an aggregation, i.e. defines the child project in the <modules>-section.
The assembly contains artifacts, sources, etc. How do I need to setup my project to include the site?
The my-project site's links to child-modules have to work. As far as I know the links won't work before deployment. Therefore, I guess I have to stage-deploy the site first (?). According to the docs, the staging is only possible after creating the site:
This goal requires the site to already have been generated using the site goal, such as by calling mvn site.
How can I achieve this?
Is there a way to get everything assembled with one single mvn package? How does my assembly-descriptior have to look like?
I don't know, if this is a good solution, but there were no other answers, so I came up with this:
1. Move the assembly build into a separate child module
Important: I don't know if this is necessary, however I don't have the time to check whether it also works, if the assembly is configured in the root project. Otherwise you have to define a dependency in my-project to my-project itself with different classifier in step 2, and I think this won't work. Feel free to edit this answer, if I'm wrong.
+ my-project
+-- my-child-project-1
+-- my-child-project-2
+-- my-project-build
2. Define dependencies for all modules with classifier site in the build project
<!-- Yes, also for the parent project. However, not for the build project itself -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>my-project</artifactId>
<version>${project.version}</version>
<classifier>site</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>my-project</artifactId>
<version>${project.version}</version>
<classifier>site</version>
</dependency>
...
3. Define dependencySets in the assembly descriptor. Fix broken links by moving sub module site content to respective sub-directories of the main module's site directory.
The idea is to use the site-jar artifacts generated due to the site-classifier dependencies and unpack them. The module links are relative, so unpacking the content into sub-directories named by their artifactIds will fix those links.
<dependencySets>
<dependencySet>
<outputDirectory>site</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<useProjectAttachments>true</useProjectAttachments>
<unpack>true</unpack>
<includes>
<include>*:my-project:jar:site</include>
</includes>
</dependencySet>
<!-- sites of sub modules -->
<dependencySet>
<includes>
<include>*:my-child-project-1:jar:site</include>
<include>*:my-child-project-2:jar:site</include>
<include>*:my-project-build:jar:site</include>
</includes>
<outputDirectory>site/${artifact.artifactId}</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<useProjectAttachments>true</useProjectAttachments>
<unpack>true</unpack>
</dependencySet>
<!-- sites of sub-sub modules (if required) -->
<dependencySet>
<includes>
...
</includes>
<outputDirectory>site/${artifact.parent.artifactId}/${artifact.artifactId}</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<useProjectAttachments>true</useProjectAttachments>
<unpack>true</unpack>
</dependencySet>
...
</dependencySets>
4. Define the site:jar goal in the root project
This goal is by default executed in the package phase and generates the "site"-attachments (e.g. my-parent-1.0.0-site.jar), which are defined as dependencies in step 2 and unpacked in step 3:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.4</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
5. Run mvn package to generate your assembly
The result is a sub-directory "site" in your assembly containing the complete site with working links.
I use Maven to build my MyProject. There are several other projects which are used as library projects for 'MyProject'.
In pom.xml of MyProject, I defined those library projects as dependencies of MyProject. One of the Library project is named "OneLibProject":
<dependency>
<groupId>com.xxx.OneLibProject</groupId>
<artifactId>OneLibProject</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>jar</type>
</dependency>
<dependency>
...
</dependency>
Under MyProject root path, after I run : maven clean install a MyProject.jar is generated. But those classes defined in library projects(dependencies) are not included in this MyProject.jar.
Each library project also have its own pom & can generate its own jar.
Now, what I want to do is I want to have my pom.xml in "MyProject" to be configured so that the generated MyProject.jar file contains the classes of OneLibProject and classes of MyProject. Other library project classes are not included.
How to achieve this?
You can use maven-assembly-plugin and configure which dependencies to include in jar in assembly descriptor's dependencySet section.
Assuming you have project y and z. Add this plugin to y's pom
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</configuration>
</plugin>
place this assembly.xml in scr/main/assembly
<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>jar-with-dependencies</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<scope>runtime</scope>
<includes>
<include>test:y</include>
<include>test:z</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
run mvn install in z
run mvn package assembly:assembly in y
if all correct you will get y-0.0.1-SNAPSHOT-jar-with-dependencies.jar in target folder. It will contain y and x classes only.
I have a multi-module maven project with an installer sub-project. The installer will be distributed as an executable JAR. It will setup the DB and extract the WAR file to the app server. I would like to use maven to assemble this jar like so:
/META-INF/MANIFEST.MF
/com/example/installer/Installer.class
/com/example/installer/...
/server.war
The manifest will have a main-class entry pointing to the installer class. How might I get maven to build the jar in this fashion?
You can build the jar using the Maven Assembly Plugin.
First, you'll need to add some information to your pom.xml plugins section to make the resulting jar executable:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.example.installer.Installer</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
I recommend using a separate assembly descriptor to build the actual installer jar. Here's an example:
<assembly>
<id>installer</id>
<formats>
<format>jar</format>
</formats>
<baseDirectory></baseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<includes>
<!-- this references your installer sub-project -->
<include>com.example:installer</include>
</includes>
<!-- must be unpacked inside the installer jar so it can be executed -->
<unpack>true</unpack>
<scope>runtime</scope>
</dependencySet>
<dependencySet>
<outputDirectory>/</outputDirectory>
<includes>
<!-- this references your server.war and any other dependencies -->
<include>com.example:server</include>
</includes>
<unpack>false</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</assembly>
If you've saved the assembly descriptor as "installer.xml" you can build your jar by running the assembly like this:
mvn clean package assembly:single -Ddescriptor=installer.xml
Hope this helps. Here are some additional links that you might find useful:
Maven Assembly Plugin - Configuration and Usage
Creating Executable JARs using the Maven Assembly Plugin
Creating executable jars with Maven