Building Spring Boot Application - Maven Errors - spring

I've been trying to package my spring-boot application into a war file but the errors keep coming, I've solved 3 so far but I'm stuck with this one.
Error
Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:1.3.5.RELEASE:repackage
(default) on project pns: Execution default of goal org.springframework.boot:spring-boot-maven-plugin:1.3.5.RELEASE:repackage failed:
A required class was missing while executing org.springframework.boot:spring-boot-maven-plugin:1.3.5.RELEASE:repackage:
org/springframework/boot/loader/tools/LaunchScript
App Properties
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<start-class>iq.pns.PushNotificationServerApplication</start-class>
</properties>
Build Config
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>${start-class}</mainClass>
<layout>WAR</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
</plugin>
</plugins>
</build>
Any ideas why this is happening?
Thanks in advance.

Turns out to be a corrupted jar in the Maven cache, just like #AndyWilkinson suggested.
Solved by deleting the ~/.m2/repository folderand letting Maven re-download everything.

Related

Build docker image with a custom name using Spring Boot Maven plugin

In my pom.xml file, I configured the imageName to be the project name by default:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-image</goal>
</goals>
</execution>
</executions>
<configuration>
<imageName>${project.name}</imageName>
</configuration>
</plugin>
</plugins>
</build>
When I run mvn spring-boot:build-image, it works fine.
When I try to override the image name using mvn spring-boot:build-image -Dspring-boot.build-image.imageName=customname, I was expecting to get a docker image named customname. I'm still getting the project name instead. This means that maven plugin is still using ${project.name}.
Am using the command in a wrong way?
In your case the name of image always comes from plugin configuration <imageName>${project.name}</imageName>. If you want to support both options to specify target image name (i.e. maven base configuration and CLI) you make take advantage of using maven properties, i.e.:
<properties>
<module.image.name>${project.name}<module.image.name>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-image</goal>
</goals>
</execution>
</executions>
<configuration>
<imageName>${module.image.name}</imageName>
</configuration>
</plugin>
</plugins>
</build>
after that both mvn spring-boot:build-image and mvn spring-boot:build-image -Dmodule.image.name=customname (note another name of system property) will work as expected

understanding Spring Boot Maven Plugin in Multi-Module projects

I'm learning about Spring Boot multi module projects and I try to understand what exactly does spring boot maven plugin.
For example I have 2 different projects. In the first project I have the spring boot maven plugin in the web module:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.0.4.RELEASE</version>
<configuration>
<mainClass>dgs.web.DemoApplication</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
And in the second project I have this plugin in the data module:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
And this is in the parent pom of the 2nd project:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Can somebody explain me what exaclty does this spring boot maven plugin especially in the second project? And why there is no reference about mainClass. I see this mainClass tag only in the first project.
The maven plugin is for packaging and executing via Maven.
You should read the docs:
https://docs.spring.io/spring-boot/docs/current/reference/html/build-tool-plugins-maven-plugin.html
https://docs.spring.io/spring-boot/docs/2.0.4.RELEASE/maven-plugin/

Spring Boot setup does not resolve dependencies when assembling WAR [duplicate]

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>

Using bootRepackage=false in Maven

Does anybody know what is the Gradle bootRepackage=false equivalent in Maven? How can you configure spring boot plugin to not generate boot war?
The problem that I face is that I have a multi module project. When I build the project with mvn clean install, the module jar contain the entire libraries defined in its pom.
The solution above applies to older versions. Spring-boot maven plugin 1.2 introduced:
<properties>
<spring-boot.repackage.skip>true</spring-boot.repackage.skip>
</properties>
Skip the execution. Default value is: false. User property is: spring-boot.repackage.skip.
https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/html/#goals-repackage
and
https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/html/#goals-repackage-parameters-details-skip
You can skip the repackage goal from being executed by setting the skip attribute to true:
Skip the execution. Default: false.
In your plugin configuration, you can then have:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.3.2.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<skip><!-- true or the result of a Maven/system property for example --></skip>
</configuration>
</execution>
</executions>
</plugin>
It`s works for me
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

After deploy in Nexus, the variables in POM.xml are not resolved?

I use Maven Multi-Modul, Jenkins builds and then deploy in Nexus...
I'm using in my Pom files many variables that I have defined in parent-pom part propertis
I would have after the build/deploy resolved the variables in Pom-Nexus.
I know that this is feasible, because I made a few years ago....
I think, i found it
<build>
<plugins>
<plugin>
<groupId>com.sap.prd.mobile.ios.maven.plugins</groupId>
<artifactId>resolve-pom-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>resolve-pom-props</id>
<goals>
<goal>resolve-pom-props</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Resources