Maven dependency: ranges resolving issue - java

I want to use a range for the version of some dependency. But I don't really get it how it should be defined for my case.
Here's the results of lookup - maven-metadata-nexus.xml file.
<versioning>
<latest>0.1.0-SNAPSHOT</latest>
<versions>
<version>0.0.13-SNAPSHOT</version>
<version>0.0.14-SNAPSHOT</version>
<version>0.0.15-SNAPSHOT</version>
<version>0.0.16-SNAPSHOT</version>
<version>0.0.17-SNAPSHOT</version>
<version>0.1.0-SNAPSHOT</version>
</versions>
<lastUpdated>20190826092951</lastUpdated>
</versioning>
I want to import the latest 0.1.x dependency, so I thought writing range this way would do the thing
<dependency>
<groupId>my.group.id</groupId>
<artifactId>my-artifact</artifactId>
<version>[0.1, 0.2)</version>
</dependency>
However, maven says that there's no version of my artifact available.
Defining range as [0.1.0-SNAPSHOT, 0.2) fixes the problem, but I don't really understand why I need to be so specific with the boundary and is it a good practice or not. What's the right way to define such ranges?

Maven treats SNAPSHOT version differently than "normal" versions.
"normal" (published in a repo) version is typically immutable. It can't be updated nor removed and no matter when you access it will still be the same.
SNAPSHOT versions are the opposite of that. They can change at any time (think work in progress).
Typically SNAPSHOTs are only to be found in your local repo. If you want to use SNAPSHOTs from remote repo you have to explicitly tell Maven that repo provides SNAPSHOT versions.
With that distinction in mind, Maven folks have decided that
Resolution of dependency ranges should not resolve to a snapshot (development version) unless it is included as an explicit boundary. There is no need to compile against development code unless you are explicitly using a new feature, under which the snapshot will become the lower bound of your version specification.

Related

AEM OSGI 3rd party dependency, bundle not Active

I'm working off an AEM project, I'm new to AEM btw. I'm trying to use a couple of 3rd party non-OSGI libraries, like Dozer and Spring. I'm really struggling with this, it is a pain in the ass, maybe it is because OSGI is kind of old school. My bundles get installed, but not Active in the OSGI console, as they complain about missing packages.
I want to do step by step. First I want to make work my bundles with just Dozer and nothing else. This is my pom dependencies:
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer-osgi</artifactId>
<version>5.5.1</version>
</dependency>
Here is my maven-bundle-plugin configuration:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<version>4.1.0</version>
<configuration>
<instructions>
<Export-Package>somepackages*</Export-Package>
<Private-Package/>
<Import-Package>*</Import-Package>
<Sling-Bundle-Resources>/META-INF</Sling-Bundle-Resources>
</instructions>
</configuration>
</plugin>
As you can see, I'm using dozer-osgi already. I'm not sure why it doesn't pick it up. It complains about this:
org.dozer,version=[5.5,6) -- Cannot be resolved
org.dozer.loader.api,version=[5.5,6) -- Cannot be resolved
First, I don't understand why it says [5.5,6), because I'm telling it to use 5.5.1. Second, I'm using dozer-osgi already, I believe it should pick it up automatically.
I tried also using:
<Embed-Dependency>dozer-osgi</Embed-Dependency>
Whit dozer-osgi added, things start to get better, and more complex at the same time. It seems like now it loads dozer, but starts complaining about transitive dependencies:
android.dalvik -- Cannot be resolved
dalvik.system -- Cannot be resolved
javassist.util.proxy -- Cannot be resolved
org.apache.commons.beanutils,version=[1.9,2) -- Cannot be resolved
org.apache.commons.beanutils.converters,version=[1.9,2) -- Cannot be resolved
The beanutils utils is easy to fix. I just need to add the regarding dependencies like this:
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.2</version>
</dependency>
and add "commons-beanutils" here:
<Embed-Dependency>dozer-osgi,commons-beanutils</Embed-Dependency>
Now, it complains about:
android.dalvik -- Cannot be resolved
dalvik.system -- Cannot be resolved
javassist.util.proxy -- Cannot be resolved
org.hibernate.proxy -- Cannot be resolved
The hibernate dependency error is new. I thought beanutils depended on hibernate, but not, is Dozer the one depending on it.
I tried adding hibernate, like this:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.9.Final</version>
</dependency>
<Embed-Dependency>dozer-osgi,commons-beanutils,hibernate-core</Embed-Dependency>
And so on, it is like a look, it gets worse and worse everytime I try to add a transitive dependency. I also tried this, only keeping dozer-osgi in my dependencies:
<Embed-Dependency>dozer-osgi</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive>
Result:
android.dalvik -- Cannot be resolved
dalvik.system -- Cannot be resolved
javassist.util.proxy -- Cannot be resolved
org.hibernate.proxy -- Cannot be resolved
org.apache.commons.beanutils -- Cannot be resolved
org.apache.commons.beanutils.converters -- Cannot be resolved
It is like if Embed-Transitive doesn't work at all.
What is the best way to work with 3rd party libraries when using Maven and AEM? In my case, Maven is using to install the bundles in my AEM instance.
In OSGi you have to distinguish between the build and the runtime. At build time your initial approach was totally fine.
You use dozer and the maven-bundle-plugin creates suitable Import-Package statements. You can check these by looking into the Manifest of the jar.
The rules for package imports result in a range of version that should work with your code. So [5.5,6) is exactly the expected import range.
Now to runtime. Here you have to supply all dependencies of your code (including the transitive ones) as bundles in AEM (or more generally in the OSGi runtime).
So you also need to install dozer OSGi as bundle. If this complains again then you also need to install its dependencies.
This is the default approach and normally totally fine.
Now if you want to make your bundle standalone in respect to having no additional runtime depenencies then you can try to embed all dependencies. Then you only need to install your bundle.
Be aware though that this is not easy. If your code uses some of the embedded classes in its own API then you get into lots of problems with embedding. So if your are not very experienced then better go the way of installing all dependencies as bundles.
To simplify the install process you can create a content package that contains all needed bundles.
You also have to check that all dependencies actually are bundles. In some cases the normal maven dependencies are not suitable. In this case have a look at apache servicemix bundles. It is a project that creates OSGi bundles for popular dependencies and deploys these to maven central.

How to configure maven for alternate deployment repos?

I've been reading the docs for the deploy plugin, and am confused about the altDeployment repository parameters.
There are these three params:
altDeploymentRepository
altReleaseDeploymentRepository
altSnapshotDeploymentRepository
Whereas the altRelease and altSnapshot seem to be fairly straightfoward, I'm not sure what the altDeploymentRepository setting is for. Is that supposed to be a superset of the Snapshot and Release?
Can someone clarify the difference between the three settings and when to use which?
altDeploymentRepository
No idea
altReleaseDeploymentRepository
Let's say you are going to build the artifact which does not have any SNAPSHOT attached to your pom file. Ex: 43.0.1 (this is release version) 43.0.1-SNAPSHOT (this is SNAPSHOT version), release version will always be unique...also it means you have properly tested all the code.
So when you define releaseRepo, your artifact will load into the release repository
altSnapshotDeploymentRepository
SNAPSHOT artifact is useful for initial testing: once you build the code, respective artifact will load into the snapshot repository

Maven: Resolving Duplicate Dependencies

I'm developing an application that will be used internally at our company. In order for it to interop with our other internal systems I have to use some maven dependencies that we use internally, but this is causing some issues with using some external 3rd party dependencies that I also need.
So essentially my pom looks like this:
<dependencies>
<dependency>
internal-framework-artifact
</dependency>
<dependency>
necessary-third-party-artifact
</dependency>
</dependencies>
I've come to find that both of these dependencies have the apache's commons-collections as one of their own dependencies (among a large number of others, but we'll just keep it at one for this question's simplicity).
If I place exclusion rules on both of them for the commons-collections pom I can compile the project, but my resulting jar won't have access to either version of commons-collections and will just result in a java.lang.NoClassDefFoundError exception. Removing the exclusion rule on either of them just results in a mvn compiler error:
[WARNING] Rule 2: org.apache.maven.plugins.enforcer.BanDuplicateClasses failed with message:
Duplicate classes found:
I've been looking through various so q/a's and I can't really seem to find something that's 100% relevant to my situation. I'm really at a loss as to how to resolve this. Am I missing something really obvious?
I've never actually used the maven-shade-plugin for shading, but I think this is the exact use case it was designed for.
Create a new project that uses the maven-shade-plugin (see: http://maven.apache.org/plugins/maven-shade-plugin/) to produce an uber-jar version of internal-framework-artifact which contains that classes in internal-framework-artifact and all its dependencies. Configure the plugin so that it relocates all the classes that are also dependencies of necessary-third-party-artifact to some non-conflicting package names. This new project should produce a .jar with a different name, something like internal-framework-artifact-with-dependencies.
Now modify your original pom so that it is dependent on internal-framework-artifact-with-dependencies instead, and it should work.

How to configure a longer version Number in artifactory

The version-numbers for our jars have to be longer them x.x.x.
We would rather need x.x.x.x to integrate some old-fashioned self-made mechanism.
This is, because we tag our software with x.x.x and as soon as we have a delivery to a customer one specific jar has to be build exactly at this point of time to fit to another backend,
which communicates with our program. For that reason this one jar has the version 2.3.4.1,
when generated and in next delivery of the same Version it is build and named 2.3.4.2.
Now artifactory cannot handle this an doesn't save more than x.x.x.2 in some cases.
So we thought of maybe edit the regular expression in the maven repository layout (see attached Screenshot) Because testing the path in the field below shows,
that it cannot handle the version number. Of course for the rest of our jars still x.x.x has to work..
For Example here is the maven-metadata.xml
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>com.firm</groupId>
<artifactId>someid</artifactId>
<version>1.5.1</version>
<versioning>
<latest>1.5.1</latest>
<release>1.5.1</release>
<versions>
<version>1.4.62</version>
</versions>
<lastUpdated>20120926073942</lastUpdated>
</versioning>
</metadata>
The folder structure looks like:
someid
- 1.4.62
- 1.4.62.1
- 1.4.62.2
- 1.4.62.3
If we deploy an new artifact version (1.4.62.1), the maven-metadata.xml contains the 1.4.62.1 version.
But the artifactory overrides the version number (1.4.62.x) to (1.4.62) after an unspecified time. It seems that the artifactory only support major, minor and revision numbers, and deletes the buildnumber.
Now we looking for a solution do disable this behavior.
We use the JFrog Artifactory version 2.5.0 (rev. 13086).
I apologize in advance that this will be an unsatisfactory answer for you.
Your version format is incompatible with the version format used by Maven. Maven uses a .. format for version numbers. Anything after this needs to be prefaced with a dash for it to be properly used by Maven. For more information about how version numbers are used and formatted in Maven, please refer to this section of the Maven book: http://www.sonatype.com/books/mvnref-book/reference/pom-relationships-sect-pom-syntax.html

Finding list of versions available in a Maven repository for a specific plugin?

Given the following repository URL from my pom.xml how can I determine what the latest versions of spring and hibernate are available in the repository?
http://repo1.maven.org/maven2
Retrieve the maven-metadata.xml file, placed in the artifact directory, e.g. https://repo1.maven.org/maven2/com/sun/media/jai_codec/maven-metadata.xml for an artifact with the groupId com.sun.media and artifactId jai_codec.
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>com.example</groupId>
<artifactId>project</artifactId>
<versioning>
<latest>0.0.5</latest>
<release>0.0.5</release>
<versions>
<version>0.0.3</version>
<version>0.0.4</version>
<version>0.0.5</version>
</versions>
<lastUpdated>20090725212606</lastUpdated>
</versioning>
</metadata>
Programatically or just manually?
Since the repository works over HTTP you can just navigate it manually:
http://repo2.maven.org/maven2/org/springframework/spring/
http://repo2.maven.org/maven2/org/hibernate/hibernate/
http://repo2.maven.org/maven2/org/hibernate/hibernate-core/
As Robert's answer says, the maven-metadata.xml file for each artifact in the repository holds the version information you need. In particular note the latest and release elements in the metadata. The latest element denotes the last version to be published, this may not be the version you want though. For example it could be a maintenance release to an older version, a release candidate, or a milestone. The release version denotes the last published version intended to be treated as a release, so generally you'd want to take this version.
For information the Maven super POM has a special release-profile profile, activated by setting the performRelease property (e.g. by passing -DperformRelease on the command line). Amongst other things, activating this property will set the updateReleaseInfo property of the deploy-plugin so that the metadata will be updated when you deploy.
Depending on what the real use case is, it can be worth looking at http://www.mojohaus.org/versions-maven-plugin/

Categories

Resources