Maintaining two different Spring boot versions in single Maven package - java

Let's say we have a shared-lib package. The pom for the same is as follows:
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.project.microservice-a</groupId>
<artifactId>shared-lib</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>shared-lib</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>com.projects.lib1.Application</start-class>
<java.version>1.8</java.version>
</properties>
....
....
</project>
There are projects using above shared library, having following pom.xml
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.projects.microservice</groupId>
<artifactId>accounts</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>accounts</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.3.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>com.project.microservice-a</groupId>
<artifactId>shared-lib</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
....
<dependencies>
Then there is one special subsystem running on Spring-boot-starter-parent.1.3.5 as parent, which won't take shared-lib with Spring-boot-starter-parent-1.2.3.
For importing shared-lib with Spring-boot.1.3.5, we need to modify pom.xml with parent as Spring 1.3.5 version and then build. This causes maintenance issues while building all subsystems, as Jenkins CI builds all JARs from Github with master branch. We can specify a separate branch manually, but maintaining same code for two branch is plain repetition.
Can anyone suggest a solution, which IMO may be a way to achieve one of these:
Create a package embedding both Spring 1.2.3 and Spring 1.3.5, and specifying required dependency version in other subsystems.
Bulid original client package with Spring Boot 1.3.5, and force it to use older version of Spring boot when used a dependency in required subsystems.

Let's say these are your dependencies for each project:
shared-lib:
spring-boot-foo:1.2.3
project-a:
shared-lib
spring-boot-bar:1.2.3
project-b:
shared-lib
spring-boot-baz:1.3.5
Now you want project-a to use 1.2.3 of all spring-boot libraries, and project-b to use 1.3.5, regardless of what spring-boot libraries shared-lib specifies?
Put the following in your pom.xml:
<properties>
<spring-boot.version>1.3.5.RELEASE</spring-boot.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
If your projects have a common parent pom.xml, you can put it there and simply change spring-boot.version value to something else per-project as you see fit. Otherwise you'll have to duplicate it.
Alternatively if this so-called BOM (<scope>import</scope>) doesn't work, you can list each dependency explicitly, e.g.:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-foo</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-bar</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-baz</artifactId>
<version>${spring-boot.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
Read more about managing spring-boot dependencies: http://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-build-systems.html
UPDATE:
You can manage other dependencies the same way as necessary. For example:
<properties>
<spring-data-releasetrain.version>Gosling-SR4</spring-data-releasetrain.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>${spring-data-releasetrain.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>

Related

maven dependency management mechanism, the priority about dependency management which using import scope

There are two examples.
example 1.
pom of project A is a simple pom:
<groupId>org.demo</groupId>
<artifactId>kafka-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<name>kafka-demo</name>
pom of project B:
<parent>
<artifactId>kafka-demo</artifactId>
<groupId>org.demo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>child-one</artifactId>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
In this example, spring-boot version of project B is 2.0.3.RELEASE.
example 2.
pom of project A.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/>
</parent>
<groupId>org.demo</groupId>
<artifactId>kafka-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<name>kafka-demo</name>
pom of project B is the same as the previous example.
<parent>
<artifactId>kafka-demo</artifactId>
<groupId>org.demo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>child-one</artifactId>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
In the example two, spring-boot version of project B is 2.3.1.RELEASE.
My question is in example 2, why the version of spring-boot is 2.3.1, rather than 2.0.3.
This scope is only supported on a dependency of type pom in the section. It indicates the dependency to be replaced with the effective list of dependencies in the specified POM's section. Since they are replaced, dependencies with a scope of import do not actually participate in limiting the transitivity of a dependency.
AFAIK, dependencyManagement that is directly declared in the POM is always stronger than imported dependencyManagement.
It is wrong to assume that an import is the same as declaring the list from the BOM at the same place.
So in your second example, one of the BOMs is used as parent, so it is directly used in the resulting effective POM, while the other is an import, which is less strong.

pom.xml showing error after being downloaded from https://start.spring.io/

trying to follow a tutorial on developing web application with spring, thymeleaf, hibernate and mysql database. I created the project using https://start.spring.io/ after downloading the zip, pom.xml shows error marking the heading tag
i have ran maven build and maven clean, both is successful but the error still is not going.
//I get the error on the first line with no hint at all
<?xml version="1.0" encoding="UTF-8"?>
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>net.codejava</groupId>
<artifactId>ProductManager</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ProductManager</name>
<description>Spring boot CRUD web app Example</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
You can try to downgrade your boot version to 2.1.4.RELEASE
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
OR
update your maven version to the newest one. Download maven
If you are using eclipse then it's eclipse issue,if you can just run the spring project and check whether is it running fine?
If it's running then don't worry.
Sorry for lot's of assumption as the question is ambiguous.
I have faced same problem in eclipse.The projects generated from start.spring.io didn't have any packaging info jar/war.
<groupId>net.codejava</groupId>
<artifactId>ProductManager</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
Now it is not showing any after adding "packing". Later maven>update project

How to exclude specific dependencies from spring-boot-starter-parent

I am using a legacy Spring application and want to migrate to Spring Boot. My intention is to use the spring-boot-starter-data-jpa. For this reason I have added following section in pom.xml (which manages all spring-boot-dependencies):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
But this is screwing up certain dependencies which I need to retain for time being. I am currently using Selenium dependencies (version 2.53.0; added transitively from another project) but spring-boot is fetching dependencies of 3.9.1.
I want to exclude 3.9.1 dependencies but the exclusion filter is not working as expected.
Just to summarize, I want to use spring-boot-starter-parent and spring-boot-starter-data-jpa but not the managed selenium-java from spring-boot-dependencies.
Appreciate any help in this regard.
Instead of messing around with <excludes> and then try to figure out what you need to include again (after figuring out what you excluded). Just override the version as explained here in the Spring Boot Reference Guide.
Assuming you are using the spring-boot-starter-parent as the parent you can just add a <selenium.version> to your <properties> section to specify which version you want.
<properties>
<selenium.version>2.53.0</selenium.version>
</properties>
This will make Spring Boot use the version you want.
Mention your dependency in pom.xml which you need to exclude in exclusion tag. Then excluded dependency will not be downloaded:
<dependency>
<groupId>sample.ProjectA</groupId>
<artifactId>Project-A</artifactId>
<version>1.0</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<!-- declare the exclusion here -->
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
</exclusion>
</exclusions>
</dependency>
Remove the deppendency from the starter pom. Use the exclsuions tag in pom.xml. For example to remove the actuator dependency
<?xml version="1.0" encoding="UTF-8"?>
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo-1</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

spring-boot-starter-web hibernate-validator dependency missing on Mac

I created spring boot project(Spring starter project) on STS(Spring tool suit), both of Window and Mac. Here is my pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Some of the dependency hierarchies are missing on Mac.
Example :
hibernate-validator
validation-api (missing on Mac)
jboss-loggin (missing on Mac)
classmate (missing on Mac)
I need that jars on Mac without modifying pom.xml.
I think I miss some environment Mac.
And I bought Mac 2 days ago. It's my first Mac.
If you want to use Hibernate Validator, you need to include it as explicit dependency:
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
Notice we don't specify version as Spring Boot will take care of it.
Other option is to use validation starter provided by Spring Boot:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Concerning your Windows/MacOS specific problems, it is some kind of misunderstanding. You need dependencies I mentioned. If you include them, it will work the same way on both platforms.

Maven module using spring-boot

I like to configure my applications in maven by creating modules like;
<groupId>com.app</groupId>
<artifactId>example-app</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>app-api</module>
<module>app-impl</module>
<module>app-web</module>
</modules>
The modules then use the 'example-app' as the parent.
Now I want use 'spring-boot' for my web application.
Is there a way to configure maven so that my 'app-web' is a spring-boot application?
The problem I'm facing is that you have to use spring-boot as a parent.
You don't have to use the spring-boot-starter-parent, it's just a way to get started quickly. All it provides are dependency management and plugin management. You can do both yourself, and you can use the spring-boot-dependencies (or equivalently the parent) to manage dependencies if you want a halfway step. To do that, use scope=import like this
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<type>pom</type>
<version>1.0.2.RELEASE</version>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Another alternative, is to include in the parent pom, the parent declaration for spring boot, as shown in this post
example-app pom.xml:
<project>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.5.RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
// rest of the example-app pom declarations
</project>
After that, in the modules poms (app-web, app-impl, etc.), you declare example-app as parent, but now you can include the starter dependencies as you would normally do in a regular project.
app-web pom.xml:
<project>
<parent>
<groupId>org.demo</groupId>
<artifactId>example-app</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<name>app-web</name>
<artifactId>app-web</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.demo</groupId>
<artifactId>app-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.demo</groupId>
<artifactId>app-impl</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
// rest of the app-web pom declarations
</project>
Regarding version management, what i used in these examples aren't exactly the best practices, but since is out of the scope of the question i skipped dependencyManagement and parent properties usage.
Also, if there is a starter that is used in every module, you can declare the dependency in the parent pom and then all the modules will inherit it (for example spring-boot-starter-test)

Categories