Spring Boot Multi-Module maven project repackage failed - java

I'm currently following John Thompson's Spring Framework Beginner to Guru course. I follow his step by step procedures on creating multi module maven project for spring pet clinic on spring boot. When I clicked package on my root module it says repackaged failed, unable to find main class.
<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>
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.6.RELEASE:repackage (repackage) on project pet-clinic-data: Execution repackage of goal org.springframework.boot:spring-boot-maven-plugin:2.1.6.RELEASE:repackage failed: Unable to find main class -> [Help 1]

Remove
<configuration>
<skip>true</skip>
</configuration>
and add "spring-boot.repackage.skip" property like the following:
<artifactId>pet-clinic-data</artifactId>
<properties>
<spring-boot.repackage.skip>true</spring-boot.repackage.skip>
</properties>

The spring-boot-maven-plugin should only be in the pom.xml of the module that contains the main class. It looks like you have this plug in on (or inherited by) a simple jar module that the main module will use as a dependency.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
The main class is annotated with #SpringBootApplication

you are using spring-boot-maven-plugin:2.1.6.RELEASE.
since Spring-Boot 2 you don't need the spring boot plugin anymore.
you can use the following code after declaring the artifact id of your module.
<artifactId>pet-clinic-data</artifactId>
<properties>
<spring-boot.repackage.skip>true</spring-boot.repackage.skip>
</properties>

Error speaks for itself. The executor cannot find your main class. It has nothing to do with your pom.xml. but has everything to do with the environment you are using to build and run your spring boot project.
If you are using IntelliJ, go to Run/Debug configuration (Add configuration on the screenshot, in your case it could be something else) and make sure your main class exits. Then tap your shift two times and type Invalidate Caches/Restart and do both. Then it should work as expected.

Related

How could I only deploy a specific module to my remote repository?

I have a Maven project with several modules, but I only want one to be deployed to my remote repository server. I tried to put the distributionManagement in the pom of my module that I want to deploy, but it can only be put in the main pom. How could I do this?
Thank you.
Edit: Fixed by putting
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M1</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
to the modules that I don't want to be deployed.
You can do that by setting the skip property of the maven deploy plugin to true in all other modules.
But: Why is it multi-module project if you only need one of the modules later? Shouldn't it be split up?
Make this module an independent project. Remove parent section from its pom file.

How to properly setup maven Spring Boot multi module project?

After some research try and fail, I am still not able to put my head around a clear way to do the following:
Project-All - "Ability to combine Module #1 & Module #2 and to run in dev (Test full solution)"
|
+ Module_1 - "Ability to run independently in dev (Different dev team)"
| - pom.xml
+ Module_2 - "Ability to run independentlyin dev (Different dev team)"
| - pom.xml
- pom.xml
I would like to build and run module_1 and module_2 separately, as well as assembled. After trying Assembly Plugin for Maven without significant success (Or over-complicated solution), I am now trying with Spring Boot Plugin for Maven which seems way simpler to use.
So would we have any recommendation on how to properly build such setup with Spring Boot Plugin for Maven?
Thanks
Here is one approach you can try :
In the main module POM you could use the maven release plugin like follows :
...
<packaging>pom</packaging>
<modules>
<module>module1..</module>
<module>module2..</module>
</modules>
...
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<goals>install</goals>
<autoVersionSubmodules>true</autoVersionSubmodules>
</configuration>
</plugin>
</plugins>
</build>
If you wish to build the submodules in such a way that they could run on its own :
your could use maven repckage goal in the module pom as follows:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
There is possibility providing the name of the main class in this configuration.
Checkout the official documentation

Maven doesn't find imported class from another module but Intellij does

I have multi-module maven project. The acceptance-tests module has dependency from api module in pom.xml (Replacing real company name by xxx to keep confidentiality). I am trying to import some classes from api module in my acceptance-tests.
Here is my pom.xml dependency of acceptance-tests module:
<dependency>
<artifactId>xxx-api</artifactId>
<groupId>com.xxx</groupId>
<version>${xxx.api.version}</version>
</dependency>
The api module separately is being installed and packaged (mvn install, mvn package) by maven without any issue. The jar file is being created in my local .m2.
However, when I try to compile the acceptance-tests module, I get a compilation error saying that the the classes cannot be imported because the package is not found.
Here is the actual error:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project xxx-acceptance-tests: Compilation failure: Compilation failure:
[ERROR] /Users/andranik_chorokhyan/mydisk/Projects/XXX/automation/xxx-project-test-automation/xxx-acceptance-tests/src/main/java/com/xxx/xxx/utilities/api/ApiPayloadUtils.java:[17,38] package com.xxx.domain.dto does not exist
[ERROR] /Users/andranik_chorokhyan/mydisk/Projects/XXX/automation/xxx-project-test-automation/xxx-acceptance-tests/src/main/java/com/xxx/xxx/utilities/api/ApiPayloadUtils.java:[18,38] package com.xxx.domain.dto does not exist
[ERROR] symbol: class MappingData
[ERROR] location: class com.xxx.utilities.api.ApiPayloadUtils
One more interesting fact is that there is no error visible in Intellij IDEA. No red underline, no compilation error, no problem with navigating to the appropriate imported file.
And in reality, the com.xxx.domain.dto package does exist and the MappingData class as well.
I removed whole xxx directory from my local .m2 repository and executed mvn clean dependency:resolve command. It succeeded as well.
Does anybody know what's the problem here and how it can be solved?
Thanks in advance!
Finally I have found the solution. Thanks JF Meier and khmarbaise for hints.
It appeared Maven doesn't allow dependency from executable jar. This was my case. My api module was an executable Spring Boot application and not reusable library.
So, the solution was the following:
It was necessary to find the Application.java file in api module.
Add maven-jar-plugin with exclusion of the Application.java file and specification of some classifier
Making dependency in acceptance-tests module from the above specified classifier instead of standard jar
Plugin specification in api module below:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>qa</classifier>
<excludes>
<exclude>**/Application*</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
Dependency in acceptance-tests module below:
<dependency>
<artifactId>xxx-api</artifactId>
<groupId>com.xxx</groupId>
<version>${api.version}</version>
<classifier>qa</classifier>
</dependency>
I was also getting symbol not found errors while compiling with maven, and the solution is for spring boot 2 you need to configure plugin as below, classifier exec
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
If you are working with spring boot 1
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>

How do I tell Spring Boot which main class to use for the executable jar?

Execution default of goal
org.springframework.boot:spring-boot-maven-plugin:1.0.1.RELEASE:repackage
failed:
Unable to find a single main class from the following candidates
My project has more than one class with a main method. How do I tell the Spring Boot Maven plugin which of the classes it should use as the main class?
Add your start class in your pom:
<properties>
<!-- The main class to start by executing java -jar -->
<start-class>com.mycorp.starter.HelloWorldApplication</start-class>
</properties>
or
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.mycorp.starter.HelloWorldApplication</mainClass>
</configuration>
</plugin>
</plugins>
</build>
For those using Gradle (instead of Maven) :
springBoot {
mainClass = "com.example.Main"
}
If you do NOT use the spring-boot-starter-parent pom, then from the Spring documentation:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.1.3.RELEASE</version>
<configuration>
<mainClass>my.package.MyStartClass</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
For those using Gradle (instead of Maven), referencing Spring Boot Gradle Plugin Reference Guide (as of Gradle 7.6 and Spring Boot 3.0.0):
The main class can also be configured explicitly using the task’s mainClass property:
tasks.named("bootJar") {
mainClass = 'com.example.ExampleApplication'
}
Alternatively, the main class name can be configured project-wide using the mainClass property of the Spring Boot DSL:
springBoot {
mainClass = 'com.example.ExampleApplication'
}
If you're using spring-boot-starter-parent in your pom, you simply add the following to your pom:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Then do your mvn package.
See this Spring docs page.
A very important aspect here is to mention that the directory structure has to be src/main/java/nameofyourpackage
I tried the following code in pom.xml and it worked for me
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>myPackage.HelloWorld</mainClass>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<fork>true</fork>
<executable>D:\jdk1.8\bin\javaw.exe</executable>
</configuration>
</plugin>
</plugins>
Since Spring Boot 1.5, you can complete ignore the error-prone string literal in pom or build.gradle. The repackaging tool (via maven or gradle plugin) will pick the one annotated with #SpringBootApplication for you. (Refer to this issue for detail: https://github.com/spring-projects/spring-boot/issues/6496 )
I had renamed my project and it was still finding the old Application class on the build path. I removed it in the 'build' folder and all was fine.
Have seen this issue with Java 1.9 and SpringBoot 1.5.x, when main-class is not specified explicitly.
With Java 1.8, it is able to find main-class without explicit property and 'mvn package' works fine.
If you are using Grade, it is possible to apply the 'application' plugin rather than the 'java' plugin. This allows specifying the main class as below without using any Spring Boot Gradle plugin tasks.
plugins {
id 'org.springframework.boot' version '2.3.3.RELEASE'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'application'
}
application {
mainClassName = 'com.example.ExampleApplication'
}
As a nice benefit, one is able to run the application using gradle run with the classpath automatically configured by Gradle. The plugin also packages the application as a TAR and/or ZIP including operating system specific start scripts.
For Kotlin with Gradle:
springBoot {
mainClass.set("com.example.MainKt")
}

Get sources of a snapshot dependency on Eclipse

Something bother me a lot...
On a big project with many dependencies, some of them are set as SNAPSHOT in Maven2.
The matter is that it seems i can't get the sources through Eclipse without loading the project or fixing the dependency to the last release.
For debugging, it's really annoying me...
EDIT
This is what i get in eclipse maven console:
26/08/10 11:31:46 CEST: Downloading http://repo-maven/archiva/repository/snapshots/com/blabla/1.1-SNAPSHOT/blabla-1.1-20100824.213711-80-javadoc.jar
26/08/10 11:31:47 CEST: Could not download sources for com.blabla:blabla:1.1-20100824.213711-80
On archiva i can see the deployed stuff i want to retrieve in eclipse...
Repository snapshots
Group ID com.blabla
Artifact ID blabla
Version 1.1-20100824.213711-80
Packaging jar
Parent com.blabla bla 1.1-SNAPSHOT (View)
Other Versions 1.1-20100824.213535-79
I can download sources of this artifact with my browser but not within Eclipse... Any idea?
The matter is that it seems I can't get the sources through Eclipse without loading the project or fixing the dependency to the last release. For debugging, it's really annoying me...
Well, these modules are probably not publishing source JARs as part of the "regular" build process (i.e. outside the release). If these modules are under your control (which is my understanding), configuring the Maven Source Plugin to produce source JARs for them and deploying them in your corporate repo should solve the problem. From the Usage page:
Installing the sources along with your artifact
There are two ways to do this. You can
either bind this plugin to a phase or
you can add it to a profile. The goals
source:jar-no-fork and
source:test-jar-no-fork are preferred
for binding the goal to the build
lifecycle.
Installing the sources using a phase binding
Here is how you would configure the
plugin in your pom.xml to run
automatically during the verify phase:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>verify</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
We are using the verify phase here
because it is the phase that comes
before the install phase, thus making
sure that the sources jar has been
created before the install takes
place.
Installing the sources using a profile
If you want to install a jar of your
sources along with your artifact
during the release process, you can
add this to your pom.xml file:
<project>
...
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
...
</project>
Using a profile would probably be a good idea so that building source JARs will only be done by the build running at the CI server level but not on developer machines.

Categories

Resources