miércoles, 12 de agosto de 2015

Maven Plugin ClassLoader conflicts

Why Maven oh why????
We love you, we really do.  But some times you just manage to piss off your fans.

Let me tell you guys a story...

Imagine you have a pom.xml file that contains the following dependency:


  com.my.artifact.group
  my-artifact
  1.0.0

Now for the sake of the story let's say you have your custom plugin, or any for that matter:

  com.my.plugin.group
  my-plugin
  1.0.0

Now the hero in this story is happy with his new pom file and ready to make it build so he goes ahead an do:

mvn clean package


BUT WAIT, the build failed!!!!
The exception is not really importan but, again, for the sake of the story let's say it's a NoSuchMethodException.

Afterwards our hero starts tracking the cause of the error, and it so happens that the class with a missing method is part of
my-artifact
But how comes?
When he goes and looks for that class code the method is there.
Weird eh?

He keep on and decides checking different versions of the same artifact and he finally finds out that version 2.0.0 of the artifact does not have such method.

- But wait, I'm not using that artifact am I? - he thinks for himself

He does:
mvn dependency:tree

And also
mvn dependency:resolve

And as he thought the version is the correct one.
After a few hours of useless tests he decides to check the plugin, as it's the only thing left to check.

When he runs:
mvn dependency:tree

He sees something odd:
com.my.artifact.group:my-artifact:2.0.0

- OMFG 2.0.0, WTF!!!!! -  He thinks


And here the story ends!




Now for the more realistic part of this blog, the problem here is Maven uses the same classloader to load both the plugin's dependencies as well as the ones of the project you are trying to build.

So far so good, the problem comes when, like in the story two different versions of the same jar are not compatible. In our story they remove a whole method.

It get's worst there is no easy way track this issue as the logs will only who show that there is an issue but they will also show that the jar being loaded is the one declared in the pom's project giving you now clue on where the problem is coming from.


Solutions:


Well not much to do here. If you control the plugin you could just go ahead and check that pom and exclude the dependency (if possible).

If you don't control it, you can try excluding the dependency or the transitive dependency. Although after a quick search doesn't seems to be that easy.

Any way, the conclusion here is:
* Next time you face a similar problem check the plugin
* To Maven team, guys please find a way to separate the plugin classloader from the one of the application being build.


P.S.: didn't have time to create nice code snippets sorry!




miércoles, 13 de mayo de 2015

Dependency Hell

So it seems I'm on a roll... No long ago I stumble upon the jar hell issue, several times in a short time span and thus I write a small post about it. Now I stumble upon the Dependency Hell issue. So what is that all about??? Have you ever come across a maven error like:
failed: An API incompatibility was encountered while executing
Well if you had, the you're fu%#&. Well not that much but it's an interesting problem to have. Now I have found this article quite useful http://discursive.com/2014/03/17/maven-3-2-1-provides-a-new-cure-for-dependency-hell/, but in short:

When you have a dependency hell problem, is because maven is loading the same jar but different versions of it and they happen to be incompatible

Not really helpful right?
What it means is either, a dependency of your project of a transitive dependency is in conflict. Now when I say transitive, I mean transitive something in the third or forth degree may cause a problem. That's a dependency of a dependency of a dependency of a dependency. Not only that, plugin dependencies come into the game too.

Now all this this is lovely, how do I solve this mess???

There is no straight forward way, I'm sorry to say, at least none that I know of.
Usually  the firsts lines of the error will point you to the class and the method that is causing the problem.
From there, you first need to find which maven artifact contains that class.
One you have located that artifact, look for it in the stack trace chances are that you'll find it more than one time.
Now here is when it get's funny, you need to pick one of the versions of this artifact and take it out.
The problem is that the stacktrace is not arrange in a hierarchical way so when you see the module you want to take out it may be because it's in your pom, or it's a transitive dependency of the artifact just above (in the stack trace I mean). But it could also mean that the one above is a transitive dependency of the one just above or to levels up.

So here you will have to start using mvn dependency:tree, and play Find my artifac. Now this command will not output all the transitive dependencies but just a few levels of the whole tree (may be 2 or 3). The other problem is it will only show the version of the artifact that's being loaded during the build (not that the other are not loaded but you get my point).

Any ways, removing unnecessary dependencies ore telling a dependency to exclude a particular jar will probably solve the problem, the fun of this game it to spot the correct one.


I know this post is not perfect guide on how to solve this problem but I hope it'll give you a better idea of what you're dealing whit and an idea on how to start solving it.



viernes, 17 de abril de 2015

XPath and Name Spaces, don't you hate them too??

How about running a XPath expression from Java?
Pretty straight forward right, oh wait NAMESPACE!!!!

Here's a example on how to create your xpaht parser and the more complex Name Space Context.
Let's start with the NameSpaceContextImpl

Now the actual Xpath parser imple: Hope it helps guy!!!

The famous Jar Hell issue

So I reckon I'm not the first one to have this problem. I'm certainly not the one who will tell you how to solve it BUT!!!!

Here is a really small example about using the JHades tool 

Why am I posting this?
Because the example in the home page is a little bit outdated and if you search JHades for the maven dependency the first 4 links you hit get it wrong.


Maven Dependency


Java Code

You should place this in some place that you are sure it'll get run during building.
If you have issues during tests. Just create a test where the test method has this code.

Hope this helps!