In this talk you will learn how to set up an Alfresco SDK 3.0 multi module project that could be used in a larger consulting project context. Extension modules will be standalone and versioned and released independently in the Nexus 3 Repository Manager. The talk also includes a look at defining a Parent POM and an Aggregator POM for your SDK 3 project solution.
Alfresco DevCon 2018: SDK 3 Multi Module project using Nexus 3 for releases and versioning
1. SDK 3 Multi Module project
using Nexus 3 for releases
and versioning
Martin Bergljung
2. Speaker Introduction
• Martin Bergljung – Technical Writer @ Alfresco
• Working with Alfresco products for 11 years doing consulting, product
development, training, documentation
• Speaker at DevCon & Summit 2011, 2012, 2013, 2014
• Speaker at Alfresco Days Washington DC, Brussels, Stockholm
• 2 Books (Alfresco CMIS, Alfresco 3 Business Solutions)
• Developed Alfresco SDK version 2.1, 2.2, 3.0
3. Learn. Connect. Collaborate.
Agenda
• Ways of structuring Alfresco SDK projects
• Multi Standalone-Module SDK Project Setup
• Get going with Nexus 3
• SDK Project configuration to:
– Deploy snapshot artifacts to Nexus
– Deploy release artifacts to Nexus
– Use a local Nexus repository
• Defining a parent POM for SDK projects
• Defining an SDK aggregator project
• Demo?
5. Learn. Connect. Collaborate.
All extensions contained in one All-In-One (AIO) Project:
Introduction
• All extension JAR projects contained in the same multi module AIO project
• Very useful for smaller projects with 1-2 developers
• Easy to manage and control when not too many developers
• No need for an artifact repository such as Nexus
• Use GitHub for source code control and tagging
• Build, Tag, and Release/Deploy with for example Jenkins
7. Learn. Connect. Collaborate.
All extensions contained in one All-In-One (AIO) Project:
Pros & Cons
• Pros:
– Easy to get going with
– Easy to manage (with a small team)
– Easy to build
– Easy to understand
– Easy to get the latest code
– No need to install an Artifact Repository Manager, such as Nexus
• Cons:
– No version management – using SNAPSHOTs
• Cannot rely on it to produce a repeatable build
• Downloading 1.0-SNAPSHOT today might give a different file than downloading it
yesterday or tomorrow
– Might build, and release, with incomplete functionality
– Does not promote reuse
– Does not scale well to accommodate more developers
– Difficult to include 3rd party libs not in central artifact repositories
8. Learn. Connect. Collaborate.
Standalone extensions with aggregator AIO Project:
Introduction
• The standalone JAR projects are managed by individual developers and
versioned and released individually in Nexus
• An AIO project is used to aggregate all the extension JARs and produce
the final WARs, which are release to Nexus, and to run the solution on dev
machines
• A Parent POM is used for all general properties, plugins, profiles etc.
• Very useful for larger projects with >2 developers
• Use GitHub for source code control and tagging
• Release to QA, UAT, PROD with for example Jenkins
10. Learn. Connect. Collaborate.
Standalone extensions with aggregator AIO Project :
Pros & Cons
• Pros:
– Can manage and version functionality (JARs) separately
– Can manage and version custom WAR artifacts
– Easy to control exactly what functionality is included in the build, can produce reliable
builds
– Functionality can easily be reused
– Lesser risk of building with incomplete and error prone functionality
– Can proxy, and cache, all dependencies via local Nexus Repo
– Can store 3rd-party jars not in Maven Central in local Nexus Repo
• Cons:
– More complex SDK project setup and need to install Nexus
– More administration
– Takes a bit of time to get on top of
– Can forget to build with latest functionality
– Not ideal for Continuous Delivery
16. Learn. Connect. Collaborate.
Installing and
Running Nexus 3
with Docker
• Running:
– docker run -d -p 8081:8081 --name nexus
sonatype/nexus3
• Accessing:
– http://localhost:8081 (admin/admin123)
• More info about Nexus images on Docker Hub:
– https://hub.docker.com/r/sonatype/nexus3/
17. Learn. Connect. Collaborate.
Out-of-the-box
hosted Maven
repos
• The Nexus 3 repository manager ships with the following
configured hosted Maven repositories:
• maven-releases
– This hosted repository uses the maven2 repository format
with a release version policy.
– It is intended to be the repository where your organization
publishes internal releases.
– You can also use this repository for third-party components
that are not available in external repositories and can
therefore not be retrieved via a configured proxy repository.
• maven-snapshots
– This hosted repository uses the maven2 repository format
with a snapshot version policy.
– It is intended to be the repository where your organization
publishes internal development versions, also known as
snapshots.
18. Learn. Connect. Collaborate.
Out-of-the-box
Maven
Repository
Groups
• The Nexus repository manager ships with the
following Maven group:
• maven-public
– The maven-public group is a repository group of
maven2 formatted repositories and combines
the important external proxy repository for the
Central Repository with the hosted repositories
maven-releases and maven-snapshots.
– This allows you to expose the components of
the Central Repository as well as your internal
components in one single, simple-to-use
repository and therefore URL.
22. Learn. Connect. Collaborate.
Introduction to the SDK/Enterprise Parent POM
• The parent POM is really useful
– It will contain generic configuration that all SDK projects can benefit from:
• Java version
• SDK version
• Alfresco data directory location
• Alfresco version
• Alfresco edition
• Solr locations
• Assembly plugin configuration
• Resource plugin configuration
• JRebel plugin configuration
• Deploy plugin definition
• Release plugin definition
• Nexus snapshot and release repository definition for artifact upload
• Local Nexus repository for artifact download
• Custom project versions used by multiple modules, such as Utils version
23. Learn. Connect. Collaborate.
Creating the SDK/Enterprise Parent POM
• Basically, use the parent POM in an AIO project:
– Start out by generating an SDK 3 AIO project (mvn archetype:generate -
Dfilter=org.alfresco:)
– Update name and description in parent POM appropriately
– Remove the extension JAR projects (sub modules)
– Remove the <modules> section in parent POM
– Remove alfresco-maven-plugin definition, we are not going to “run” the
parent POM, and configuration for this plugin differ between extension projects
– Remove the maven-resource-plugin so it is not run
– Move jrebel-maven-plugin definition to the pluginManagement section
– Now we are ready to configure deploy and release plugins…
25. Learn. Connect. Collaborate.
Maven SNAPSHOT version Introduction
• A snapshot version in Maven is one that has not been released.
• The idea is that before a 1.0 release (or any other release) is done, there
exists a 1.0-SNAPSHOT. That version is what might become 1.0. It's
basically "1.0 under development".
• The difference between a "real" version and a snapshot version is that
snapshots might get updates. That means that downloading 1.0-
SNAPSHOT today might give a different file than downloading it yesterday
or tomorrow.
• Usually, snapshot dependencies should only exist during development
and no released version (i.e. no non-snapshot) should have a dependency
on a snapshot version.
26. Learn. Connect. Collaborate.
Parent POM Updates:
Nexus snapshot repo location
<distributionManagement>
<snapshotRepository>
<id>local-nexus-snapshots</id>
<url>http://localhost:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
• In order for Maven to be able to deploy artifact SNAPSHOTs to Nexus, we
need to tell it what repository to deploy to:
27. Learn. Connect. Collaborate.
Maven ~/.m2/settings.xml updates
<servers>
<server>
<id>local-nexus-snapshots</id>
<username>deployment</username>
<password>1234</password>
</server>
</servers>
• Nexus will not let you upload artifacts unauthenticated, so we need to
specify what credentials to use for the SNAPSHOT repository:
28. Learn. Connect. Collaborate.
Out-of-the-box Maven Deploy Plugin introduction
• By default, Maven handles the
deployment mechanism via the built in
maven-deploy-plugin. This is mapped
to the deployment phase of the default
Maven lifecycle.
• The maven-deploy-plugin is a viable
option to handle the task of deploying
project artifacts 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.
<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>
29. Learn. Connect. Collaborate.
Parent POM Updates:
Define custom Deploy plugin
• The nexus-staging-maven-plugin is
designed to take full advantage of the
more advanced functionality that Nexus
has to offer:
• it is meant to completely replace the
maven-deploy-plugin
• it transparently supports release
and snapshot builds
• supports multiple operation
modes: direct deploy, deferred
deploy, staging and image upload
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-
plugin</artifactId>
<version>1.6.8</version>
<extensions>true</extensions>
<configuration>
<serverId>local-nexus</serverId>
<nexusUrl>http://localhost:8081/nex
us/</nexusUrl>
<skipStaging>true</skipStaging>
</configuration>
</plugin>
• <extensions>true</extensions>: Plugin provides lifecycle enhancements (maven3 only).
30. Learn. Connect. Collaborate.
bp-best-publishing-parent mbergljung$ mvn clean deploy
[INFO] Scanning for projects...
[INFO] Inspecting build with total of 1 modules...
[INFO] Installing Nexus Staging features:
[INFO] ... total of 1 executions of maven-deploy-
plugin replaced with nexus-staging-maven-plugin
[INFO]
[INFO] -------------------------------------------------
-----------------------
[INFO] Building BestPub Parent Project 1.0-SNAPSHOT
[INFO] -------------------------------------------------
-----------------------
. . .
Deploying SNAPSHOT artifact to Nexus
32. Learn. Connect. Collaborate.
Maven release introduction
• Released artifacts are considered to be solid, stable, and perpetual in
order to guarantee that builds that depend upon them are repeatable over
time.
• Released JAR artifacts are associated with PGP signatures, and
checksums verify both the authenticity and integrity of the binary software
artifact.
• The Maven Central repository stores release artifacts.
• A release usually contains a version number according to SemVer
(MAJOR.MINOR.PATCH).
• Product deliverables should be built with released artifacts, never
SNAPSHOT versions.
33. Learn. Connect. Collaborate.
Parent POM Updates:
Nexus release repo location
<distributionManagement>
<repository>
<id>local-nexus-releases</id>
<url>http://localhost:8081/repository/maven-releases/</url>
</repository>
</distributionManagement>
• In order for Maven to be able to deploy artifact releases to Nexus, we need
to tell it what repository to deploy to:
34. Learn. Connect. Collaborate.
Maven ~/.m2/settings.xml updates
<servers>
<server>
<id>local-nexus-releases</id>
<username>deployment</username>
<password>1234</password>
</server>
</servers>
• Nexus will not let you upload artifacts unauthenticated, so we need to
specify what credentials to use for the RELEASE repository:
35. Learn. Connect. Collaborate.
Parent POM Updates:
Source Code Location
The release process will interact with the Software Configuration/Code Management
(SCM) tool used by the project, which means that we need to define the <scm> element in
every top pom.xml:
<scm>
<connection>scm:git:https://github.com/gravitonian/bp-best-publishing-
parent.git</connection>
<url>https://github.com/gravitonian/bp-best-publishing-parent</url>
<developerConnection>scm:git:https://github.com/gravitonian/bp-best-
publishing-parent.git</developerConnection>
</scm>
36. Learn. Connect. Collaborate.
Parent POM Updates:
Define Release plugin
The standard Maven plugin used by a Release Process is the maven-release-plugin,
and the configuration for this plugin is minimal:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<tagNameFormat>v@{project.version}</tagNameFormat>
<autoVersionSubmodules>true</autoVersionSubmodules>
<releaseProfiles>releases</releaseProfiles>
</configuration>
</plugin>
37. Learn. Connect. Collaborate.
Parent POM Updates:
Define Releases Profile
The Maven Release Plugin activates a releases profile. It’s in this process that the nexus-
staging-maven-plugin is used to perform a deploy to the local-nexus-releases Nexus
repository: <profile>
<id>releases</id>
<build>
<plugins>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.8</version>
<extensions>true</extensions>
<configuration>
<serverId>local-nexus</serverId>
<nexusUrl>http://localhost:8081/nexus/</nexusUrl>
<skipStaging>true</skipStaging>
</configuration>
</plugin></plugins></build></profile>
38. Learn. Connect. Collaborate.
Using the Release Plugin:
Clean project for release
We are performing a Release when the current version of the project is a SNAPSHOT version, say
1.0-SNAPSHOT. Start by cleaning up any previous release attempts:
bp-best-publishing-parent mbergljung$ mvn release:clean
[INFO] Scanning for projects...
[INFO] Inspecting build with total of 1 modules...
[INFO] Installing Nexus Staging features:
[INFO] ... total of 1 executions of maven-deploy-plugin
replaced with nexus-staging-maven-plugin
[INFO]
[INFO] --------------------------------------------------
----------------------
[INFO] Building BestPub Parent Project 1.0-SNAPSHOT
[INFO] --------------------------------------------------
----------------------
[INFO]
[INFO] --- maven-release-plugin:2.5.3:clean (default-cli)
@ best-publishing-parent ---
[INFO] Cleaning up after release...
• What happens here?
1. Delete the release descriptor
(release.properties), if any
2. Delete any backup POM files
39. Learn. Connect. Collaborate.
Using the Release Plugin:
Prepare project for release
When a release is prepared the version number will be updated so SNAPSHOT is
removed, changes pushed, code tagged, then version updated with new SNAPSHOT, and
pushed:
bp-best-publishing-parent mbergljung$ mvn release:prepare
[INFO] Scanning for projects...
[INFO] Inspecting build with total of 1 modules...
[INFO] Installing Nexus Staging features:
[INFO] ... total of 1 executions of maven-deploy-plugin replaced with
nexus-staging-maven-plugin
[INFO]
[INFO] ----------------------------------------------------------------------
--
[INFO] Building BestPub Parent Project 1.0-SNAPSHOT
[INFO] ----------------------------------------------------------------------
--
[INFO]
[INFO] --- maven-release-plugin:2.5.3:prepare (default-cli) @ best-
publishing-parent ---
[INFO] Verifying that there are no local modifications…
. . .
[INFO] Executing: /bin/sh -c cd /Users/mbergljung/IDEAProjects/devcon/bp-
best-publishing-parent && git tag -F
/var/folders/6b/tr3_cwjd1sv5zl6wfqvvzx440000gp/T/maven-scm-305938066.commit
v1.0
. . .
• What happens here?
• perform some checks – there should be no
uncommitted changes and the project should
depend on no SNAPSHOT dependencies
• change the version of the project in the pom
file to a full release number (remove
SNAPSHOT suffix) – in our example – 1.0
• run the project test suites
• commit and push the changes
• create the tag out of this non-SNAPSHOT
versioned code
• increase the version of the project in the pom
– in our example – 1.1-SNAPSHOT
• commit and push the changes
40. Learn. Connect. Collaborate.
Results of Prepare Release:
In Local project and POM
The POM file is backed up and a release.properties file is created with information about what tag
that is to be released. The POM is updated with new SNAPSHOT version.
41. Learn. Connect. Collaborate.
Results of Prepare Release:
In GitHub Project
The GitHub project will be updated with two commits 1) prepare release 1.0 and tag 2)
prepare new development iteration with new SNAPSHOT:
42. Learn. Connect. Collaborate.
Using the Release Plugin:
Perform the Release of project
When we got the release prepared and tagged in GitHub we are ready to perform the
release to Nexus:
bp-best-publishing-parent mbergljung$ mvn release:perform
[INFO] Scanning for projects...
[INFO] Inspecting build with total of 1 modules...
[INFO] Installing Nexus Staging features:
[INFO] ... total of 1 executions of maven-deploy-plugin replaced with
nexus-staging-maven-plugin
[INFO]
[INFO] -----------------------------------------------------------------
-------
[INFO] Building BestPub Parent Project 1.1-SNAPSHOT
[INFO] -----------------------------------------------------------------
-------
[INFO]
[INFO] --- maven-release-plugin:2.5.3:perform (default-cli) @ best-
publishing-parent ---
[INFO] Checking out the project to perform the release ...
[INFO] Executing: /bin/sh -c cd
/Users/mbergljung/IDEAProjects/devcon/bp-best-publishing-parent/target
&& git clone --branch v1.0 https://github.com/gravitonian/bp-best-
publishing-parent.git /Users/mbergljung/IDEAProjects/devcon/bp-best-
publishing-parent/target/checkout
. . .
• What happens here?
• Checkout release tag from SCM
• Build and deploy released code to Nexus
The second step of the process relies on the
output of the Prepare step, the release.properties.
43. Learn. Connect. Collaborate.
Results of Perform Release:
In Nexus Repo
After a successful release to
Nexus we should see the
artifact in the maven-
release repository under
the correct package and
version:
44. Using the Parent POM and
the Local Nexus Repo from
an SDK Project
45. Learn. Connect. Collaborate.
SDK Project POM Updates:
Parent POM definition
Define the parent POM to get access to all common project configuration and
plugins:
<parent>
<groupId>org.acme.bestpublishing</groupId>
<artifactId>best-publishing-parent</artifactId>
<version>1.1</version>
</parent>
This brings in all the properties configuration from the Parent POM, so we can
pretty much leave the properties section empty:
<properties>
</properties>
46. Learn. Connect. Collaborate.
SDK Project POM Updates:
Plugin configuration update
The parent POM also contains
most of the plugin
configuration, except the
correct alfresco-maven-
plugin configuration to run the
app server with the extension,
so remove all plugins except
the following:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.alfresco.maven.plugin</groupId>
<artifactId>alfresco-maven-plugin</artifactId>
<version>${alfresco.sdk.version}</version>
<configuration>
<enableH2>true</enableH2>
<enablePlatform>true</enablePlatform>
<enableSolr>true</enableSolr>
<enableShare>false</enableShare>
<enableApiExplorer>true</enableApiExplorer>
…….. Other config ……… </plugin></plugins>
47. Learn. Connect. Collaborate.
SDK Project POM Updates:
Source Code Location
The release process will interact with the Software Configuration/Code Management
(SCM) tool used by the project, which means that we need to define the <scm> element in
every extension module pom.xml:
<scm>
<connection>scm:git:https://github.com/{user}/{project}.git</connection>
<url>http://github.com{user}/{project}</url>
<developerConnection>scm:git:https://github.com/{user}/{project}.git
</developerConnection>
</scm>
48. Learn. Connect. Collaborate.
SDK Project POM Updates:
Local Nexus Repo Location
In order for Maven to be able to find artifacts in the local Nexus repository we
need to add a repository element:
<repositories>
<repository>
<id>local-releases</id>
<url>http://localhost:8081/repository/maven-releases/</url>
</repository>
</repositories>
Needed in every extension project to get access to parent POM.
49. Learn. Connect. Collaborate.
SDK Project Updates:
Check so maven-javadoc-plugin will run OK
For example, <p/> will generate an error and stop release process:
self-closing element not allowed
[INFO] [ERROR] * <p/>
[INFO] [ERROR] ^
50. Learn. Connect. Collaborate.
Commit changes
Before you can start releasing your standalone extension the changes that
were made needs to be committed.
52. Learn. Connect. Collaborate.
Introduction to the Application Aggregator Project
• The application aggregator project is used to aggregate all the standalone
extension projects into one application that can be run (i.e. WAR)
• It is based on a standard SDK 3 AIO project
• It extends the custom Parent POM
• It contains one submodule that will create the Platform App WAR
• It contains one submodule that will create the Share App WAR
53. Learn. Connect. Collaborate.
Creating the Application Aggregator Project
• Basically, use the parent POM in an AIO project:
– Start out by generating an SDK 3 AIO project (mvn archetype:generate -
Dfilter=org.alfresco:)
– Update name and description in parent POM appropriately
– Extend the custom Parent POM
– Start updating the alfresco-maven-plugin configuration, specifically the
platformModules and shareModules sections, and include all the platform and
share extensions, using release versions
– Define Local Nexus repository for artifact download
56. Learn. Connect. Collaborate.
Creating the Application
Aggregator Project –
Platform App Module
• Create a new submodule called
platform-app
• It will use the maven-war-plugin to
assemble the custom alfresco.war
<artifactId>platform-app</artifactId>
<name>Alfresco Platform WAR Application</name>
<packaging>war</packaging>
<parent>
<groupId>org.acme.bestpublishing</groupId>
<artifactId>best-publishing-aggregator</artifactId>
<version>1.2-SNAPSHOT</version>
</parent>
<properties>
<alfresco.platform.war.artifactId>alfresco-platform </alfresco.platform.war.artifactId>
</properties>
<dependencies>
Platform WAR dependency
All Platform extensions dependencies
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<overlays>
<overlay />
<overlay>
<groupId>${alfresco.groupId}</groupId>
<artifactId>${alfresco.platform.war.artifactId}</artifactId>
<type>war</type>
<excludes />
</overlay>
<!-- Include all platform extension JARs here -->
</overlays>
</configuration></plugin>
</plugins></build>
57. Learn. Connect. Collaborate.
Creating the Application
Aggregator Project –
Share App Module
• Create a new submodule called
share-app
• It will use the maven-war-plugin to
assemble the custom share.war
<artifactId>share-app</artifactId>
<name>Alfresco Share WAR Application</name>
<packaging>war</packaging>
<parent>
<groupId>org.acme.bestpublishing</groupId>
<artifactId>best-publishing-aggregator</artifactId>
<version>1.2-SNAPSHOT</version>
</parent>
<properties>
<alfresco.share.war.artifactId>share</alfresco.share.war.artifactId>
</properties>
<dependencies>
Share WAR dependency
All Share extensions dependencies
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<overlays>
<overlay />
<overlay>
<groupId>${alfresco.groupId}</groupId>
<artifactId>${alfresco.share.war.artifactId}</artifactId>
<type>war</type>
<excludes />
</overlay>
<!-- Include all share extension JARs here -->
</overlays>
</configuration></plugin>
</plugins></build>
58. Learn. Connect. Collaborate.
Results of Performing a Release:
In Nexus Repo
After a successful release to
Nexus we should see the
WAR artifacts in the maven-
release repository under
the correct package and
version: