Quantcast
Channel: biotext.org.uk » LJC
Viewing all articles
Browse latest Browse all 4

NoSuchMethodError when running JUnit tests in Eclipse

$
0
0

This is worth a quick post as I couldn’t find a solution on Google and it took me an hour or two of fiddling.

I have a Maven project, call it frontend-war, which contains the main service code for FuncNet. A unit test kept failing in Eclipse with NoSuchMethodError, one of my least favourite screw-ups to disentangle.

In this case it was particularly frustrating, as the method (on a class in one of the main project’s dependent jars, called service-utils) definitely existed, was public, and had the right signature. Also, even more weirdly, when I ran the tests in Maven from the command line, they passed.

Cue all the usual Eclipse cargo-cult dead-chicken-waving — cleaning everything, closing and reopening projects, etc. etc. No joy.

Then it hit me… (solution below the jump)


One of the other jars included by frontend-war, called sessionDB, also included service-utils — and was using an out-of-date version. This version didn’t include the method I was calling (at least not with that signature). The dependency hierarchy looked something like:

frontend-war-CURRENT
    service-utils-1.2.9
        …
    sessionDB-1.3.3
        service-utils-1.2.4
        …

So I rebuilt sessionDB against the latest version of service-utils, then rebuilt frontend-war against that, and it worked.

So, my fault for getting myself into jar hell, although even if you don’t bring it on yourself, it’s hard to avoid it if you use a lot of open-source components, and Maven — which I still argue is a timesaver overall — tends to exacerbate it. Take a look at the Dependency Graph view in Eclipse’s POM Editor sometime — if you see any red arrows, that means two or more different versions of a dependency are being requested by different modules within your project.

So why did it work on the command line and not in Eclipse? To be honest, I don’t know in detail. But in cases like this, the classloader will (AFAIK) just pull in whichever version is requested first, so Eclipse’s classpath management must have happened to process the dependencies in a different order from Maven’s — meaning it worked by pure luck.

Note: My solution — updating sessionDB to use the latest service-utils — wasn’t a problem, because all three of the modules in the unholy ménage à trois belonged to me. But what do you do if two third-party libraries request different versions of the same jar?

A famous notorious example of this tends to happen with Hibernate, which depends on a really out-of-date version of ASM — or at least it used to, I haven’t checked recently. Lots of open-source projects use ASM but more recent versions clash nastily with the old one Hibernate requires.

The solution in this case is to use Maven’s exclusions clause to specifically exclude ASM from Hibernate’s transitive dependencies. Thankfully it can just use the more recent versions without problems.

But what would you do if one of the libraries you were using depended on a method that was no longer available in a more recent jar? Then you’re really in jar hell. Answers on a postcard…


Viewing all articles
Browse latest Browse all 4

Trending Articles