Maven is the most popular dependency management tool in the Java world with countless add-ons. Even if a project doesn't use Maven for building, a lot of other build tools like Gradle, Bazel, Leiningen, or SBT use Maven repositories for keeping and obtaining libraries.
Suppose you have a project with the following structure:
pom.xml src/ main/ java/ org/ example/ core/ Core.java util/ FileUtil.java cli/ Main.java web/ Web.java
i.e. it's some tool (e.g. static site generator named "generator") with
- web interface;
- command-line interface;
- some core library (the main engine);
- some filesystem utility library.
So the logical dependencies for this project look like the following:
The file utility library could be also used in other projects so it's useful to keep it as a separate Maven artifact. Actually, the same is true for all other components. So let's re-configure Maven to separate the components.
Step 1. Change the directories structure
Inside the main project let's create a directory per component in the parent directory.
pom.xml generator-web/ pom.xml src/main/java/org/example/web/Web.java generator-cli/ pom.xml src/main/java/org/example/cli/Main.java generator-core/ pom.xml src/main/java/org/example/core/Core.java generator-fileutil/ pom.xml src/main/java/org/example/util/FileUtil.java
Each component's pom.xml should be self-contained and should get dependencies via Maven. For example,
generator-fileutil pom.xml could look like:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <groupId>org.example.generator</groupId> <artifactId>generator-fileutil</artifactId> <packaging>jar</packaging> <version>1.0.0-SNAPSHOT</version> <organization> <name>Example Company</name> <url>http://example.org/</url> </organization> <name>File Utilities Library</name> <description>File Utilities Library</description> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>3.0.1</version> <executions> <execution> <id>attach-sources</id> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-gpg-plugin</artifactId> <version>1.6</version> <executions> <execution> <id>sign-artifacts</id> <phase>verify</phase> <goals> <goal>sign</goal> </goals> </execution> </executions> </plugin> </build> <distributionManagement> <repository> <id>target</id> <url>http://company.example.org/maven</url> </repository> </distributionManagement> </project>
By "self-contained" I mean that one can go into the corresponding directory and build the package:
mvn clean package
<distributionManagement> tag specifies the URL of the company's Maven repository to upload jar to. So the ideal organization looks like the following: whenever one pushes changes to a component, e.g.
- CI (continuous integration server) discovers the changes;
- CI checks out the code and runs
mvn clean package upload
- This command uploads the new version of the JAR to the company's Maven repository and since then it's available for other components.
- Other components (like
generator-fileutilas a dependency in their pom.xml files:
maven-source-plugin allows to upload source JAR file into the company Maven repository as well, so the IDE will recognise and attach
generator-fileutil sources when working with other components.
Now one can go inside any other component and build them with
mvn clean package regardless of the fact whether
generator-fileutil sources are located in a nearby directory or not. Thus we decouple dependency management and source management.
Step 2. The parent project pom.xml
There's one problem remaining after Step 1. It's difficult to change related components (e.g.
generator-core) at the same time. Indeed to change a signature of some utility method in
generator-fileutil and its usages in
generator-core one has to
- Change and push
- Wait until CI runs all the tests and uploads new version of
generator-fileutilto the Maven.
- Get the updated version of
generator-fileutilfrom the Maven.
This is inconvenient, especially if you have to do that many times. So the encapsulating parent pom.xml is the rescue. Let's look at our structure once again:
This pom.xml allows to include the components as Maven modules so that the local sources of each component are used. Here's how this pom.xml could look like:
<modelVersion>4.0.0</modelVersion> <groupId>org.example.generator</groupId> <artifactId>generator-project</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>pom</packaging> <organization> <name>Example company</name> <url>http://example.org/</url> </organization> <name>Generator App Project</name> <description>Generator App Aggregate Project</description> <modules> <module>generator-fileutil</module> <module>generator-core</module> <module>generator-cli</module> <module>generator-web</module> </modules> </project>```
That's all. Now if one runs
mvn clean package
for that parent directory, the local sources version of each component will be used. But the main advantage is that one can open the pom.xml as a project in the IDE and all the refactorings and compilation will run on the entire codebase.
Barcelona, Spain, September 3, 2018 - Atlassian announced today that TMate Software is a launch partner for Atlassian's new Data Center approved apps. SVN Mirror for Bitbucket is now listed on the Atlassian Marketplace as a Data Center approved app.
"The Data Center approved apps program is the culmination of a year’s worth of work to establish new app development and testing criteria for Marketplace apps used in Data Center environments," said Laura Della Torre, Head of Business Operations, Ecosystem. "Our launch partners were an integral part of this process – it wouldn't have been possible without their help and support."
In order to be approved for the program, vendors must build and test their apps to a rigorous, Data Center-specific standard. This includes how the apps handle cache operations, support required databases, implement locking and availability in clustered environments, and manage event handlers, just to name a few. The apps are then verified by Atlassian before they are listed on the Atlassian Marketplace.
To learn more, please see the Atlassian blogpost.