What is the difference between tags parent, dependency and plugin (Maven) - maven

I am confused by the fact that POM.xml contains parent, dependency and plugin. Somethings something specified with parent must be again included in dependency, for example
<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.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<url>http://maven.apache.org</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
</dependencies>
</project>
Why do I have to specify a dependency twice ? How can I use these three tags ?

The parent is a POM which gets "inherited", it basically gets combined with your current POM by means of overwriting. (You can use "mvn help:effective-pom" to print the combined result). So all the dependencies and plugins in the parent will become yours (and all managed dependency versions, which is in case of spring-boot a majority).
The dependendency specifies artifacts you need on your classpath for compiling or testing or running your project (depending on its scope).
Whereas plugin is a artifact which gets executed at build time (like a compiler, report generator and stuff).
I would suggest to read a good tutorial or book on maven, my simple explanation is not enough to make good use of it. https://maven.apache.org/articles.html

Related

Not able to access maven dependency from a common folder in same directory

I am using a multi-module approach in Spring boot application. My directory structure is like
package name
|_bom
|__common-test
|__service
|_src/test/java/TestFile.java
I have put test related dependencies in pom.xml of common-test and accessing them in test folder of service. I am able to access most of the dependencies in TestFile.java but not the dependency mentioned below. This is the last dependency in pom.xml of common-test. Following the same structure I am able to use mockito dependency but not this one.
I have defined related properties in bom/pom.xml which are to be used in common-test/pom.xml. Using this approach for first time and not sure how to achieve this. Basically, I need to maintain test related dependencies in common-test pom.xml and not include it in service.
import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport;
pom.xml of common-test have this 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">
<parent>
<artifactId>projeectname</artifactId>
<groupId>in.packagename.mint</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>projeectname-common-test</artifactId>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>in.packagename.mint</groupId>
<artifactId>projeectname-bom</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- project dependencies -->
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-migrationsupport</artifactId>
</dependency>
</dependencies>
</project>
pom.xml of bom
<?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 coordinates -->
<parent>
<groupId>in.packagename.mint</groupId>
<artifactId>projectname</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>projectname-bom</artifactId>
<properties>
<junit.jupiter.migration-support.version>5.7.0</junit.jupiter.migration-support.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>3.5.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-migrationsupport</artifactId>
<version>${junit.jupiter.migration-support.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
I have tried deleting .m2 folder and building all these bom, common-test, etc. separately and runnning mvn install but this dependency issue is not resolved and not able to import it in service test folders.

Download/import all dependencies from Spring IO

I work for a large organization where all development tools must go through a rigorous certification process and security assessment. I want to have Spring IO Brussels SR2 certified, along with Apache Maven.
I'd like to provide them with a ZIP file containing all JARs (dependencies and transitive dependencies) of the Spring IO platform so they can do the security assessment on it.
Being a new Maven user, I've created a new Maven project in Eclipse, and simple added this in 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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>my.company</groupId>
<artifactId>MySpringApp</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>MySpringApp Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>Brussels-SR2</version>
<type>pom</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>MySpringApp</finalName>
</build>
</project>
The project compiles and packages correctly, but it's not importing/adding any JARs to the packaged WAR file. I've also tried to change the scope to compile.
Is it possible? Is it because it's a bill of material?
Thank you
According to the Website you have to enable the dependency-tree using
<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>my.company</groupId>
<artifactId>MySpringApp</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>MySpringApp Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>Brussels-SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<build>
<finalName>MySpringApp</finalName>
</build>
</project>
Eclipse and Maven are designed to be able to work alone, a bit of experiences is required to let them work together, often a cleanup using Update Project ... (project-rightclick/maven) is required
I ended up downloading the dependency versions list into a CSV file, then loop through it in a simple Java class, outputting the results in a tag manually. Then, I was able to copy/paste all those tags into my pom.xml file and then get all those dependencies resolved by Maven.
Finally, I have taken the content of /target/WEB-INF/lib.

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.

share entities between maven projects

I'm migrating one monolithic project to a microservices architecture and just for sake of make things work, I'm basically copy-pasting the model and repository classes between the projects. Turns out that I know that I can create one maven module with these classes and add it as dependency of any other project, but one thing comes to my mind: These classes are mapping of my database, and in this monolithic project, my application.yml contains all the info related to database access. If I decouple it and put this models and repositories to a separated module, where should this config lives? inside the module, inside the project that have it as dep.?
Ok, I tried a lot of things, and this is where I'm now:
I created a maven project that depends on spring boot jpa starter and added the classes (models, repos, etc) and added this project as dependency of another bigger project, but I'm seeing this error now:
[ERROR] Failed to execute goal on project github: Could not resolve dependencies for project com.inkdrop:github:jar:0.0.1-SNAPSHOT: Failure to find com.inkdrop:commons:jar:1.0-SNAPSHOT in https://repo.spring.io/snapshot was cached in the local repository, resolution will not be reattempted until the update interval of spring-snapshots has elapsed or updates are forced -> [Help 1]
it this case, commons is the project I want to add as depedency of github since it contains the models and repos
Here is my commons 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.inkdrop</groupId>
<artifactId>commons</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Commons files</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>com.inkdrop.App</start-class>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>
spring-boot-starter-data-jpa
</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>${spring-loaded.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>

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