Get up to speed with the core of Maven quickly, and then go beyond the foundations into the more powerful functionality of the build tool, such as profiles, scopes, multi-module projects and quite a bit more:
Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.
Get started with mocking and improve your application tests using our Mockito guide:
Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.
Get started with understanding multi-threaded applications with our Java Concurrency guide:
Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:
Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.
But these can also be overused and fall into some common pitfalls.
To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:
Get started with Spring and Spring Boot, through the Learn Spring course:
>> LEARN SPRINGExplore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:
Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.
I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.
You can explore the course here:
Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.
Get started with Spring Data JPA through the guided reference course:
Refactor Java code safely β and automatically β with OpenRewrite.
Refactoring big codebases by hand is slow, risky, and easy to put off. Thatβs where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.
Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions β one for newcomers and one for experienced users. Youβll see how recipes work, how to apply them across projects, and how to modernize code with confidence.
Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.
1. Overview
In a previous article, I discussed how a Maven project can install locally a third party jar that has not yet been deployed on Maven Central (or on any of the other large and publicly hosted repositories).
That solution should only be applied in small projects where installing, running and maintaining a full Nexus server may be overkill. However, as a project grows,
Nexus quickly becomes the only real and mature option for hosting third party artifacts, as well as for reusing internal artifacts across development streams.
This article will show how to deploy the artifacts of a project to Nexus, with Maven.
2. Nexus Requirements in the pom.xml
In order for Maven to be able to deploy the artifacts it creates in the package phase of the build, it needs to define the repository information where the packaged artifacts will be deployed, via the distributionManagement element:
<distributionManagement>
<snapshotRepository>
<id>nexus-snapshots</id>
<url>http://localhost:8081/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
A hosted, public Snapshots repository comes out of the box on Nexus, so thereβs no need to create or configure anything further. Nexus makes it easy to determine the URLs of its hosted repositories β each repository displays the exact entry to be added in the <distributionManagement> of the project pom, under the Summary tab.
3. Plugins
By default, Maven handles the deployment mechanism via the maven-deploy-plugin β this mapped to the deployment phase of the default Maven lifecycle:
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.1</version>
<executions>
<execution>
<id>default-deploy</id>
<phase>deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
The maven-deploy-plugin is a viable option to handle the task of deploying to artifacts of a project to Nexus, but it was not built to take full advantage of what Nexus has to offer. Because of that fact, Sonatype built a Nexus specific plugin β the nexus-staging-maven-plugin β that is actually designed to take full advantage of the more advanced functionality that Nexus has to offer β functionality such as staging.
Although for a simple deployment process we do not require staging functionality, we will go forward with this custom Nexus plugin since it was built with the clear purpose to talk to Nexus well.
The only reason to use the maven-deploy-plugin is to keep open the option of using an alternative to Nexus in the future β for example, an Artifactory repository. However, unlike other components that may actually change throughout the lifecycle of a project, the Maven Repository Manager is highly unlikely to change, so that flexibility is not required.
So, the first step in using another deployment plugin in the deploy phase is to disable the existing, default mapping:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>${maven-deploy-plugin.version}</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
Now, we can define:
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.5.1</version>
<executions>
<execution>
<id>default-deploy</id>
<phase>deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
<configuration>
<serverId>nexus</serverId>
<nexusUrl>http://localhost:8081/nexus/</nexusUrl>
<skipStaging>true</skipStaging>
</configuration>
</plugin>
The deploy goal of the plugin is mapped to the deploy phase of the Maven build.
Also notice that, as discussed, we do not need staging functionality in a simple deployment of -SNAPSHOT artifacts to Nexus, so that is fully disabled via the <skipStaging> element.
By default, the deploy goal includes the staging workflow, which is recommended for release builds.
4. The Global settings.xml
Deployment to Nexus is a secured operation β and a deployment user exists for this purpose out of the box on any Nexus instance.
Configuring Maven with the credentials of this deployment user, so that it can interact correctly with Nexus, cannot be done in the pom.xml of the project. This is because the syntax of the pom doesnβt allow it, not to mention the fact that the pom may be a public artifact, so not well suited to hold credential information.
The credentials of the server have to be defined in the global Maven setting.xml:
<servers>
<server>
<id>nexus-snapshots</id>
<username>deployment</username>
<password>the_pass_for_the_deployment_user</password>
</server>
</servers>
The server can also be configured to use key based security instead of raw and plaintext credentials.
5. The Deployment Process
Performing the deployment process is a simple task:
mvn clean deploy -Dmaven.test.skip=true
Skipping tests is OK in the context of a deployment job because this job should be the last job from a deployment pipeline for the project.
A common example of such a deployment pipeline would be a succession of Jenkins jobs, each triggering the next only if it completes successfully. As such, it is the responsibility of the previous jobs in the pipeline to run all tests suites from the project β by the time the deployment job runs, all tests should already pass.
If ran a single command, then tests can be kept active to run before the deployment phase executes:
mvn clean deploy
6. Conclusion
This is a simple, yet highly effective solution to deploying to Maven artifacts to Nexus.
It is also somewhat opinionated β nexus-staging-maven-plugin is used instead of the default maven-deploy-plugin; staging functionality is disabled, etc β it is these choices that make the solution simple and practical.
Potentially activating the full staging functionality can be the subject of a future article.
Finally, weβll discuss the Release Process in the next article.
