How to properly setup maven Spring Boot multi module project? - java

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

Related

Spring Boot Multi-Module maven project repackage failed

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.

How do I build the whole project, but then run a plugin goal in a single module?

I have a web application project structured give or take like this:
foo
│ pom.xml
│
├───foo-backend
│ pom.xml
│
└───foo-web
pom.xml
The module foo-web depends on foo-backend.
The parent POM contains the nested projects as modules:
...
<modules>
<module>foo-backend</module>
<module>foo-web</module>
</modules>
...
And the foo-web module enables the Tomcat plugin to correctly run this application without wrangling a separate app server installation:
...
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat6-maven-plugin</artifactId>
<configuration>
...
</configuration>
</plugin>
...
The problem I have is that if I run just this plugin for foo-web, the module foo-backend doesn't get rebuilt, and any old build output is used instead.
I set up IDEA to just build the project as part of the run configuration, but I'd like to keep as much of this not IDE-specific as possible, and as one cognitive step as possible.
Is there a way to tell Maven in a one-liner or configuration to:
compile the whole project; and then
tomcat6:run the foo-web submodule?
You can create an execution of the tomcat maven plugin attached to one of the maven phases. Since you want it to run after everything is compiler, it seems like the phase process-classes would be appropriate.
Also, I assume that you don't want to always run tomcat when trying to run maven phases, so it's better to make this execution conditionally.
<profiles>
<profile>
<activation>
<property>
<name>runTomcat</name>
</property>
</activation>
<id>run-tomcat-on-compile</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat6-maven-plugin</artifactId>
<executions>
<execution>
<id>one</id>
<phase>process-classes</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
To compile and run tomcat:
mvn process-classes -PrunTomcat

How to include opencv in an intellij sub module (maven)

I'm using IntelliJ IDE with maven. I have a project (main module) with a parent pom, that includes 2 sub modules, each with their own pom.
<!-- main pom module part -->
<packaging>pom</packaging>
<modules>
<module>ModuleA</module>
<module>ModuleB</module>
</modules>
<!-- example for sub module pom -->
<parent>
<artifactId>main-module</artifactId>
<groupId>my.main.module</groupId>
<version>0.5.0</version>
</parent>
Image ModuleA includes the OpenCV Java wrapper and ModuleB is an executable java program (having the main class) using ModuleA.
The compiling works fine, but when I run ModuleB with having set the library path in the launcher, I'll get the following error for ModuleA:
java.lang.NoClassDefFoundError: org/opencv/core/Core
Any suggestions how to fix this?
Ok, I found a solution my self. The problem was, that the opencv java wrapper was included with a system path. Now I use the maven install plugin within the validate live cycle step instead.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<groupId>org.opencv</groupId>
<artifactId>opencv</artifactId>
<version>3.3.0</version>
<packaging>jar</packaging>
<file>${project.basedir}/../lib/opencv/opencv-330.jar</file>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Works fine for me, but was not the way I wanted it to be... The system-path type dependency seems to be buggy in maven.
Try to add the following dependency to your ModuleA:
<dependency>
<groupId>nu.pattern</groupId>
<artifactId>opencv</artifactId>
<version>2.4.9-7</version>
</dependency>

Maven versions plugin: reference a rule.xml from a maven dependency?

I am using the mvn versions:display-dependency-updates versions:display-plugin-updates goals to check for dependencies or plugins updates.
My maven project is a multi module one, which looks like this:
moduleA
|- moduleB1
| |- moduleC
|- moduleB2
|- build-config/rules.xml
Since there is some unwanted updates, like betas I don't want, I've made a filter (which works). I use it like that:
<profile>
<id>maven-version-plugin-1</id>
<activation>
<property>
<name>version.rules.uri</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<configuration>
<rulesUri>${version.rules.uri}</rulesUri>
</configuration>
</plugin>
</plugins>
</build>
</profile>
I am forced to use a profile and a property version.rules.uri because it must refer to an existing file (by default it points to ./build-config/rules.xml, but it is also in my settings.xml with an absolute path).
I'd like to avoid that by:
publishing an independent build-config project
referencing this project using some uri: m2:myGroupId:myArtifactId:version:scope:jar/rules.xml
Now the question: is there an implementation of Maven Wagon Plugin (which is used by maven versions plugin) that allow for reading a repository entry such as a jar ?
This works for me:
<rulesUri>file:///${session.executionRootDirectory}/maven-version-rules.xml</rulesUri>
For the meaning of the variable ${session.executionRootDirectory}, see
Finding the root directory of a multi module maven reactor project.
Based upon the documentation for the plugin this is possible:
You can provide your ruleset xml file also within a jar, if you want to distribute your ruleset xml as Maven artifact. Therefore you have to declare the containing jar as direct dependency of the versions-maven-plugin and to use classpath as protocol.
I just tried it out and got it to work.
Create a new folder for the new version-rules artifact, as so:
version-rules
|- files
\- version-rules.xml
\- pom.xml
The pom.xml is pretty basic:
...
<artifactId>my-version-rules</artifactId>
<packaging>jar</packaging>
<build>
<defaultGoal>package</defaultGoal>
<resources>
<resource>
<directory>files</directory>
<filtering>false</filtering>
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>
</plugins>
</build>
...
run a mvn install to install this artifact.
Then, in the other pom, you configure the versions plugin as follows:
...
<build>
...
<pluginManagement>
...
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.7</version>
<configuration>
<rulesUri>classpath:///version-rules.xml</rulesUri>
</configuration>
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>my-version-rules</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</plugin>
...
</plugins>
...
</pluginManagement>
...
</build>
...

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