I have a Spring Boot application and I have created a Jar out of that. Following is my pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- WebJars -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.6.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
I want to use this Jar in my other application so added this jar to my application. But when I am calling a method in that Jar, it is throwing a ClassNotFoundException.
How can I fix this issue? How can I add a dependency to a Spring Boot JAR?
By default, Spring Boot repackages your JAR into an executable JAR, and it does that by putting all of your classes inside BOOT-INF/classes, and all of the dependent libraries inside BOOT-INF/lib. The consequence of creating this fat JAR is that you can no longer use it as a dependency for other projects.
From Custom repackage classifier:
By default, the repackage goal will replace the original artifact with the repackaged one. That's a sane behaviour for modules that represent an app but if your module is used as a dependency of another module, you need to provide a classifier for the repackaged one.
The reason for that is that application classes are packaged in BOOT-INF/classes so that the dependent module cannot load a repackaged jar's classes.
If you want to keep the original main artifact in order to use it as a dependency, you can add a classifier in the repackage goal configuration:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.4.1.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
With this configuration, the Spring Boot Maven Plugin will create 2 JARs: the main one will be the same as a usual Maven project, while the second one will have the classifier appended and be the executable JAR.
Tunaki's answer is correct but doesn't work in Spring Boot 2.
Spring Boot 1.x
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.20.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
...
</plugin>
Read more
Spring Boot 2.x
If you are using spring-boot-starter-parent, the repackage goal is executed automatically in an execution with id repackage. In that setup, only the configuration should be specified as shown in the following example:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
...
</plugin>
Read more
For Spring Boot 2 #Tunaki's answer must be modified a bit according to the documentation if spring-boot-starter-parent is used as parent :
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
Take note of the extra <id>repackage</id> necessary to overwrite to execution from the spring-boot-starter-parent.
if you want to use the spring-boot project as a dependency and same time want to run as a spring-boot jar then use the below configuration. by the below configuration, you can achieve two goals.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>build information</id>
<goals>
<goal>build-info</goal>
</goals>
</execution>
<execution>
<id>repackage</id>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
This configuration creates two jars as shown below example screenshot:
What #Tunaki stated was mostly correct but the one missing part based on your original question was:
This throwing ClassNotFoundException. The External jar's used in
spring boot application is missing.
This is due to the fact that the FatJAR created from the maven packaging has the dependent libraries specified in a specific location that works for how Spring Boot executes the application. If you are just adding the JAR to another application's classpath then you should do what #Tunaki said and also include the dependent JAR files to the classpath. The best way to work with this is to use the Maven Dependency Plugin specifically targetting the dependency:copy-dependencies mojo to download all the dependencies into a folder that you can then specify as a library path when compiling the other application.
You can extend your project by maven-assembly-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
After the build you will get 3 jars. The main one will be the same as a usual Maven project, while the second one will have the classifier appended with exec and be the executable JAR. The third jar name will be appended by jar-with-dependencies and will contain your classes with classes added as dependencies in your spring boot application(spring-boot-starter-web, thymeleaf,...), so into the pom of the application where you want to add that project as dependencie you won't have to add dependencies from spring boot project.
Use the build section provided below, it will do three things:
Create the spring boot jar using spring-boot-maven-plugin
Create a normal jar with your source code compiled classes using maven-assembly-plugin
Install the normal jar into the m2 folder locally
If you want to deploy the normal jar into a remote repository, configure the deploy plugin
<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">
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>true</appendAssemblyId>
<descriptors>
<descriptor>src/main/resources/sources-jar-build.xml</descriptor>
</descriptors>
<finalName>${pom.artifactId}-${pom.version}</finalName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<executions>
<execution>
<id>install-file</id>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${pom.artifactId}-${pom.version}</file>
<artifactId>${pom.artifactId}</artifactId>
<groupId>${pom.groupId}</groupId>
<version>${pom.version}</version>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Place the below content in a file named "sources-jar-build.xml", into resources folder:
<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>sources</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>jar</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}/target/classes</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
use below plugin for spring boot version 2.*
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.1.RELEASE</version>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
All existing answers are made under the assumption that the Spring Boot project upon which another project should depend is an application, which is fair enough since the question is phrased like that.
But if the underlying project is meant to be used as a library only, i.e. it contains no (sensible) Main class, there is obviously no executable code that needs to be repackaged at all.
So in that case, it makes more sense to skip the repackaging entirely like this:
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
I used version 2.2.5 and it's working. add it to your pom.xml
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.5.RELEASE</version>
<executions>
<execution>
<id>repackage</id>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
You can setup your projects so that the batch launcher relies on a jar, which would be shared with your other application.
Said differently, as per your initial request :
I want to use this Jar in my other application so added this jar to my application.
Let's say your jar is your project A, and your application is your project B.
Now, what I suggest, is that you remove the launching part from A ;
then you put it into a new project C, that would embed Spring Boot, and that would rely almost totally on A.
Then, since A is now a simple jar, B can use it as a dependency.
any project if you want add as a dependency you need that project <groupId>,<artifactId>,<version>, with these details you can add your project as a dependency in another module or application
for ex: your application pom details
<project
<groupId>com.sample</groupId>
<artifactId>sampleapp</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
</project>`
your dependency as like below
<dependency>
<groupId>com.sample</groupId>
<artifactId>sampleapp</artifactId>
<version>1.0</version>
</dependency>
I have built a javaFX application using Maven.The problem is that the javaFX jar file generated from maven, doesn't contain dependencies included.
I have included the javaFx dependency this way :
<dependency>
<groupId>com.oracle</groupId>
<artifactId>javafx</artifactId>
<version>8.0.151</version>
<scope>system</scope>
<systemPath>C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\jfxrt.jar</systemPath>
</dependency>
I have also included the javaFx plugin :
<plugin>
<groupId>com.zenjava</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>${javafx.plugin.version}</version>
<configuration>
<vendor>Vendor</vendor>
<mainClass>org.bsh.generator.App</mainClass>
<jarFileName>CSVGenerator</jarFileName>
</configuration>
<executions>
<execution>
<id>create-jfxjar</id>
<phase>package</phase>
<goals>
<goal>build-jar</goal>
</goals>
</execution>
</executions>
</plugin>
When I build the jar using goal "build-jar", the jar generated doesn't include other dependencies. Any help please?
Dependencies scoped as system are not respected, this is intentional. Only provided and runtime scoped dependencies/libraries are respected by the plugin.
Disclaimer: I'm the maintainer of the javafx-maven-plugin.
I currently am using the Exec Maven Plugin and it works fine with:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<id>myExec</id>
<goals>
<goal>exec</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<executable>myExec</executable>
<arguments>
<argument>--foo=${basedir}/src/test/resources/test.xml</argument>
<argument>--output-directory=target/generated-sources/output</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
I am also using the build helper plugin as follows:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/output</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
This is incredibly verbose however and I want multiple maven modules to be able to use this program and not have to retype all the exec plugin specific XML along with the builder XML.
Question: How do I possibly combine these 2 into another plugin?
I have used the maven archetype generator to generate a sample maven plugin and have a Mojo class:
#Mojo(name = "touch", defaultPhase = LifecyclePhase.PROCESS_SOURCES)
public class MyMojo
extends AbstractMojo
{
public void execute()
throws MojoExecutionException
{
ExecMojo exec = new ExecMojo();
}
}
And have figured out how to create a new ExecMojo.
Question How do I add the arguments here as I would in the XML above? And how can I integrate these arguments into my plugin?
Instead of creating your own Maven plugin, which may reduce portability and maintenability of your project, you may consider the following approach instead:
Have a common parent pom
Configure the given plugins configuration, optionally in a Maven profile
In the concerned module, point to this parent. Optionally (in case of profiled configuration) activate it on demand when required.
A simple parent pom would look like the following:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>sample-maven-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<path.to.myexec>path</path.to.myexec>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<id>myExec</id>
<goals>
<goal>exec</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<executable>${path.to.myexec}\myExec</executable>
<arguments>
<argument>--foo=${basedir}/src/test/resources/test.xml</argument>
<argument>--output-directory=${project.build.directory}/generated-sources/output</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/output</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>myexec-profile</id>
<build>
<plugins>
<!-- optionally move here the configuration above -->
</plugins>
</build>
</profile>
</profiles>
</project>
Note the path.to.myexec property I added, to be overriden in children projects if required, in order to point to the correct relative path.
Then, once installed in your machine (or deployed in your company Maven repository), it can be referenced as following in any concerned Maven projects:
<parent>
<groupId>com.sample</groupId>
<artifactId>sample-maven-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
No need to re-declare the plugin configurations above and its verbose approach. They will be automatically part of the defaul build as part of the inherited build configuration from this parent.
The profiled approach can also be a solution if:
You want to reuse an existing parent pom already used by projects which don't need this configuration
You don't always need this behavior on your build and you want to activate it on demand
In such a case, you can then activate it via, as an example:
mvn clean package -Pmyexec-profile
Given that you already set the parent accordingly and you moved into the profile the configuration above.
Advantages of this approach:
lighter option than writing a new maven plugin (which needs to be written, tested, maintained, distributed, etc.)
easier for consumer modules to customize something: at any moment they can override parent's configuration as an exception
less fragile: just imagine what if another version of one of these plugins provides a bug fix important for you, that's easy to configure an XML, much less easy to change the customized maven plugin etc.
configuration remains centralized, transparently accessible and entry point for further governance
easier troubleshooting: at any moment a consumer module can run mvn help: effective-pom and see the merged full effective pom (as aggregate of parent and current pom) and check what it's actually running
How to skip parent plugin executions in certain modules
A simple (and often used) approach to execute this plugins only in certain modules while having the parent in common with other modules is the following:
Define a new property, let's call it skip.script.generation, with default value to true, defined in the parent pom.
Use this skip property in the skip configuration entry of the plugins above.
Re-define the property only in the concerned modules and set it to false. This will be the only configuration required for their pom.xml files, hence reduced to one line (keeping verbosity really low).
The exec-maven-plugin provides such a skip option, unfortunately the build-helper-maven-plugin doesn't. But that's not blocking us. We can still skip the two executions playing with their phase element, setting it to a non existing phase, like none and as such skipping them. This is suitable because the two executions are actually already attached to the same phase, generate-sources.
For this approach, let's rename our new property to script.generation.phase.
As an example:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>sample-maven-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<path.to.myexec>path</path.to.myexec>
<script.generation.phase>none</script.generation.phase>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<id>myExec</id>
<goals>
<goal>exec</goal>
</goals>
<phase>${script.generation.phase}</phase>
<configuration>
<executable>${path.to.myexec}\myExec</executable>
<arguments>
<argument>--foo=${basedir}/src/test/resources/test.xml</argument>
<argument>--output-directory=${project.build.directory}/generated-sources/output</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<phase>${script.generation.phase}</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/output</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>myexec-profile</id>
<build>
<plugins>
<!-- optionally move here the configuration above -->
</plugins>
</build>
</profile>
</profiles>
</project>
Note the <phase>${script.generation.phase}</phase> changes for both plugins. With its default value to none, this property is effectively disabling their executions by default.
In another module you would then have the following:
<parent>
<groupId>com.sample</groupId>
<artifactId>sample-maven-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<properties>
<script.generation.phase>generate-sources</script.generation.phase>
</properties>
And nothing else. That is. Maven during the build will re-define the property for a certain module and automatically replace it in the configuration inherited from its parent and as such enabling again the two executions above.
I have to import few custom Java classes in JasperReports's JRXML file.
I am able to do that using
<import value="org.ga.jasper.sample.MyCustomClass"/>
This works perfectly fine and I am able to run this jrxml and test my code.
Problem comes when I want to precompile this into .jasper file by using jasperreports-maven-plugin.
When doing a build, it complains saying it does not find my package and hence import is invalid.
package org.ga.jasper.sample does not exist
import org.ga.jasper.sample.MyCustomClass;
FYI, My Java code and .jrxml are in the same maven module but in different folders.
Following is the code from my plugin tag
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jasperreports-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>compile-reports</goal>
</goals>
</execution>
</executions>
<configuration>
<sourceDirectory>src/main/resources/jasper</sourceDirectory>
<outputDirectory>${project.build.directory}/jasper</outputDirectory>
<compiler>net.sf.jasperreports.engine.design.JRJavacCompiler</compiler>
</configuration>
<dependencies>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>4.5.1</version>
</dependency>
</dependencies>
</plugin>
By default, the plugin runs in the generate-resources phase, before the current module's classes have been compiled. You can change the plugin to run at the compile phase instead. See notes at bottom of page here:
http://mojo.codehaus.org/jasperreports-maven-plugin/usage.html
Also, see this similar q/a:
Compile JasperReports jrxml with scriptlet dependency in same project via Maven
This is how I solved the issue. Adding phase
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jasperreports-maven-plugin</artifactId>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile-reports</goal>
</goals>
</execution>
</executions>
<configuration>
<sourceDirectory>src/main/resources/jasper</sourceDirectory>
<outputDirectory>${project.build.directory}/jasper</outputDirectory>
<compiler>net.sf.jasperreports.engine.design.JRJavacCompiler</compiler>
</configuration>
<dependencies>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>4.5.1</version>
</dependency>
</dependencies>
</plugin>
I'm using JSR 269 as a way to analyze code during compilation and to fail it if needed.
I'm having troubles with displaying output of my annotation processor in maven (Ant does show the output)
I'm using javax.annotation.processing.Messager to display warnings and errors, but in maven I don't see it's output. (I do know it runs though, because it generates code like it should).
Any ideas?
I think you are running into a Maven bug or better a bug in the compiler plugin - MCOMPILER-66. When it comes to annotation processing the compiler plugin has several problems, eg also MCOMPILER-62. Really the best option imo is to disable annotation processing for the compiler plugin and use the maven-processor-plugin. In this blog post you can see how to use it. It looks like this:
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<version>1.3.7</version>
<executions>
<execution>
<id>process</id>
<goals>
<goal>process</goal>
</goals>
<phase>process-sources</phase>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>1.1.0.Final</version>
<scope>compile</scope>
</dependency>
</dependencies>
</plugin>
Note also how the annotation processor dependency is nicely scoped to the plugin only.
You can do this by enabling showWarnings flag in the maven-compiler-plugin configuration:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
</plugins>
</build>
See also https://github.com/Cosium/annotation-processor-logger#enable-all-logging-levels