Maven versioning for multiprofile project - java

I need to support two builds with some set of differences in libraries versions, so I made two build profiles and this works fine, but now I have a versioning problem while preparing a release.
I use the major.minor.revision-qualifier versioning schema, where:
major - a breaking change
minor - a backward-compatible changes (new features)
revision - a bug fix
qualifier - the only qualifier I use now is SNAPSHOT to mark unreleased versions.
But since now I have two builds, I need to add some qualifiers to release versions e.g. 1.8.0-v1 and 1.8.0-v2, but then I won't be able to have two SNAPSHOT versions. Or I need to break the "rules" about major\minor version usage and make two "branches" e.g. release 1.8.0 and 1.9.0 and then increase only last number no matter when fixing a bug or adding a new features.
I have a feeling like I am doing something antipattern, could anyone please give me some advice?
P.S. I already have heavily reworked 2.x version, so I can't have separate "branches" as 2.x and 1.x versions, unless i change this new version to 3.0
upd
I guess i can't make this story short, so here we go.
In my project i use to have ojdbc6 and aqapi jars(oracle libraries), my app was working on java 7 and Apache ServiceMix 5 with oracle 11 database. But then some clients updated to oracle 12 and i need new libraries for that, but they only work on java 8, but ActiveMQ i am using as part of ServiceMix 5 doesn't work on java 8. So i updated to servicemix 7 and and after some chances it works fine. So rest of the difference in build profiles are versions of servicemix provided libraries (a complete list is redundant here i guess).
In the end despite the fact that new jdbc driver is fully compatible with old database(not completely sure about aqapi and client side of ActiveMQ, but they should be also compatible), i can't force every client to update and reinstall java\servicemix at the same time, but i still wanna be able to fix\add stuff for all of them.
So i need to support two builds for different versions of servicemix, at least for now(its a temporary solution, but as proverb says: there is nothing more permanent than temporary, so i want to make it in the most right way possible)
P.S.
I decided to make profiles instead of separate brunch in VCS, because it looks like much easier solution, but it doesn't metter in terms of the versioning problem.

So as #Software Engineer said, after thinking about reasons and writing a post update i realised its not multiprofile problem, it's purely versioning problem, it would be the absolutely the same if i make brunch in VCS.
So in the end i decided to make 1.x.x and 2.x.x versions despite the fact that changes are not that "breaking", but they are not fully backward-compatible(even tho new version can work with old database it still needs new servicemix).
This multiprofile workaround doesn't looks pretty, but i left it there, it allows me to build both versions in one go(i use mvn versions:set -DnewVersion command after the first build) and i don't need to support two brunches this way, so it saves some time.

Related

Spring-Web Very High Vulnerability in 5.x.x Version

We are using spring-web in one of our projects which uses Java 8 and Veracode has reported a v high flaw in spring-web framework.
I know updated 6.x.x has been released and it's vulnerability free but in order to update to spirng 6 Java needs to be updated considering our project is very old and on path of EOL by this Sept upgrading it to Java 17 is somewhat not a feasible option.
Are we expecting any release for 5.x.x version with this vulnerability fixed?
The problem highlighted by this CVE is that deserialization of Java serialized objects from an untrusted source is dangerous.
However, flagging all versions of Spring-Web 5.x.x as being vulnerable is misleading. Sure, the Spring-Web codebase has code that allows that to happen. But so do all versions of Java ... until they deprecate and remove Java object serialization entirely. (That is described as a "long term goal", but I doubt that will happen any time soon.)
The correct way to deal with this is not to "upgrade" ... but to audit your code carefully to look for places where you are using Java object deserialization. Then you check each place to see if you are (potentially) getting the data from an untrusted source, or a source that could be compromised thereby rendering it risky.
If you are not using Java object serialization you are fine.
If you are not getting the serialized data from an untrusted (or risky) source you are (probably) fine ... modulo the accuracy of your assumptions and your analysis.
Otherwise you need to change your application to stop using Java object serialization / deserialization in a risky way. Do it another way; e.g. use JSON and a JSON binding technology.
Note that upgrading to Spring-Web 6 or higher doesn't actually solve the problem anyway. Sure they removed the "vulnerable" classes, but the "ability" to use Java serialization unsafely exists in Java. Spring-Web cannot prevent it.
For more background, I recommend that you read issue 24434 on the Spring issue tracker.
In particular, read this comment from one of the developers which explains their stance on the issue.

Is there a way to import a specific version of a java sdk in a project with multiple versions of the same sdk?

Because of, reasons, I cannot just update the old version of the aws sdk I'm working with, but I also need some new things that are in a more recent version.
The problem is that if put both version of the sdk the project I get a "java.lang.NoSuchMethodError" because I think it's trying to use the old version of the sdk. If I delete the old one and just use the updated one it works fine. Is there a way to keep both version of the sdk and tell my java class which one to exclusively import?
There are a couple of ways, but they're pretty nasty.
The arguably "more correct" approach is to could use a custom classloader - see this answer for details. However, that's not exactly simple, and can lead to weird outcomes.
A simpler, but somewhat nastier approach is to get the source code of both SDKs (if available), and rename the packages. For example if we have sdk_v1 and sdk_v2, we can rename the packages to com.example.sdk.v1 and com.example.sdk.v2,
Once there's no package name collision, there's no problem using two different SDKs, even in the same class - just use fully qualified imports (see answer):
com.example.sdk.v1.SomeClass.someFunc() will not collide with com.example.sdk.v2.SomeClass.someFunc()

Apache Common Utils package got changed to 4

We have used CollectionUtils.isEmpty is many places through out the application around 1000 files.
Now the package name has been changed in the recent version apachecommonutils to apache common utils4.
Do we need to have our own utility package and call inside the above API since the changes are drastic during upgrade. If we have our own utility the package name change would be in one single place.
What would be the best practice?
How does enterprise application builts it?
We are facing lot of merge issues and conflicts due to several people working and merging on different projects
There's really only one way to do this.
Go back to the prior version of Commons Utils for now;
Plan this upgrade as a separate, major project that can be done when your code base is in a stable state. Make a new feature branch, off of a release, and do nothing else on that branch EXCEPT the upgrade.
Make sure you thoroughly regression-test all the modules that use Common Utils and are affected by the upgrade

Multi-component versioning/building best practices

I have a Java project, built with Maven, that aggregates several components, each one in its own Maven project. Any one of these components may evolve separately.
The structure of my project can be described as follows:
my-main-project that depends on:
my-component-1
my-component-2
etc.
Nowadays, all pom.xml are using "snapshot" versions, so, they are all using the "latest" version available in my repository.
But once I send a release version to my customer, I'm supposed to freeze the versions and make a TAG (or equivalent) in my source-control, so I can restore a previous state in case of maintenance.
So, my question is: should I change all pom.xml files before each release, give version numbers to the components, and tie everything with this dependency versions? Also, if I have many components (my project currenty has 30+ small subcomponents) would I have to renumber/reversion each one before each release? When a single component evolves (due to bug fix or enhancement), must I increase its version so that the changes do not affect pre-existing releases, right?
How people using maven generally handle this many-component versioning case?
Of course, I could just rely on my version-control tags to restore to a previous point-in-time and just tag every component on each release, but I don't like this approach, since the dependency versioning (with maven) gives me much more control and visibility about what is packaged, and relations of (broken-)compatibility and many more.
General Considerations
You may consider some relations between your components.
Are they really independant (each one vs each other) ? Or is there some kinds of relation ... some commons lifecycles ?
If you find some relationship between them, consider using maven multi-modules : http://www.sonatype.com/books/mvnex-book/reference/multimodule.html. In a few words, you will have a parent, with one version, and some modules (some jars .. in a way like Spring and its submodules). This will help you to reduce versions management.
You may consider using maven-release-plugin. It will help you to tag, build and deploy automatically your modules, dealing more easily with versionning and links with SCM and Repository.
Moreover, combine with multi-module it would drastically help you !
There is a lot of topic dealing with this on Stack Overflow.
I don't know if you already know that. I could explain it a lot further if you want, but you may have enough elements to search by yourself if you don't.
Straight Answers
So, my question is: should I change all pom.xml files before each release, give version numbers to the components, and tie everything with this dependency versions?
Yes you should. In Application Lifecycle Management follow the changes is REALLY important. So, as you could imagine, and as you point it out, you really should build and tag each of your components. It could be painful, but maven-realease-plugin and multi module (even with a Continuous Integration plateform) it could be easier.
would I have to renumber/reversion each one before each release?
For exactly the same reasons : yes !
must I increase its version so that the changes do not affect pre-existing releases, right?
Yes, you should too. Assuming you choose a common versionning like MAJOR.minor.correction, the first number indicate compatibilty breaks. Minor version would bring some breaks, but should not. Corrections whould NEVER affect compatibility.
How people using maven generally handle this many-component versioning case?
I cannot reply for every one, but my previous comments on release-plugin and multi-module considered as best pratices. If you want to a little bit further, you can imagine use more powerfull SCM (Clearcase, Perforce, ...), but maven integration is fewer, not "well" documented and community provide less examples than SVN or Git.
Maven Release Plugin
If you are using a multi-module pom.xml you should be able to do mvn release -DautoVersionSubmodules and have it do a "release" build of all your dependencies and remove the -SNAPSHOT versions and upload them to your repository. That is what the release plugin and its workflow exists solely to do.

Why Maven requires same version of different dependencies?

I'm a student with quite some experience in Java but totally new to Maven.
I was trying to implement a RESTful service provider and client with jersey-server and jersey-client. Both also depends on jersey-json, to make use of automatic conversion between POJO and JSON. Both of them also depend on a service model I implemented myself, where the POJO definition resides.
However, the code doesn't work for me. I spent quite a few hours looking for solutions everywhere on the Internet. It turns out the reason of the failure is that I accidentally specified version of jersey-server and jersey-client as 1.14, but jersey-json as 1.9.1.
The server doesn't work at the beginning, but at some point suddenly starts working. (I have no idea how this happened.) The client never worked until I change jersey-json version to 1.14.
Why do I need to have the same version for these different dependencies?
Because one depends on the other or otherwise has a compatibility issue. This is what dependency management is all about. Run mvn dependency:tree to see exactly how these libraries relate to each other.
In this case, it seems Jersey libraries are all released together as a "bundle" - and you need to use the versions from those bundles together. See: http://jersey.java.net/nonav/documentation/latest/chapter_deps.html
Note that this is an attribute of the Jersey libraries, not Maven.
Often different jars from the same distribution are tested together and given the same version number.
If you try to mix different versions it might work, or it might not, as its not a combination which was intended or tested.

Categories