Maven & Jenkins order classpath alphabetically, but not locally - maven

I'm currently facing severe classpath problems with Jenkins 1.532.2 and Maven 3.0.3. Locally, the classpath order is correct and all JUnit test work. On Jenkins though, the classpath is ordered alphabetically, not like in the pom defined.
Output of mvn dependencies:build-classpath on Jenkins (partly redacted):
axis/axis/1.4/axis-1.4.jar
axis/axis-wsdl4j/1.5.1/axis-wsdl4j-1.5.1.jar
com/company/ownlibrary.jar
com/microsoft/sqljdbc4/3.0/sqljdbc4-3.0.jar
com/oracle/ojdbc6/11.2.0.1.0/ojdbc6-11.2.0.1.0.jar
commons-codec/commons-codec/1.5/commons-codec-1.5.jar
commons-discovery/commons-discovery/0.2/commons-discovery-0.2.jar
commons-lang/commons-lang/2.4/commons-lang-2.4.jar
commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar
junit/junit/4.11/junit-4.11.jar
log4j/log4j/1.2.17/log4j-1.2.17.jar
org/apache/axis/axis-jaxrpc/1.4/axis-jaxrpc-1.4.jar
org/apache/axis/axis-saaj/1.4/axis-saaj-1.4.jar
org/apache/poi/poi/3.8/poi-3.8.jar
org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
org/mockito/mockito-core/1.9.5/mockito-core-1.9.5.jar
org/objenesis/objenesis/1.0/objenesis-1.0.jar
org/slf4j/slf4j-api/1.7.5/slf4j-api-1.7.5.jar
This is the output of mvn dependencies:build-classpath locally executed (partly redacted):
com\oracle\ojdbc6\11.2.0.1.0\ojdbc6-11.2.0.1.0.jar
commons-logging\commons-logging\1.1.1\commons-logging-1.1.1.jar
org\apache\poi\poi\3.8\poi-3.8.jar
commons-codec\commons-codec\1.5\commons-codec-1.5.jar
de\company\xyz.jar
de\company\xyz2.jar
com\company\own.jar
log4j\log4j\1.2.17\log4j-1.2.17.jar
commons-lang\commons-lang\2.4\commons-lang-2.4.jar
com\microsoft\sqljdbc4\3.0\sqljdbc4-3.0.jar
axis\axis\1.4\axis-1.4.jar
org\apache\axis\axis-jaxrpc\1.4\axis-jaxrpc-1.4.jar
org\apache\axis\axis-saaj\1.4\axis-saaj-1.4.jar
axis\axis-wsdl4j\1.5.1\axis-wsdl4j-1.5.1.jar
commons-discovery\commons-discovery\0.2\commons-discovery-0.2.jar
org\slf4j\slf4j-api\1.7.5\slf4j-api-1.7.5.jar
junit\junit\4.11\junit-4.11.jar
org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar
org\mockito\mockito-core\1.9.5\mockito-core-1.9.5.jar
org\objenesis\objenesis\1.0\objenesis-1.0.jar
I use Maven 3.0.3 so it should use the pom-defined ordering of dependencies.
What can be the source of this problem and how can I solve this?
Additional info: As you can see on the classpath items, I'm building locally on Windows and Jenkins runs on a Linux OS.
New information: The Maven process on Linux also does not work correctly. I tried to build it locally on the machine, on which Jenkins runs, and the result is the same. The classpath is ordered, although I tried Maven 3.0.3 and 3.2.1

Updating Maven to 3.2.1 helped with the sorting classpath, but not the classpath problem. The classpath is not sorted anymore on Jenkins, but the resources are loaded in a false order nonetheless.

IMHO, class path order should not matter. If you have issues, it means you are loading more than one version of the same jar. You should not rely on class path order.
You should understand why it happens and if you cannot avoid it, use the mvn dependency:tree to figure out where the "bad" jar is coming from, and add an exclude in the dependency that's responsible for it.
I hope this helps.

Related

Setup maven pom to work with dependencies across environments

I have a Java projects a-1.0.jar with ojdbc.jar dependency and b.jar that depends on a-1.0.jar and ojdbc.jar. I am trying to make it work on my machine, new user machine and a Bamboo server.
Desired behavior:
On local machine git clone <git_url>, mvn clean install, java -jar b.jar project should run. Bamboo should checkout and run project.
On Bamboo: a plan can check out a project and run it. Build should track version of b.jar built and a.jar used.
So far I saw these options:
<systemPath>${project.basedir}/lib/a-1.0.jar</systemPath>: maven warns that it will fail to resolve dependencies
A Perl script to run mvn install for each dependent jar before building the project
(1) defeats the purpose of DevOps automation
(2) makes it unclear which version of a jar was used
(3) installs the jar, but java -jar b.jar fails a.jar is missing
I can overcome this with another Perl script that adds the dependent jars to a classpath
These are basic tasks and as a build tool Maven should be able to do it.
How to tell Maven to three goals below?
(1) For each unknown import - get a jar from lib folder
(2) Make a set of dependent jars. That is don't import ojdbc twice
(3) Pack a self sufficient jar that runs, not fails with "stuff is missing"
Seems like you need to create an executable jar - and for this, you can use various approaches.
One of them is, add maven-shade-plugin which puts all dependencies into single jar, while taking care of potential resource collisions.
Try non-maven-jar-maven plugin. It adds jars that are not in the maven central.

can't find my maven artifacts

I'm working in eclipse and I have a problem that I can't import my personal java libraries.
I created the libraries and 'installed' them into my local maven repo (using mvn install). This created a subdirectory related to the 'version' name that was in the POM file from when I ran the command. Which seemed fine.
So in this directory there where the usual jar files and other stuff.
When I released this file I manually changed the name of the version in the POM. going from 0.0.1-SNAPSHOT to 0.0.1-RELEASE
This seems to have worked as I would have expected.
However I can't seem to find import the new release jar.
Using the maven repositories browser in eclipse I can see that the new artifact is in the 'local' repository.
I try to add the dependency in the following methods:
Select the main project -> Maven -> add dependency.
This adds the dependency details into the pom but with a type value detail of <type>pom.lastUpdated</type>
Select the project pom.xml file -> Maven -> add dependency.
This time the artifact for the 0.0.1-RELEASE is greyed out I can select it, but I guess nothing is actually happening.
The original 0.0.1-SNAPSHOT it selectable, and if I use this I do not have a <type> detail in the pom.
I don't understand why there is a difference in the RELEASE and SNAPSHOT artifacts, as they have both been generated in the same way, and clearly they are both visible in the browser, the contents of the directory on disk are the same. The file names and contents are identical with the exception of the word RELEASE or SNAPSHOT.
I know that I can simply add in the RELEASE jar to my build path, but this seems to be a ridiculous thing to have to do if I intend to use maven (or do I need to do this).
I don't want to use an external repo for storing my artifacts, and I'm not too keen to go to the trouble of installing nexus (or similar) on my local machine (just because I've had trouble with it in the past).
What am I missing so as I can get my maven project to see my local repository and all its artifacts.
Thanks in advance.
David
ps I've already tried things such as mvn dependency:purge-local-repository which definitely pulled in / updated all the local jar dependencies.
So I've managed to work around my problem.
As such this solution is ridiculous, and breaks all the purpose of maven.
So I found (from running maven from the cli) that there was an error in the parent of the project I was attempting to use.
The parent was missing a direct link to the scm plugin (version error).
Once I solved this problem, I then returned to the sub project, and got a lot of errors from missing stuff from the parent.
Essentially it was not 'seeing' all the log4j dependencies.
The solution (well non-solution really).
Add all the log4j dependencies to the sub project.
Edit in SCM and surefire test plugins (as it also started to fail the test code due to missing junit).
So this is great.
I have to define all my dependencies on log4j and in my sub / child project's pom.xml file.
I also need to define them all in my parent's pom.
As it then still refused to run tests in my new project (that used the above as a dependency), and refused to find log4j also. I then decided to add all of these as dependencies for my current project.
Great.
I thought the whole point of maven was I could define my dependency on log4j in my my logging library that I use (which is the dependency), and then it would 'automagically' pull in all the required from this dependency.
Clearly not.
As stated at the start. This is NOT AN ANSWER it is a crazy work around.
My logging library that I use should be able to define its own requirement on a specific log4j version (such as moving from log4j to log4j2), and then when I include this as a maven dependency any change to the required dependency should be seen automatically.
But No : I have to import the dependency on log4j in my other projects also. So now if I had updated my logging library from log4j to log4j2 I would need to go to all my project that use this library and update their pom's to ensure that I have the correct version of log4j.
Seems the whole point of maven has just been lost!
Can someone please tell me where I am going wrong!
David.

How to configure maven multi module project and FindBugs?

I have a multi module maven project ('assembler'), and I would like to add a FindBugs phase.
The problem is that some of the projects are not able to build stand alone since have dependencies on other projects... however when I invoke mvn package from the 'assembler' project - it works fine and all inner dependencies are resolved.
The problem is that when mvn findbugs:findbugs command is executed, those inner dependencies are not resolved, and maven complains.
Searching Google, I found a way to make it work, using mvn install, but I do not like this approach since eventually this should be used in CI with Jenkins and I do not want to rely on local maven repo on the build server.
Will appreciate hearing your ideas.
Thanks.
Don't be afraid of mvn install, it is your friend. What you need is to set up a centralized Maven repository (such as Nexus or Artifactory) or rent one (such as Bintray) to which you deploy your Maven artifacts to.
Jenkins or any other decent CI engine can do the actual deploying for you, either natively or through Maven. Once deployed, other users - Jenkins included - will be able to resolve their dependencies and you will be able to run FindBugs, PMD, JaCoco, host Javadoc or pretty much anything you want.
Side-note: Don't get confused by the term deploy as most people new to Maven usually get. In context of Maven, it has absolutely nothing to with your target environment. It simply means that an artifact is pushed out to a remote repository and nothing else.

maven - how does it work? Missing some some jars

I am trying to move my MyEclipes projects to maven. But of course there are problems. After creating a web priject I get missing jar files - about 5
org.springframework.security jar files e.g. org.springframework.security.ldap-3.0.5.RELEASE
show as missing in the jar build path. They are not in the corresponding .m2 directory. I un-installed ME4S, and deleted .m2, which force .me to be rebuilt on re-install, but it has the same problem.
How do I fix this?
It would be very helpful to understand how the .m2 process works - where is this coming from and how is it controlled?
I am not sure about the MyEclipse part, but this seems to be a pure maven question.
Maven (2/3) uses the pom.xml. This file describe your project. In that file you should define a list of dependencies (which can have their own dependencies and so on).
Maven read the pom.xml and build the classpath accordingly using direct and transitive dependencies.
You can use the mvn dependency:tree command to see how your classpath is built.
More on the plugin page

Maven3 - How do I found dependency resolution? ( mvn depedency:tree does not work for mvn3 )

With maven-3, it uses aether to resolve dependency.
Unfortunately, "mvn dependency:tree" use legacy (maven-2) resolution engine.
How do I find out the true dependency resolution for maven-3. I'm running into an issue where "exec:exec" creates different classpath then "dependency:tree".
In maven 3 - compatibility notes, it says I need to use "-X" and look at the log but there is no pointer what to look for.
Also, "assembly:assembly" brings in different 'jar' than when I print out classpath from "exec:exec".
dependency:tree is the correct way to get the project dependencies. Since version 2.5 of the plugin it now resolves the tree using aether.
exec:exec runs the maven exec plugin. The classpath it generates is based on the plugin dependencies, if specified. It is relevant only for the purpose of the plugin execution and not to be taken in the context of project.
The similar explanation holds good in case of assembly:assembly. The jars that it brings in entirely depends on the plugin and assembly-descriptor configuration.
Since version 2.5 of the Maven Dependency Plugin, dependency:tree works with Maven 3 (see the bug report, and the release notes)

Resources