how to automatically update maven dependencies in a multi-level project? - maven

At my workplace, different groups works on providing different services.
My team consumes these services. Currently, whenever a new version of Service is rolled out, we manually change the pom.xml to the latest version of dependency and then make a build. I am wondering if there is an automatic way of pulling latest release into build.
Here is an example to explain:
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">
<groupId>com.company.product</groupId>
<artifactId>User-Application</artifactId>
<version>1.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<Service1-version>1.0.2</Service-1>
<Service2-version>1.1.2</Service-2>
<Service3-version>2.0.2</Service-3>
</properties>
<dependencies>
<dependency>
<groupId>com.company.product</groupId>
<artifactId>Service1</artifactId>
<version>${Service1-version}</version>
</dependency>
<dependency>
<groupId>com.company.product</groupId>
<artifactId>Service2</artifactId>
<version>${Service2-version}</version>
</dependency>
<dependency>
<groupId>com.company.product</groupId>
<artifactId>Service3</artifactId>
<version>${Service3-version}</version>
</dependency>
.....
....
</project>
When new release of each service is made, we manually change the pom.xml to get the latest dependency. How can this be managed automatically?

The versions-maven-plugin should be able to do this with the task versions:update-properties. See an example here.

Related

Maven dependencyMangement doesn't inherit the virtue of dependencies in the parent pom

All our external dependencies are defined in enterprise pom. We do not want to define scope of the dependencies in the enterprise pom cause we have applications that are deployed both to Tomcat and JBoss. As we all know couple of dependencies come bundled out of the box in JBoss but may not exist in Tomcat default installation.
bom-parent is the parent of all the application specific enterprise poms. We then created a second level enterprise pom for each app, in the example below its bom-app1. All the projects inherit the app specific enterprise poms.
Sample project with detail instructions and comments available on GitHub
GitHub : https://github.com/samirshaik/mvn-dep-issue.git
Problem:
In the app specific enterprise pom we would just like to define scope of the dependency declared in dependencyManagement section in the first level enterprise pom. But this is not possible as Maven forces us to declare the version of the dependencies re-declared in the app specific enterprise pom. We went ahead and used the same version property as is declared in first level enterprise pom and every thing worked, except that we lost all the properties of the parent dependency like the exclusion of all the transitive dependencies.
To us this is very genuine requirement but looks like dependencyManagement the way its designed today, doesn't consider the virtues of inheritance.
<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.samir.enterprise</groupId>
<artifactId>bom-parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<name>Enterprise BOM</name>
<properties>
<log4j.version>1.2.17</log4j.version>
</properties>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
Below is sample snippet of the child BOM, which should let me define the scope of the dependency and inherit all the features of the parent.
<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>
<parent>
<groupId>com.samir.enterprise</groupId>
<artifactId>bom-parent</artifactId>
<version>1.0.0</version>
</parent>
<groupId>com.samir.enterprise</groupId>
<artifactId>bom-app1</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<name>Enterprise Child BOM</name>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

Custom spring boot starter for specifying distribution management

We have a spring boot application which has its parent defined as spring-boot-starter-parent. But in our project, we have a parent pom with distribution management defined in it, and all the submodules in the project inherit from it. Now, since the spring boot application already inherits from spring-boot-starter-parent, and I do not want to duplicate the distribution management, I thought of having a custom spring boot starter module just to be able to define the distribution management in there and then include this custom spring boot starter as a dependency in the spring boot application. But when I do a mvn clean install deploy of the spring boot application it fails with the error shown below:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.8.
2:deploy (default-deploy) on project crs-acc-eve-gridgain-load-app: Deployment f
ailed: repository element was not specified in the POM inside distributionManage
ment element or in -DaltDeploymentRepository=id::layout::url parameter -> [Help
1]
Is it the right way to achieve this? or there any other recommended ways of doing it?
Given below are the poms of custom spring boot starter parent module:
<?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>crs-micro-services</artifactId>
<groupId>com.ing.crs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>crs-spring-boot-starter-parent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot.version>1.3.5.RELEASE</spring-boot.version>
</properties>
<modules>
<module>crs-spring-boot-starter</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<distributionManagement>
<repository>
<id>XXXX</id>
<name>XXXX</name>
<url>XXXX</url>
</repository>
<snapshotRepository>
<id>XXXX</id>
<name>XXXX</name>
<url>XXXX</url>
<uniqueVersion>false</uniqueVersion>
</snapshotRepository>
</distributionManagement>
</project>
And this..for the starter module
<?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>crs-spring-boot-starter-parent</artifactId>
<groupId>com.ing.crs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<version>1.0-SNAPSHOT</version>
<artifactId>crs-spring-boot-starter</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
And the sprng boot application has this dependency
<dependency>
<groupId>com.ing.crs</groupId>
<artifactId>crs-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>import</scope>
</dependency>
Thanks and regards,
Priya
There is no requirement that your build should be configured with the spring-boot-starter-parent. If you already have a parent with some distribution management, feel free to keep it. You'll need to adapt the parent a bit. Here are couple of options:
If the whole project is spring boot based, maybe your parent could inherit from the Spring Boot starter parent? This may not work if you have a parent that is used within the entire organization
You can keep your parent as it is and use the spring-boot-dependencies BOM instead. See the documentation for more details. You'll have to copy the bits of the parent that you use (such as the plugin definition) but it's not a ton of work.
Your proposal will never work. BOM only imports <dependencyManagement>. What you're looking for is mixin and it's not supported by Maven yet.

IntelliJ can't find maven dependencies for GAE

I was following along with the Creating a Simple Hello World Backend API tutorial (GAE) and all was running fine via local terminal but as soon as I opened the project in IntelliJ, IntelliJ can't build the project...
The pom file has a bunch of errors about being unable to find any dependencies, however I can still build the application just fine outside of IntelliJ.
I'm not overly familiar with Maven but I believe it is configured correctly in the IDE as I can build other generic examples generated by IntelliJ. I've attempted to re-import all dependencies but no luck...
Is there something else I need to do here?
Snippet from the pom file where both dependencies are failing to find versions.
<?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>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<groupId>com.example.helloworld</groupId>
<artifactId>helloworld</artifactId>
<properties>
<app.id>your-app-id</app.id>
<app.version>1</app.version>
<appengine.version>${appengine.version}</appengine.version>
<gcloud.plugin.version>0.9.58.v20150505</gcloud.plugin.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.showDeprecation>true</maven.compiler.showDeprecation>
</properties>
<prerequisites>
<maven>3.1.0</maven>
</prerequisites>
<dependencies>
<!-- Compile/runtime dependencies -->
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-api-1.0-sdk</artifactId>
<version>${appengine.version}</version>
</dependency>
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-endpoints</artifactId>
<version>${appengine.version}</version>
</dependency>
Your appengine.version property is recursively defined, so IntelliJ can't figure out what it is. Substitute <appengine.version>${appengine.version}</appengine.version> with <appengine.version>1.9.24</appengine.version> and you should be fine.

Overrriding spring version in Spring boot/ spring cloud

I note that with spring cloud Angel.SR3 which uses Spring Boot 1.2.4, the spring version loaded is 4.1.6.RELEASE.
There is a memory leak issue in the yaml processor that I read was fixed in spring 4.1.7.RELEASE.
Specifically addressed in this https://jira.spring.io/jira/secure/ReleaseNote.jspa?projectId=10000&version=14936 ([SPR-13173] - YAML Processor leaves StreamDecoder open)
I tracked through and saw that the starters use ${spring.version} to specify the spring version to be used.
I tried overriding by adding 4.1.7.RELEASE to my properties, but it still loads the 4.1.6 version
Anyway I can do this? I understand that these are curated but this particular memory leak is causing us a lot of issues.
As requested I have attached the front part of the pom. All base dependencies are pulled in through the spring cloud parent. I noticed that they use ${spring.version} to define the correct value of spring. I attempted to override it via a property setting. At no time in the rest of the my pom do I explicitly bring in any of the spring framework libs. The parent pom does that.
<?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.libertas.vipaas</groupId>
<artifactId>vipaas-starter</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<name>Vipaas Starter</name>
<description>Vipaas Starter</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>Angel.SR3</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<maven.javadoc.skip>true</maven.javadoc.skip>
<spring.version>4.1.7.RELEASE</spring.version>
..... other stuff ...
</properties>
... other stuff as not relevant ....
Using dependencyManagement it should work:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
You can check it with:
mvn help:effective-pom | grep -A1 "artifactId>spring-context"

Different result by different profile activate method?

I have been using maven for about two years, but I don't think I understand profiles in maven exactly, especially when I encounter the following problem.
I have a maven project with three modules, secweb-parent, secweb-service and secweb-web, secweb-sevice depends on spring-webmvc, and secweb-web depends on secweb-service.
The problem is :
1) When I use 'mvn clean install -Dinclude', it works well, and spring-mvc.jar will be found in secweb-web.war
2) When I use 'mvn clean install -Pinclude-jar', it doesn't work, and spring-mvc.jar can't be found in secweb-web.war
Anybody know why ? And is there something I must pay attention to when I use profiles ?
(I know I can define scope of dependency, this project here just to demo different result of different profile activate method)
pom.xml for secweb-parent
<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>
<properties>
<project.version>1.0.0</project.version>
</properties>
<groupId>com.mediatek.dt</groupId>
<artifactId>secweb-parent</artifactId>
<version>${project.version}</version>
<packaging>pom</packaging>
<modules>
<module>../secweb-web</module>
<module>../secweb-service</module>
</modules>
</project>
pom.xml for secweb-service
<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>com.mediatek.dt</groupId>
<artifactId>secweb-parent</artifactId>
<version>${project.version}</version>
<relativePath>../secweb-parent</relativePath>
</parent>
<artifactId>secweb-service</artifactId>
<profiles>
<profile>
<id>include-jar</id>
<activation>
<property>
<name>include</name>
</property>
</activation>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
</profile>
</profiles>
</project>
pom.xml for secweb-web
<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>com.mediatek.dt</groupId>
<artifactId>secweb-parent</artifactId>
<version>${project.version}</version>
<relativePath>../secweb-parent</relativePath>
</parent>
<artifactId>secweb-web</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>com.mediatek.dt</groupId>
<artifactId>secweb-service</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
You mat check the active profile by using the Maven Help Plugin as the following example
change directory to the parent
e.g. cd /my/project/secweb-parent
Then execute the following command twice for comparing
mvn help:help:active-profiles
mvn help:help:active-profiles -Pinclude-jar
Anyhow the significant point is the version, you have defined as 1.0.0. I would prefer to use the 1.0.0-SNAPSHOT instead.
You may see further information about the SNAPSHOT, here.
Why would you use this? SNAPSHOT versions are used for projects under active development. If your project depends on a software component that is under active development, you can depend on a SNAPSHOT release, and Maven will periodically attempt to download the latest snapshot from a repository when you run a build. Similarly, if the next release of your system is going to have a version "1.4", your project would have a version "1.4-SNAPSHOT" until it was formally released.
As a default setting, Maven will not check for SNAPSHOT releases on remote repositories. To depend on SNAPSHOT releases, users must explicitly enable the ability to download snapshots using a repository or pluginRepository element in the POM.
There is also a useful question and answer about the snapshot at our stackoverflow, here as well.
I hope this may help.

Resources