How a maven dependecy can be defined without version tag? - maven

I have a pom which works without defining dependency version in pom works fine and another one without dependency version which does not work.
The one which works:
<project>
<parent>
<artifactId>artifact-parent</artifactId>
<groupId>group-parent</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
</dependency>
</dependencies>
</project>
This one which does not work:
<project>
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
</dependency>
</dependencies>
</project>
The only thing differ in these two seems to be:
<parent>
<artifactId>artifact-parent</artifactId>
<groupId>group-parent</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
Second one does not work it seems fine to me but my question is why the first one works ?
Quoted from maven pom reference :
This trinity represents the coordinate of a specific project in time,
demarcating it as a dependency of this project.
So my question is how the first one is working?

The main thing to notice here is:
<parent>
<artifactId>artifact-parent</artifactId>
<groupId>group-parent</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
Version of the dependency looks like to be defined in the parent pom. This can be something like this:
<project>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Again quoting from the doc :
This is because the minimal set of information for matching a
dependency reference against a dependencyManagement section is
actually {groupId, artifactId, type, classifier}.
Here we did not need to define the {type, classifier} as it is same as default value which is as follows :
<type>jar</type>
<classifier><!-- no value --></classifier>
If this value differ form the default, you need to define it explicitly in both parent pom and child pom.

Related

How to force maven dependency version via dependencyManagement in parent pom?

Let's say B:1.0.1 has transitive dependency A:1.0.1, but the child project is supposed to depend on A:1.0.2 (with intentional overriding transitive dependencies).
It is easy to discover that the order of dependencies in <dependencyManagement> affect versions overriding, so adding A:1.0.2 in the child pom just before B:1.0.1 would force using A:1.0.2 even as a dependency for B:1.0.1.
In this case I'm looking for a way to declare A:1.0.2 in the parent pom, and remove boilerplate from all its children. Unfortunately, the following setup leads to using both versions in the final artifact: A:1.0.1 (comes as a dependency of B:1.0.1) and A:1.0.2 (comes from the explicit declaration in the parent pom).
How to force using version A:1.0.2 in all child projects, keeping the declaration in the parent?
Parent pom:
<groupId>my-group</groupId>
<artifactId>my-parent</artifactId>
<version>0.0.1</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>g</groupId>
<artifactId>A</artifactId>
<version>1.0.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Child pom:
<parent>
<groupId>my-group</groupId>
<artifactId>my-parent</artifactId>
<version>0.0.1</version>
</parent>
<artifactId>my-child</artifactId>
<version>0.0.1</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>g</groupId>
<artifactId>A</artifactId>
<!-- version 1.0.2 comes from the parent pom -->
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>g</groupId>
<artifactId>B</artifactId>
<version>1.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
You are using the dependencyManagement incorrectly.
If A and B are jar artifacts, you should not have the tags
<type>pom</type>
<scope>import</scope>
These are for BOMs only.

Why spring-boot-build parent dependency is missig?

I know that when I am inheriting from spring-boot-starter-parent I'll have this inheritance chain:
my-project => spring-boot-starter-parent => spring-boot-dependencies => spring-boot-build => maven parent pom
=>(means inherit)
Indeed That's what I saw in Github. And I believe It is true.
But when I am navigating through these POMs on my IDE (IntelliJ) the spring-boot-dependencies does not declare a parent pom (which should be spring-boot-build according to GitHub)
Why there is no inheritance specified in spring-boot-dependencies in my IDE(there is one GitHub)? I am missing something?
Edit
My project's pom:
<?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 https://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.2.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
It doesn't show the parent POM relation in your IDE, because in the pom file for spring-boot-dependencies, that's deployed to the central Maven repository, there is no parent tag: https://search.maven.org/artifact/org.springframework.boot/spring-boot-dependencies/2.2.0.RELEASE/pom
Eclipse will load that pom file, not the one from the source repository.
So it looks that the build process from Spring Boot removes the parent tag, when it's deploying the pom to Maven Central.
A reason for this could be (and the naming suggests it), that spring-boot-build only provides configuration and dependencies related to the build process for Spring Boot itself, but isn't necessary or desired for applications using it.

Spring Boot Application cannot be resolved to a type but I imported it in pom.xm

I have added the spring boot in pom.xml but still it is giving an error.
Can anyone help me.
It is giving error The import org.springframework.boot.autoconfigure.SpringBootApplication cannot be resolved
and
SpringBootApplication cannot be resolved to a type
My pom. xml is
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.webapp</groupId>
<artifactId>proj1</artifactId>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
</parent>
<version>0.0.1-SNAPSHOT</version>
<name>proj1 Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</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>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>proj1</finalName>
</build>
</project>
Your pom looks almost correct, but few things to note
No need to add dependency 'javax.servlet-api', it is available from 'spring-boot-starter-web'
And you probably you may be missing the 'spring-boot-maven-plugin', it is not compulsory but you may want that in your project. Where it provides some easy maven goals for you to run.
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
if your running eclipse you can generate your .classpath files just as usual
mvn eclipse:eclipse, once done your ide should look fine
then mvn spring-boot:run should set your application running

Spring Boot multi module Maven project deployment

We have multi module Maven project with following modules:
Commons
Model
Repository
Service
Web
We've googled around and we didn't found a solution how to make one executable jar when project has this kind of structure.
Here is the parent 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>...</groupId>
<artifactId>...</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>Model</module>
<module>Web</module>
<module>Service</module>
<module>Repository</module>
<module>Common</module>
</modules>
<packaging>pom</packaging>
<name>Api</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<mssql.jdbc.driver.version>4.2</mssql.jdbc.driver.version>
<apache.commons.lang.version>3.3.2</apache.commons.lang.version>
<apache.commons.collection.utils.version>4.1</apache.commons.collection.utils.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-envers</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
So, very basic parent pom.xml. We know that we can't use Spring Boot Maven plugin when packaging is pom, so we've defined it in pom.xml from Web module:
<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">
<parent>
<artifactId>...</artifactId>
<groupId>...</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>...</groupId>
<artifactId>...</artifactId>
<packaging>jar</packaging>
<name>...</name>
<dependencies>
<dependency>
<groupId>...</groupId>
<artifactId>Service</artifactId>
<version>${project.version}</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-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.4.1.RELEASE</version>
<configuration>
<mainClass>...App</mainClass>
</configuration>
<!--<executions>-->
<!--<execution>-->
<!--<goals>-->
<!--<goal>repackage</goal>-->
<!--</goals>-->
<!--</execution>-->
<!--</executions>-->
</plugin>
</plugins>
</build>
</project>
The rest of pom.xmls from other modules are pretty much the same: Service's pom.xml includes Repository.jar, Repository includes Model and Common.
Problem 1: when we run mvn install, plugin creates fat jar in target folder of web module. But when we try to run it with java -jar name-of-jar it gives java.lang.NoClassDefFoundError about some class from Service module - and you can see from Web's pom.xml that Service module is included (there is also a Service.jar packed as library in Web.jar)
Problem 2: what's interesting is that Service.jar inside of Web.jar also contains pretty much all the dependencies that are already present in Web.jar - basically they are duplicated.
Did anyone managed to create executable fat jar using Spring Boot Maven plugin and Maven Module project structure?
Problem 1 & 2
You should not have devtools as dependency in your parent pom.
Move the following to the web/spring-boot module:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
If you look at devtools's pom, it includes the following:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
So your service jar ends up with some spring boot dependencies.

Maven Plugin for Version Management

I am looking for a possibility to manage my maven project versions.
I have some maven modules in my maven project and some of these modules are depending on others of these modules.
I want to define the version to work with globally for every module or dependency.
Is this somehow possible?
Something like
globalVersion=2.0
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>${globalVersion}</version>
But as i said, not in each single pom. I mean globally for all my poms in my maven modules.
(I assume you have a parent pom common for all your modules.)
define a property in the parent pom:
<properties>
<globaleVersion>1.0.0</globalVersion>
</properties>
And define a <dependencyManagement> section in the parent pom too:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>${globalVersion}</version>
</dependency>
<dependency>
<groupId>A</groupId>
<artifactId>A</artifactId>
<version>${globalVersion}</version>
</dependency>
</dependencies>
</dependencyManagement>
And in you modules define dependencies without specifying the version (maven will find it from the dependencyManagement section of the parent)
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>test</artifactId>
</dependency>
<dependency>
<groupId>A</groupId>
<artifactId>A</artifactId>
</dependency>
</dependencies>

Resources