Maven Best-Practices for Customized Builds with Plugins/Extensions? - maven

I'm looking for advice on how to build artifacts that are composed of combinations of multiple modules without repeating a lot of boilerplate for all possibilities:
We have a software that is deployed as a .war into Tomcat and as an .amp into Alfresco running on the same Tomcat instance.
Everything related to Alfresco / .amp does not matter for the scope of the question. For simplicity just assume a single .war artifact in regards to Maven.
We use the open-core model and have a free version that consists of some code that ends up in an .amp and a .war file that contains the Angular-Frontend and several backend libraries.
We have at the moment two plugins in our software - each plugin provides an additional .amp file and adds a .jar / config files to the .war and we have lot's of extensions - each extensions overwrites/extends some Angular-Frontend files and also adds XML-configuration to the .war and/or .amp
Now I'm trying to migrate to Maven from an ancient ant-based build setup that basically just copies the plugins/extensions on deploy time over the base-install.
I need to be able to create configurations like: core + plugin-a + extension-b or core + plugin-a + plugin-b + extension-c - so that I have several .amp artifacts and a single .war artifact for each configuration.
It would be nice if it's also possible to aggregate extensions like core + plugin-a + plugin-b + extension-c + extension-d
At the moment I'm using the maven assembly plugin for the .war and the maven-frontend-plugin for angular and the assembly-plugin just copies the compiled artifacts into the war.
The .war itself is a maven module.
I could go on with this strategy and create modules for every extensions and every plugin but then I will need a module for every possible combination of the extensions and plugins.
To make it worse some extensions/plugins are commercial and live in different repositories - so I can't just add everything to the open-core POM.
I've looked into profiles but I'm not sure if that would solve my problem - as I need something like a central registry for all the submodules?
Somethink like mvn clean package -Pextension-a,extension-b,plugin-a that creates the artifacts would be great.
How to tackle this problem with Maven? Are there projects with these requirements where I can look how it's solved there?

This answer is bit speculative, as I do not know anything about Alfresco.
Have you thought about writing a Maven plugin that downloads an extension/plugin (maybe as zip file from your repository?), unpacks it and applies it to your project?
Then you could call the maven plugin with different lists of extensions/plugins.

In the end I've found Bazel with jvm_rules_external.
The concept of WORKSPACE files that allow dependencies using git/maven/http/etc.pp is perfect for this. Beeing able to also build the Angular frontend using Bazel and create lightweight Docker images as well as the cached incremental builds make it a perfect fit.
However transitioning from Maven to Bazel is not straight forward but after learning the concepts I won't look back!

Related

Confused with maven assembly plugin vs build-helper-maven:attach-artifact

I'm a bit confused between maven assembly plugin and build-helper-maven plugin.
I've also read in the maven documentation that The assemblies/archive created by the Assembly Plugin gets deployed during the deployed phase.Hence, they can be deployed to the remote nexus repositories.
The purpose of maven assembly plugin is to archive many things into one(say in tar.gz format).
However, the attach-artifact goal present within build-helper-maven plugin has the same role i.e.archiving,installing and deploying the artifact.
With that being said,why would anyone use both of them together? I've seen people using both of them together. Isn't one of the plugins an alternative choice of the other?
Kindly advise.
If you use maven-assembly-plugin you can create as you already mentioned any kind of archives (range from very simple to very complex structures) they will be by default be attached to your project which means they will be deployed into remote repositories in one go if you do mvn deploy with no supplemental configuration.
The build-helper-maven-plugin is intended to add an artifact (one goal of this plugin) which is usually not generated by Maven itself which most of the cases is a smell. If people using them together (in the use case to create an archive and attach it) this makes no sense.
Apart from that the build-helper-maven-plugin can also be used to add other source directories for example for scala, kotlin projects (other goals for example add-source etc.)
So those plugins are not alternatives they have different intentions/use cases.

Edit Java source code before compile

I am new to gradle. I am looking forward to migrating from maven to gradle.
I had few requirements:
Existing project is maven based, and is generating a fat jar/uber jar. I am planning to split this into multiple projects, and creating smaller/thinner jars/libraries
I am currently evaluating the Multi-project Build support.
I have to also edit the Java source code, automatically, like making the java source modifications based on certain conditions
Publish the project as maven based, as other projects which need these split-up jars are still maven based.
I suppose Maven plugin can be used for publishing?
Would Gradle be a good, scalable solution for these two requirements which I am looking into currently?
Also please provide some pointers around these two topics.
Gradle has very good multi-project support, far better than Maven's. You can start with this documentation section
You can setup compilation of generated/auto-edited sources as well. Take a look at this forum post, discussing compilation of sources created from database using hbm2dao
You can setup publishing of projects using the Maven plugin. pom.xml files will be generated automatically

JBoss Modules for large number of jar dependencies HOW TO

I'm trying to figure out how to make my WARs lighter by putting JasperReports, Apache POI and other heavy libs directly to JBoss AS by using JBoss Modules.
Now, Jasper uses many many libraries to generate PDF or XLS files as you can see here. Our templates are pretty old and we are stuck with old jasper version 3.7.1 which of course uses older versions of libraries such as commons which are already present on JBoss AS 7.1.1 modules.
How can I make one "big" module which will contain all jars used by Jasper and keep other parts of application using newer modules?
Putting all jars into separate directories seems so much work without guaranteed success, can we put everything into one module without creating package alike directories?
We started with JBoss modules recently and wrote a small plugin for Maven that generates module folders with module.xmls based on XML descriptors. The plugin is called smartics-jboss-modules-maven-plugin and you'll find additional information about it at the project's blog.
We just started to work with it, but it already makes the process of synchronization between the POM and the module.xml (plus directory structure) for our projects very easy.
The downside of this approach is that you have to learn an additional XML descriptor and have to configure an additional Maven plugin.
If you want to give it a try, the plugin is licensed under Apache License 2.0.
The creation of JBoss modules for external libraries can be automated through maven as explained in another answer here on SO. The author has posted a GitHub project too. This can lessen the pain in managing lots of transitive dependencies.

Maven: Checkout a SVN Repository, compile, package into a jar and add as a Dependency

We have a web application in which we are using Ant as a build tool. There is a urgent requirement to create web services (API) and this will be a separate project. For now, to make it available to our customers we have decided to use our web application and remove all unnecessary files (like velocity files, properties, xml etc) and make a jar of it. This jar will be used in our web service project.
In Maven, I want to checkout my web application svn branch, compile it, make a single jar of it and add as a dependency in my project. Is this possible? If yes, then please show me the way.
I'm new to Maven please explain your answers with more detail.
Thanks.
Short Answer
Get your .war deployed into a Maven Repository (local or remote) from your ant build
Child Projects will embed your .war as a dependency, creating a war with your custom services + your original .war file
It is advised that those Child Projects turn into an Archetype, so creating custom services gets easier
Long Answer
From your SCM, you could modify your build.xml file and use Maven Tasks for Ant.
In particular, the install and deploy examples are helpful in order to guide you on deployment your .war into a Maven repository (local or remote)
Then, a .war artifact (when accessible from a Repository) is able to be consumed from other .war applications.
Look into the maven-war-plugin Overlays Feature. In particular, this answer offers you more advice:
combine different maven web-projects into a single project
Other than that, I suggest you could also combine with Maven Archetypes (they're now easier than ever), so you could create skeleton projects for your webservices, already depending on this .war dependency.

Migration from ant to Maven producing 100+ jars

We are trying to migrate our builds from ant to maven. Project I am working for is using ant since ages. Scripts are real complex where build artifact is a zip file having a definite directory structure. Build creates about 108 unique jars and packages them to this zip file along with many config files and other 3rd party jars.
We need this zip file to be same as now even after migration to Maven. I am just a learner on Maven as of now. My question to you guys is that if there is a way using which I can use one pom.xml to produce more that one jar file, providing list of jars and includes, excludes packages for each.
I googled and found that in case we need multiple jars from one project but different packages, we can do so by placing one pom.xml at each package (jar will be created from this package) and bonding all using dependency management.
But this does not solves my problem, as having 100+ pom.xmls does not seems to be a good idea.
Hope I have made my question clear. Please suggest if there is a way out.
Adding to Udo's answer here's another Sonatype blog posting with a diagram explaining the Maven anti-pattern of generating multiple jars from a single Maven project.
Both articles recommend adopting a modular structure to your code rather than fighting Maven's approach of decoupling large projects into a set of interrelated sub-modules.
Incremental publish approach
Start with looking at the arifacts you actually plan to share. Your mail suggests that the only file you're actually publishing is a large zip file containing 100+ jars and other files?
You could invoke the Maven command-line tool to publish this zip to the Maven repository:
mvn deploy:deploy-file \
-Durl=$REPO_URL \
-DrepositoryId=$REPO_ID \
-DgroupId=org.myorg \
-DartifactId=myproj \
-Dversion=1.2.3 \
-Dpackaging=zip \
-Dfile=myproj.zip
This approach can also be used to publish jars and POMs (containing dependencies). Eventually you'll be overwhelmed with the number of POMs to maintain.... AT which time it would be simpler to restructure the building of that jar into a sub-module.
Alternative to switching build technology
It's very difficult to walk away from a legacy ANT build. These often contain complex, custom and difficult to reproduce build logic. For such projects I recommend using Apache ivy to externalise 3rd party dependencies and share artifacts with other projects (who might be using Maven).
To that end I wrote an ant2ivy script for generating an initial ivy setup, based on the jars that already exist in the ANT project's directory (normally committed alongside the source).
Using ivy doesn't get you away from the fact that it's a good idea to create project sub-modules. However it does enable you to modernise your ANT build.
Update
Yes, there are Maven ANT tasks available. I don't use them because they based on Maven 2. I'm disappointed that we're still waiting for their Maven 3 replacement aether-ant-tasks (Only available from GitHub). Ivy is still the no1 choice for integrating non-Maven clients with a Maven repository
Well you can generate multiple jars out of one project.
Its not really considered best practice. Look at the supplied article and decide it yourself.
In the includes your are not limited to packages, however this surely makes it easier. :)

Resources