AutoUpdate issues with Mavenized NetBeans Platform Application - java

I recently migrated my NetBeans Platform (NBP) based application from Ant to Maven. I pretty much figured Maven out but there's one thing I still cannot get my head around, and that is the version system/convention.
It seems that everyone in the Maven world with a large Maven project consisting of multiple modules uses a parent pom in which they define a version, which is then inherited by all child pom's (i.e. all NBP Modules in Maven NetBeans RCP project).
For instance, take a look at the final result of the example project in the maven book:
http://books.sonatype.com/mvnex-book/reference/optimizing-sect-final-poms.html
You will see one version defined by the parent POM,
<groupId>org.sonatype.mavenbook.optimize</groupId>
<artifactId>simple-parent</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
which is inherited by each child module, by specifying the parent and not using any tag of its own:
<parent>
<groupId>org.sonatype.mavenbook.optimize</groupId>
<artifactId>simple-parent</artifactId>
<version>1.0</version>
</parent>
and for its internal (within the project) dependencies each child module defines this relative to the project:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>simple-weather</artifactId>
<version>${project.version}</version>
</dependency>
This means that you cannot update one module to a higher version because it will then look for dependencies with the same version number, which don't exist. Not to mention that using a separate version for any of your child modules gives you headaches when using the versions-maven-plugin because you end up micromanaging your dependencies.
This seems to completely go against the AutoUpdate / Lifecycle / Release philosophy of the NetBeans Platform. There I could update one module and generate a new updates.xml ("Package as NBMs") and when uploaded to an AutoUpdate repository, a client will see just that one update. It seems that if you do it the Maven way (mvn nbm:autoupdate), all modules get a version bump so that the whole model of auto updating via modules goes down the drain.
I hope I am mistaken and there is somewhere a feature to restore the great autoupdate functionality that comes with the platform, some kind of extra version number that automatically gets added to the major.minor.revision number or some intelligent way to override OpenIDE-Module-Specification-Version = major.minor.revision in between releases versions. Is there or do I have to release a new version of my application for each tiny update to a client module?

There is no silver bullet.
Keeping the version in one place makes sense when you are releasing the entire thing together eg. when your thing is a webapp. Then it's simpler to just keep the version intact as you are building and deploying stuff together. With Netbeans platform you should think in the same terms. If something is part of your base application you ship, make it the same version for the base app releases and only diverse for patches shipping to customers later on. That's more or less the model netbeans itself has adopted (in ant based codebase though but all modules get a version bump after a major release)
If a plugin or set of plugins is optional or works in multiple versions of the base app or works with multiple different applications put them in a separate repository with their own versioning.
Making a release of single module within a git repository for example (using maven:release) could bring problems of it's own. Eg. when maintaining multiple different branches (patches for older versions etc)
Play with the combination for a bit to see which things suit your workflow and release cycle.
Please note that the final assembly of the application is done in the nbm-application project and not the maven reactor. Maybe the easiest way to manage the dependencies would be to keep the nbm-application final assembly separate (separate maven build, separate git repository).
Keeping each netbeans module in it's own repository allows you to micromanage the versioning but you still need to update the module's pom during release but also as the nbm-application dependency to include the new version in auto update or application. Thus you can separate a plugin release from plugin deployment to customers which can be a good thing. These multiple steps can be automated in your CI server but do add complexity to your builds.
So your mileage may vary based on how your application gets distributed, how tight are your inter-module dependencies etc.

Related

How to add 70 local jars on maven project?

why use Maven when you have such quantity of local jars?
So we have a client that have a lot of private jars and custom jars.
For example commons-langMyCompanyCustom.jar which is commons-lang.jar with 10 more classes in it.
So on their environment we use 100% Maven without local dependencies.
But on our site we have the jars for development in Eclipse and have Maven build with the public ones, but we do not have permission to add their jars in our organizational repository.
So we want to use the Maven good things like: compile,test, build uber-jar, add static code analysis, generate java-docs, sources-jars etc. not to do this thinks one by one with the help of Eclipse.
So we have 70 jar some of them are public if I get the effective pom on their environment I found 50 of them in Maven Central, but the other 20 are as I called "custom" jars. I searched for decision of course but found this:
<dependency>
<groupId>sample</groupId>
<artifactId>com.sample</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/yourJar.jar</systemPath>
</dependency>
So for all 20 of them I have to add this in the development maven profile??
Is there a easy way like in Gradle where you can add all folder with its dependencies to the existing ones?
Also installing one by one in every developer's repo is not acceptable.
Please forget the system scope as mentioned before! Too problematic...
Ideally:
Ideally, all your developers have access to Repository Manager in your or their organization (if possible).
A central environment for your System Integration Testing, maybe?
Alternatively, you may have a central environment for testing where all the dependencies are provided. This approach can be used to simulate how a compilation would work as if it's in your client's environment. Plus you only setup jars once.
So on their environment we use 100% Maven without local dependencies.
But on our site we have the jars for development in Eclipse and have
Maven build with the public ones, but we do not have permission to add
their jars in our organizational repository.
According to what you're saying in the above-quoted excerpt I believe you want to have set in your build's pom.xml assuming that in the client setup the dependencies will be present.
Especially, as you indicate that the organization doesn't give you permission to add their jars in your repository, I would use the provided scope.
As stated in the Maven docs, the definition of a provided dependency is as followed:
This is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.
So basically you assume that these dependencies will be present at your client's setup. However, this has some limitations. Meaning you can build solutions independently but cannot test it locally because you won't have the dependencies on your workstation.
If you won't even have access to the jars to configure your central environment ask if your client can provide a DEV/SIT environment.
None of the above? Inherit a parent pom.
To avoid the whole constant copy-paste process for every single (related) project, maven has the tools to centralize dependency and plugin configurations, one of such is by inheriting the configuration of a parent pom. As is explaining in the following documentation it is quite simple:
First you create a project with just a pom.xml where you define everything you wish to centralize (watch out, certain items have slight differences in their constructs);
Use as property of packaging tag the option pom: <packaging>pom</packaging>;
In the pom's that have to inherit these configurations set the parent configuration tags in <parent> ... </parent> (documentation is very clear with this);
Now everytime you update any "global" pom configuration only the parent version has to be updated on every project. As a result of this, you only need to configure everything once.
You can also apply this together with the abovementioned solutions, this way combining to find a solution that fits best to your needs.
But there is a big Maven world out there, so I advise a good read in its doc's to further acknowledge your possibilities. I remembered these situations because I've been in a similar situation you seem to be now.
Good luck!
Another alternative is the project RepoTree.
This one creates a Maven repository directory (not a server) from another directory which contains just the .jars. In other words, it creates the necessary .pom files and directory structure. It takes into account only the precise information from metadata contained in the archives (MANIFEST.MF, pom.xml).
Utility to recursively install artifacts from a directory into a local
Maven repository Based on Aether 1.7
This is 5 years old, but still should work fine.
TL;DR: MavenHoe creates a Maven repository server (not a directory) which serves the artefacts from a directory, guessing what you ask for if needed. The purpose is to avoid complicated version synchronizing - it simply takes whatever is closest to the requested G:A:V.
I have moved the MavenHoe project, which almost got lost with the decline of Google Code, to Github. Therefore I put it here for availability in the form of a full answer:
One of the options you have when dealing with conditions like that is to take whatever comes in form of a directory with .jar's and treat it as a repository.
Some time ago I have written a tool for that purpose. My situation was that we were building JBoss EAP and recompiled every single dependency.
That resulted in thousands of .jars which were most often the same as their Central counterpart (plus security and bug fixes).
I needed the tests to run against these artifacts rather than the Central ones. However, the Maven coordinates were the same.
Therefore, I wrote this "Maven repository/proxy" which provided the artifact if it found something that could be it, and if not, it proxied the request to Central.
It can derive the G:A:V from three sources:
MANIFEST.MF
META-INF/.../pom.xml
Location of the file in the directory, in combination with a configuration file like this:
jboss-managed.jar org/jboss/man/ jboss-managed 2.1.0.SP1 jboss-managed-2.1.0.SP1.jar
getopt.jar gnu-getopt/ getopt 1.0.12-brew getopt-1.0.12-brew.jar
jboss-kernel.jar org/jboss/microcontainer/ jboss-kernel 2.0.6.GA jboss-kernel-2.0.6.GA.jar
jboss-logging-spi.jar org/jboss/logging/ jboss-logging-spi 2.1.0.GA jboss-logging-spi-2.1.0.GA.jar
...
The first column is the filename in the .zip; Then groupId (with either slashes or dots), artifactId, version, artifact file name, respectively.
Your 70 files would be listed in this file.
See more information at this page:
https://rawgit.com/OndraZizka/MavenHoe/master/docs/README.html
The project is available here.
Feel free to fork and push further, if you don't find anything better.

How to update version number in Maven POMs

We have a very modular Maven pom set up, with common jars and specific jars all being bundled in to a war and ear. As there is so much reuse amongst the 70+ modules we do not use multi-module and each module can and does have its own lifecycle and can be released independently of any other module.
All modules inherit from various parent poms and ultimately every pom inherits from a master POM where all the external versions such as spring and the common local module versions are defined.
This works ok until we come to do a release. If the master POM requires a change, which it does occasionally, ALL poms need to be updated one way or another. I am aware that the maven versions plugin can update a specific POM with the latest SNAPSHOT versions etc, but this only works at the individual POM level.
We would like to be able to alter all poms once a release has been completed, iteratively.
We do not use multi-module POMs and are not able to change our build process to use this mechanism.
I have read around SO and the nearest to the problem is here.
https://stackoverflow.com/a/3615417/1279002
Writing a shell script seems to be one solution, but we have a Windows and Linux mix of development and build systems. I am sure other will have solved this issue. Can anybody advise how they have solved this?
In a similar setup, I have all my parent POMs always stay at 1.0.0-SNAPSHOT and setup various properties in the parent POMs to track internal module version numbers (so this setup now centralizes both dependency management versions AND custom module versions [via properties] into the parent POMs).
So if I need to update the reference to some com.myco:module-x, I can do this:
Edit the appropriate parent POM and set the <module-x.version>1.2.3</module-x.version> property to the new value
Rebuild/install the parent POM
Rebuild the target end-application (ear, war, jar app etc).
Where in module-x's POM it's definition may be something like this:
<groupId>com.myco</groupId>
<artifactId>module-x</artifactId>
<version>${module-x.version}</version>
And any POMs which reference com.myco:module-x refernece it via ${module-x.version} as well.
At this point, the build of the application will pickup the changes in the parent POM and thus any references it has to any properties defined in the parent POM.
There's some subtle nuances in doing this in terms of when/how the "middle man" modules need to get rebuilt...
But I really don't believe there is any silver bullet here.
The approach we've taken works pretty well, coupled with Jenkins to automate rebuilds of modules with interdependencies whenever parent POMs change.
The benefit here is that you seldom need to modify anything but the parent POMs, ever. The middle-man modules and application POMs don't need to be updated to get new version numbers, etc.
The biggest caveat though is that two rebuilds of a given module at the same version could result in a different artifact, for example:
module-x has a dependency on module-y:1.2.3
module-x is built (jar is created with a MANIFEST referencing module-y:1.2.3)
parent POM is modified to set <module-y.version>1.2.4</module-y.version>
module-y is rebuilt to create the 1.2.4 artifact
module-x is built (jar is created with a MANIFEST referencing module-y:1.2.4)
But note that #2 and #5 both built module-x with the same version for module-x, but with two different embedded MANIFEST's referencing different module-y versions.
We overcome this nuance by automating all the dependent modules with our Jenkins CI server

Will I ever have to care about versisining maven modules?

I have a single application that consists of several modules:
app-parent
app-main
app-start-cmd
app-start-gui
app-tools
app-tools-toolone
app-tools-tooltwo
app-main holds the bigger part of the application's body. app-start-cmd, app-start-gui, and app-tools modules depend on it.
When I was adding this dependency, it asked me for a version of app-main that they should depend on, and 0.0.1-SNAPSHOT was entered automatically.
I have two questions:
When I change app-main's version, will the dependency in other projects be automatically updated? (Don't want to mess something up right now.)
Is there a way to just change the app-parent's version and have it reflect on all other modules? It is after all just one application, even though it will build several separate artifacts for different purposes.
Try versions-maven-plugin http://mojo.codehaus.org/versions-maven-plugin/ it can manage versions in multi-module projects. Run this command in main project
mvn versions:set -DnewVersion=2.2.2
and it will change all versions to 2.2.2

Why breaking down a Maven project to sub-modules?

What are the main possible reasons of breaking down a Maven project to sub-modules?
Are you looking something more than the benefits of Modularization? The sub-modules should ideally be representing a single concept/feature so that they are functionally cohesive.
Pom file inheritence
You can use the and sections of the root poms to keep consistent version numbers and configurations across all child projects. So if I have an aggregator project that lists 300 projects, all that use apache commons-io and I want to upgrade them all the the latest version of commons-io, I can just change the version in the dependencyManagement section of the root pom. None of the child projects need specify a version.
build profiles
In the above example, if I have 300 sub projects, an individual developer is probably not regularly working on all (or even many) of the 300 sub-projects. You can create a build profile that specifies only the modules you work on regularly, and if you have a continuous integration server that deploys artifacts to an artifact repository, you'll get all the changes the developers on your team make too, without having to build all 300 modules.
General organization/clarity
While waiting for an answer to my comment.
A reason to split a Java EE based maven project into sub modules is so you can build the JAR/RAR/WAR/EAR/whatever independently of eachother.
For regular Java apps, you might split out the functionality into separate JARs, again each of these could be a sub-module under the overall project and again you can build them independently, run separate goals/phases/reports etc.

How do I properly setup a multi-module Maven project with sliding release cycles

I'm trying to work out the best way to setup our multi-module Apache Maven project in a way that allows for disparate release cycles of modules, and doesn't introduce dependency issues when debugging the project.
We currently have a setup along the lines of:
bigsystem#1.2
parent-1.1-SNAPSHOT
module a#1.4-SNAPSHOT
parented by parent#1.1-SNAPSHOT
module b#1.3-SNAPSHOT
parented by parent#1.1-SNAPSHOT
depends on a#1.1
module c#1.1-SNAPSHOT
parented by parent#1.1-SNAPSHOT
depends on a#1.2
depends on b#1.1
The dependencies declared in modules b and c contain the minimum version required to compile the module, which isn't necessarily the current version of the module, or the version of the module being deployed.
From a build perspective this works well, each module can be released/updated as needed, however when trying to debug the deployed application under IntelliJ IDEA (versions 8 and 9 EAPs) having opened the top level pom, IDEA decides that since we declared a dependency on a#1.2, that anytime we step into one of a's classes, it should open it from a-1.2-sources.jar rather than the current a#1.4 sources in the project. This is further confused by the fact that stepping into any of b's classes takes us to b#1.1 rather than b#1.3.
My initial attempt to work around this was to declare the version numbers in the parent pom's dependencyManagement section and just have the sub-modules inherit the version. This worked to the degree of solving the IDEA debug issue as the dependencyManagement section can point everyone to the current -SNAPSHOT versions.
This unfortunately causes a problem when doing a maven release due to having to release the parent pom before releasing the module, but as the parent may refer to multiple in-development -SNAPSHOTS it can't be released and we end up adding version references back to the modules pom to satisfy the release.
It would seem that using maven's dependencyManagement section would only really work well if we were releasing ALL bundles at the same time, regardless of if they changed, but as we're wanting to manage releases of each sub module only when needed this model doesn't seem to fit.
I have a suspicion I'm missing something, and that a combination of dependencyManagement and version ranges might satisfy out requirements although I've yet to see version ranges work properly.
Is there a better way? A proper way?
I would recommend not making them modules, but make their POMs independent. That way you do not have to worry about trying to satisfy parent POM dependencies. Since they are released independently, they really should have independent project object models. Think of Apache Commons as a template.
I think the problem with IDEA arises because you are using the root POM in your source structure to do two things that are usually mutually exclusive in Maven. You are first using the POM as a location to store common configuration information for unrelated (from a build perspective) Maven projects. Secondly you are using the POM as an aggregator for your build. You can do each of these without doing the other.
Like Rob said, remove your module a, b, etc. projects from the modules section of your parent POM. Secondly, move your parent POM down into its own directory as it is really a sibling of the other modules with respect to your build and release process. The way you have it now, it is more of a parent/aggregator.
The way you have it now also doesn't lend itself to tagging and releasing each module individually as a tag of your parent POM would likely needlessly include all of the module sub-folders.
Your file structure would look like:
parent
pom.xml
module a
pom.xml
module X
pom.xml
As for the thing you are missing, dependencyManagement isn't really well suited to manage versions for intra-project dependencies. That is dependencies between modules within an aggregated build. It is more well suited for declaring global versions for external dependencies.
The final/working solution we ended up using was fairly similar to what we started with. The actual project structure remains the same:
bigsystem#1.2
parent-1.1-SNAPSHOT
module a#1.4-SNAPSHOT
o parented by parent#1.1-SNAPSHOT
module b#1.3-SNAPSHOT
o parented by parent#1.1-SNAPSHOT
o depends on a#1.1
module c#1.1-SNAPSHOT
o parented by parent#1.1-SNAPSHOT
o depends on a#1.2
o depends on b#1.1
distribution a#1.2-SNAPSHOP
However the main differences are that:
parent module does not include any versions of project artifacts
individual modules fully declare their project dependencies and specify a version range, i.e. [1.0.0,1.1.0)
all modules start there version number cycles from .1, i.e 1.0.1-SNAPSHOT, this allows the version range to satisfied by initial snapshots (1.0.0-SNAPSHOT is earlier than 1.0.0 final, so not included).
distribution pom (not initially shown in question) identifies the exact version to be deployed/included in a specific release.
delete all project -SNAPSHOTS from local maven repository when releasing so that ranges pickup releases only ( or use -Dmaven.repo.local=/tmp/sometemprepo for a fresh local repo)
This makes each module more standalone and gives us the freedom to release and deploy new versions of our project artifacts with minimal fuss.
They certainly seem like separate modules. What benefits are you gaining by smashing them together if they have different dependencies, even within the multi-module project?

Categories