pointing eclipse to correct jar version in mvn repo - java

our maven repo currently has two versions of mockito, both versions are being pulled in as dependencies to other jars, and each is used in a different child project. Our integration-tests, which are a separate project, use a different version then the unit tests used by our core application.
The mockito versions have changed the signature of a method, making them not backwards computable. Due to the jars that each mockito version is dependent on it isn't easy for me to reconfigure maven to use only one version of mockito for each project.
When I run maven directly, from eclipse or command line, this is not an issue, the correct mockito version is used for each project based off of the pom file. However, when I try to run our unit tests in eclipse I am getting a NoSuchMethodError, which seems to be due to eclipse using the incorrect mockito version. Is there a way to ensure my junit tests use the version of version of mockito I want, aka the one specified in the pom file?

The first thing you should do is declaring mockito as a direct dependency of the modules that use it and not rely on it being drawn in through a transitive dependency. Maven/Eclipse/m2e should first use the version that is declared locally.
If that fails to resolve the problem, in my experience, it can help reordering the dependencies in the POM and checking the Maven Dependencies container in the project explorer or the Dependency Hierarchy tab in the POM editor afterwards to see if the right version is now used. Typically trying to move the problematic dependency either to the first position in the dependency list or to the last position resolves the problem.
Another (possibly additional) option is to add an exclude to that dependency which draws in the "wrong" version of mockito. Again, check the Dependency Hierarchy tab to see where the dependencies are coming from.
Finally, you should save yourself headaches and set up a project-wide dependency management that covers the unit tests in your application as well as the integration tests.
Good luck ;)

In Eclipse, go to your run configuration for your unit test. There is a "Classpath" tab there. You should be able to modify your classpath there to use the proper version of the jar.

Related

How can I prevent code from using wrong version of some dependency?

I have a project which depends on a JAR file. The version of this JAR changes often and we are having a hard time trying to ensure we are using the correct one. It is also causing problems when investigating bugs: which version of JAR contains the bug. Some programmers may forget to update corresponding dependencies and include 2 versions of this JAR inside the project, so that an old version may be found by the classloader.
A question is how to account for this issue.
I have a following plan:
1) When an error occurs log the JAR name I am working with to ensure it is a correct version. I plan to use something like
this.getClass().getResource(someResourceINeedFromThatJar).getFile()
2) I can write a test to account for this. But I don't know how I can run a test AFTER the package phase of my Maven build
3) Maybe you can suggest something else for this?
Well, We have same scenario and solved issue by using maven dependencyManagement
It does two things.
Set a default version for dependencies in submodules/child projects
override the version of transitive dependencies
it does override a specified value in a transitive dependency.
The enforcer plugin does not ignore the dependencyManagement. But is unable to recognize the discrepancy since the transitive dependency's version was altered before it went to work.
Here is a nice article : You can go through it:
http://andydennie.com/2012/08/02/maven-enforcer-plugin-vs-dependencymanagement/
And another source: http://maven.apache.org/enforcer/maven-enforcer-plugin/

How to modify the Eclipse Run Configuration classpath?

I'm developing a project in Eclipse JDT, that has optional dependencies on OSGI - that is, it supports being used as an OSGI bundle, and if it is used as a bundle inside an OSGI environment, it will also reference some classes from OSGI.
Now I want to write JUnit test cases for both running inside OSGI and running without OSGI, included in two different test suites. The OSGI tests are run as JUnit Pulg-in Tests and the Non-OSGI tests should be run as normal JUnit Tests.
Now I have the problem, that I couldn't find any way in Eclipse to exactly specify the classpath for the JUnit Test Run Configuration and exclude the optional OSGI jars.
Is there any way to exclude jars or modify the default classpath for an Eclipse Run Configuration?
If not, does anyone have a suggestion, how one should setup JUnit tests in such a case?
The only solution I was able to find is, to create a jar file from my unit tests and run the tests without OSGI from a different project with the test jar file on the classpath. But I would prefer a more elegant solution, ideally without the necessity of a second test project.
With the help of Gimbys comment, I was able to solve the problem. Although it is not possible in Eclipse to modify the default classpath generated by JDT, it is possible to entirely remove the default classpath and then add your own classpath in the classpath tab of the Runtime Configuration.
To remove the default classpath, one has to select the root entry that is named after the currently run project, and then click on the "remove" button. After that one can add all the jar files and projects that should be loaded in the classpath. The downside of this approach is, that jar files, that are normally provided by Eclipse plugins like e.g. junit.jar, must then also be selected manually (e.g. by adding it to a library folder of the project or by selecting the external jar in the plugins directory of the Eclipse installation folder).
I would suggest that you split up your project in 4 separate projects:
Logic: This package contains all the logic, so basically what your program/plug-in does
Logic.plugin: This Project resembles a Plugin-Project (OSGI-Bundle). This project contains only configurations needed for your plugin and everything dependent on osgi. It has a dependency on your Logic Project.
Logic.plugin.test: All the test cases for your osgi bundle. It is the normal plugin approach to split up logic and test cases
Logic.cli: This project contains the command line interface (or whatever your alternate application is). This also depends on the Logic project.
If your CLI project is only very small you may merge it with the Logic project.

Indirectly referenced from required .class files

I'm getting below error in STS:
The type org.springframework.core.env.EnvironmentCapable cannot be resolved. It is indirectly referenced from required .class files
This sounds like a transitive dependency issue. What this means is that your code relies on a jar or library to do something - evidently, you depend on Spring framework code. Well, all that Spring code also depends on libraries and jars.
Most likely, you need to add the corerctly versioned org.springframework.core jar to your classpath so that the EnvironmentCapable class can be found when your IDE attempts to build your project.
This might also be a jar collision issue as well, although that sounds less likely. When an application experiences jar collision (also known as "dll hell"), the compiler is finding multiple jars and classes with the same fully-qualified name. For example, let's say you added Spring to your classpath, along with the entire Tomcat server library. Well, those two jars may contain the same exact named classes, maybe the same version, maybe different versions. But either way, when the compiler looks for that EnvironmentCapable class, it finds two (in this contrived example) - one in the Spring jar and one in the Tomcat jar. Well, it doesn't know which one to choose, and so it throws a ClassDefNotFoundException, which would/could manifest itself as the error you experienced.
I faced same error while i work with spring security on spring-security-config.i jsut deleted that jar in maven repo and gave maven->update Project in eclipse.
it is resolved.Please try it once.
From command line, run "mvn clean install", you'll see project failed and you'll see artifacts in the logs that cause such a problem.
After that, remove artifacts from .m2/repository, then maven update from eclipse.
To avoid jar collision, make sure you declare your dependency versions under the properties tag in the aggregate pom.xml, and use the property name as a placeholder throughout the project. For example 4.2.5.RELEASE in the parent pom, and then in the child modules just use ${spring.version} instead of 4.2.5.RELEASE. This way you can avoid having two different versions of the same library on the classpath.
Also it is recommended to be consistent with the version of spring dependencies. Use the same version for spring-core, spring-web etc.
If you are using maven, then you can use the maven enforcer plugin to ensure dependency convergence, and avoid further issues with transitive dependencies.

How check if dependency is used by any of my classes and list them in Maven?

I want to do some clean up in POM.XML. How can I check which dependencies aren't used at all by my code and if one is used then how tell which one is it?
Of course I don't want to simply delete dependency and then search for errors in IDE, because that could take ages when pom has got about 80+ dependencies.
I'm using SpringSource Tools Suite version of Eclipse.
Greetz
Have a look at the Maven Dependency Plugin. When running, it should list the dependencies that you declared but do not use, but also which intransitive dependencies you use without explicitly declaring them. Note that it you use reflection, the report may not be accurate.

Why is my Mockito-based unit test unable to run in Eclipse?

I have a Maven-managed project that uses Mockito mocking in its unit tests. I can run all the tests within a Maven build, and they run without error (and pass!). However, if I right-click a single test function, and choose "Run As -> JUnit Test", I get an exception java.lang.NoSuchMethodError: org.mockito.Mockito.doAnswer(Lorg/mockito/stubbing/Answer;)Lorg/mockito/stubbing/Stubber;. Of course, the "missing" method is there if I look at the sources, and like I said the tests compile and run from the command line.
Best I can think of is if Eclipse is trying to "help" me by providing an outdated Mockito artifact (I'm using 1.8.5 in my Maven dependencies) for the JUnit plugin, akin to how the Maven plugin can stick you with an oddball version of the Maven runtime for certain tasks.
Is this the problem? Is it something else? Can I fix this?
ETA: Apparently this may relate to a known issue. There's a good chance that it stems from having multiple versions of Mockito in my classpath (thanks, Maven :-/ ). I seem to have my house in order -- Eclipse can run the tests now -- but unfortunately the bug has bitten my Hudson. I have to track down how to remove the old JAR from the classpath there as well.
Make sure the unit-test classpath has the correct mockito. You can check this from the run dialog. Btw, Eclipse does not ship with mockito, so perhaps you are having two versions of it. Take a look at your maven dependency graph and search for duplicates.
I had the similar problem and I found that I had both "mockito-all 1.8.x" and "mockito-core 1.9.5" in my classpath. I was supposed to use only 1.9 but somehow eclipse was putting 1.8 before 1.9.5 in the classpath. I removed 1.8.x and it worked ;)

Categories

Resources