I am building my Java application using Maven and the Maven Assembly Plugin to create an executable jar.
As a result, the target folder contains multiple jars and other files. However, I only want to deploy the executable jar file built via the Assembly Plugin.
To do this, I have tried to use mvn deploy:deploy-file and provided it with the following properties:
file
repositoryId
url
artifactId
groupId
version
However, when I execute the command, Maven deploys all files instead of only the executable jar.
I also tried disabling the default build step:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<executions>
<!-- disable standard deploy -->
<execution>
<id>default-deploy</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
The build part of my pom.xml looks like this:
<build>
<!--suppress UnresolvedMavenProperty -->
<finalName>${project.artifactId}-${BUILD_DATE}</finalName>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>src</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>main.PAtrackMain</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
<manifestEntries>
<!--suppress UnresolvedMavenProperty -->
<Implementation-Build>${BUILD_DATE}</Implementation-Build>
</manifestEntries>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>true</appendAssemblyId>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<executions>
<!-- disable standard deploy -->
<execution>
<id>default-deploy</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
How can I deploy only the executable jar without the other files?
That is much simpler than you might think.
There are two kinds of artifacts, produced by maven project:
main: ${artifactId}-${version}.${packaging} - this one you would like to not publish
supplemental: everything else produced by plugins (javadoc, sources, assembly, etc)
If project/module packaging is pom, that means following:
project/module may not have main artifact, only supplemental ones
some plugins are not enabled by default (https://maven.apache.org/ref/3.8.6/maven-core/default-bindings.html - compare default bindings for pom and jar packaging)
Thus, all what you need is:
switch module packaging from jar to pom
enable missing plugins: maven-compiler-plugin, maven-resources-plugin, maven-jar-plugin, etc
extra configuration of maven-deploy-plugin is not required
Related
I am trying to create jar for my spring boot server using spring boot maven plugin and my test automation framework jar from same project and pom file. To read external resources I am trying to defined manifest entries in maven jar plugin but this is causing spring server to not find application.properties in its default locations when run as a linux service using /etc/init.d/my-jar start.
Here is snippet of my pom file
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<descriptors>
<descriptor>src/assembly/dep.xml</descriptor>
</descriptors>
<archive>
<manifest>
<mainClass>com.myorg.mainclass</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.5.RELEASE</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<finalName>${project.artifactId}-${project.version}-main-only</finalName>
<archive>
<manifest>
<mainClass>com.myorg.mainclass</mainClass>
</manifest>
<manifestEntries>
<Class-Path>./config/</Class-Path>
</manifestEntries>
</archive>
<excludes>
<exclude>**/application-test.properties</exclude>
</excludes>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
I have tried changing phase of my maven assembly and jar plugin to verify but the problem still persists. Removing manifest entry seems to work but then my external resource files are not read.
To solve the problem I removed the manifest entries from maven jar plugin and then while running the test jar. I added the external resource directory path into classpath as follows:
java -classpath my/external/resource/directory/path -jar my-tests.jar
I have an application where Im using maven dependecies and Im also using an external jar of a project which is located in my computer, the project is added to the application manually. The problem is whenever I export the project with maven, It only exports all maven dependencies, not the externatl jar that I have included manually. Is there anyway that I can export it?
Here is my pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>
com.cristianruizblog.loginSecurity.LoginSecurityTutorialApplication
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Thanks for reading. If anyone can help I would be so happy!
As stated by #M. Deunum, try to get your external jar into a Maven repository to avoid enable any machine to build your jar. If this is no option, you can use the Maven system dependency scope to include the jar. Note that this is only a temporary solution as this scope has been marked as depricated.
I use Maven to build a JAR. When I check the JAR, I see a maven folder inside the META-INF folder. I want it to be excluded from the build. My current build code in the pom.xml looks like this:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>Libraries</classpathPrefix>
<mainClass>com.company.Main</mainClass>
</manifest>
<manifestEntries>
<Built-By>Me</Built-By>
</manifestEntries>
</archive>
<!-- <excludes>
<exclude>META-INF/maven/**</exclude>
</excludes> -->
</configuration>
</plugin>
<!-- ...more plugins... -->
</plugins>
</build>
I read that using the exclude tags allows you to exclude something but it doesn't work. Maybe this only refers to local files/folders? The maven folder is not part of the source, it's just added by Maven.
This answer kind of works but uses a different artifact hence a 2nd JAR is generated when I paste it into my pom.xml. I want to use my current build code and exclude the maven folder like described above. How can it be done using maven build rules?
The maven-jar-plugin uses the maven-archiver to handle packaging. It provides the configuration addMavenDescriptor, which is true by default. Setting it to false should remove the META-INF/maven directory.
...
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
....
</archive>
You can find the reference here.
You can use maven shade plugin to create the jar and exclude the maven folder using following configurations in you pom.xml file:
<profile>
<id>shade</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<excludes>
<exclude>META-INF/**</exclude>
</excludes>
</filter>
</filters>
</configuration>
</executions>
...
</profile>
When i run my jar file an it comes during runtime to access a class from a dependency (which is included by the maven-addjars-plugin), i get a java.lang.NoClassDefFoundError error.
Note: i also include some jars normaly by just specifying the dependency in the POM.xml, i only use the addjar plugin for the custom jars which i only have locally.
Part of POM.XML (If you need more information, pls tell)
<build>
<defaultGoal>install</defaultGoal>
<directory>${basedir}/target</directory>
<finalName>${project.artifactId}-${project.version}</finalName>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>Swapper</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<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}/my-repo</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
....
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen</artifactId>
<version>2.1.4-SNAPSHOT</version>
</dependency>
The swagger lib was copied into "target/com.googlecode.addjars-maven-plugin" folder which idk is the right place to have those libs since i dont see the libraries that are downloaded from maven repository. But the class is not found during runtime.
UPDATE:
When running with mvn exec instead of java -jar the program runs.
Anyone has an idea what i did wrong?
I have set up basic maven project in java SE, with a resource:
main
-java
-resources
-config -> database.properties
now since I don't want this resource in the final jar, I define:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<excludes>
<exclude>config/database.properties</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>make-jar-ultimateParser</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/dist</outputDirectory>
<finalName>testApp</finalName>
<archive>
<compress>false</compress>
<!-- Manifest - MainClass & ClassPath -->
<manifest>
<mainClass>aa.bb.Class</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Class-Path>config/database.properties</Class-Path>
</manifestEntries>
</archive>
</configuration>
</execution>
</executions>
</plugin>
<!-- Copy configuration files -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/dist/config</outputDirectory>
<resources>
<resource>
<directory>src/main/resources/config</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
So the resource is on classpath and the directory with the resource is copied to the final jar.
My manifest looks like this: "Class-Path: config/database.properties"
But I'm not able to read it:
String db = "/config/database.properties";
properties = new Properties();
properties.load(getClass().getResourceAsStream(db));
I tried absolute/relative paths, getClass()/ClassLoader. Nothing. It works flawlessly in NetBeans, but that's about it.
You're misunderstanding what the Maven Resources plugin does. It simply copies resources (perhaps with transformation) into the build output directory. Where they're then included into the build artifact (JAR, WAR, whatever).
To make this work (referencing the JAR's directory using the Class-Path manifest entry), you need to distribute the config file separately. Or reference it using a File, and not bothering with the classpath.
A better approach is to distribute your application as an assembly, which contains the core app, any dependencies, and the configuration file. This would typically be packaged as a ZIPfile, and the user would unzip it to install.
I dont understand why you are excluding it. Maven uses its own resources dir.
Project
|-- pom.xml
-- src
-- main
`-- resources
wich it makes easier the life the programmer. Theres no need to get classpatch or other when you using this way.