Need Different Versioned Dependencies In the Same Project - java

I have a project that has two needed dependencies for it. These dependencies have in turn apache cxf dependencies. Dependency A uses apache cxf versions 2.4.0 where dependency B uses apache cxf versions 3.1.0.
Because classes were changed between the versions, using one or the other results in ClassNotFoundException's.
A little description of what they are, Dependency A is the client jar for some old SOAP webservices. This includes the autogenerated files from wsdl2java. Dependency B is the client jar for a new REST webservice.
The main project uses Maven to handle dependencies, is a war, and is on tomcat 7.
Any thoughts for what I could do to try and get this to work correctly? I have already tried making the REST client a jar-with-dependencies and bringing it in through Tomcat's common classloader with no luck.
EDIT
After reviewing the dependencies I am bringing in, I can't simply update the dependencies because I do not have control of some of the dependencies being brought in. I would need to alter what those jars are doing and that will not work.

Its never a good idea to use two version of same dependency as it can create discrepancies in your project.
Ideally you should latest version and then make the old code compatible with latest version

Related

Run two versions of elasticsearch in java application using maven

I have a legacy monolith application, which uses elasticsearch 1.X and now we need to run elasticsearch 7.X in the same application, so that same application index and query data in both version of elasticsearch.
In my project, there are multiple modules and they all have their own POM and parent POM, and my new module which uses elasticsearch 7.X depends on some module which uses 1.X.
Although I have excluded 1.X specific dependency in module which uses 7.X, Still it gives me below Error:
[76B7CCD2] java.lang.NoSuchFieldError: LATEST at
org.elasticsearch.Version.(Version.java:49) at
org.elasticsearch.common.io.stream.StreamInput.(StreamInput.java:114)
After doing a lot of research and using this and this link, As explained I excluded the elastic 1.x dependency but still looks like as my other sub-module still has ES 1.X and which is required as well, hence overall classpath of my application has both versions of org.elasticsearch.Version java class from the same package org.elasticsearch, which I feel is the root cause.
Now, How can I include the same class from the same package from two different versions of a same library.
You can't. You can only have one class with a given full qualified name (package + name).
You can try to shade one of the packages (i.e. rename it) with the Maven shade plugin (never tried that, actually), which might work.
Usually, you need to change code and fiddle around until you find a version of elasticsearch that works with all dependencies.

Need help packaging a webservice client jar in Java

We have a series of web service APIs that we have also written clients for so that we can easily re-use them in other Java applications. I now have need to be able to use the clients in an environment outside of a webserver. I used the maven-assembly-plugin to create a zip containing all of the client's dependencies and it worked fine except for the dependencies that would be provided by wildfly. I added the appropriate resteasy jar files to a command line app and everything works. Now I would like to be able to package the client 2 ways; with the resteasy jars and without. The apache shade plugin looks like a good option to do this but I can't see how to include an extra dependency (resteasy) that is not referenced in the project. Has anyone done this?
Edit:
I have tried both the maven-assembly-plugin and maven-shade. Shade looked promising until I attempted to deploy the jar. I got security warnings assumedly because the dependency jars that it repackaged were signed and so repackaging them caused errors. In any case it looks like using profiles is part of the key. I can set up a separate profile in the pom that will include the resteasy dependencies and so include them only when desired.
For others looking at this question, I haven't completely solved this but adding a profile is part of the key. If you add a profile to your pom, you can add the resteasy dependencies only under that profile. If you add the maven-assembly-plugin and the resteasy dependencies under that profile, you can build a jar containing all of the dependencies without affecting you regular release.

excluding a maven dependency from grails BuildConfig

I'm using grails 2.5 and was using grails spring websockets in my project and everything was ok. Now, as I want to implement login with Google added the maven dependency to BuildConfig for google api client:
compile 'com.google.api-client:google-api-client:1.20.0'
And now, when I run the app I get this error
java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonFactory.requiresPropertyOrdering()
This is because there's a conflict between the Jackson libraries that spring websocket plugin and google api client are using.
As I could see, it looks like google api is using an outdated version of jackson.
Is it possible to exlude jackson to be imported from a maven dependency? I know that from a grails plugin is possible adding 'exclude'. But it doesn't seem to work for a maven dependency, I've added this but with no luck:
compile 'com.google.api-client:google-api-client:1.20.0', { excludes "com.google.api-client:google-api-client-jackson2:1.20.0" }
Just to remind, the google api client dependency is under 'dependencies' group in BuildConfig, which is using mavenCentral() to get the dependencies, not under 'plugins'.
Does anybody know how could I fix this?
thanks
EDIT: Probably not ideal, but I could solve this problem just adding the latest jackson dependency
compile 'com.google.api-client:google-api-client:1.20.0', {
excludes "com.google.api-client:google-api-client-jackson2:1.20.0"
}
compile 'com.fasterxml.jackson.core:jackson-core:2.7.2'
I don't think what you are trying to do is possible. Exclusions can work for plugins because the source is downloaded and compiled locally. For dependencies, you are using maven, which is downloading jars. You can't tell maven to exclude part of the jar.
The Google code you want to use may depend on other methods of the Jackson version it depends on that are not present in the version you want to use. In that case, if Maven allowed excluding Google's declared version of Jackson, the Google library would not even work. (The same problem would occur for plug-ins if they needed a different version of some library at compile time.)
You could try making your own version of the Google jar that uses your preferred version of Jackson. If it doesn't depend on methods from the older version of Jackson, that could work.

Resolving transitive dependency conflicts in Java

I am trying to build a Dropwizard (Jersey) REST endpoint that communicates with HBase. Although these are my only two top-level dependencies, both of these dependencies come loaded with many transitive dependencies that conflict. A simple example of such a conflict is Google's Guava:
The HBase client specifies version 11
Dropwizard specifies 18
Dropwizard will not work with version 11 and HBase will not work with version 18.
I have examined the Maven shade plugin documentation, but it does not seem to let you relocate classes found in dependency jars. So I don't know how to resolve this issue short of separating these two components into separate JVMs.
This is a dirty solution. But you could...
Create a project / module where you define a set of service interfaces that your dropwizard app will use to talk to HBase.
Create another module / project that implements these interfaces and uses the HBase classes. Shade this project.
In your Dropwizard project include only the interface jar but create a task to copy the shaded artifact into your resources.
Create a JARClassLoader for your shaded HBase client artifact. You may have to make a special subclass that does not delegate to the parent as by default the classloader will ask the parent to resolve linkages and may pull the newer version of guava from outer classloader.
Ask for an instance of the service contract from the Jar loader...
Businessing api = Class.forName("com.awesome.Businessing", true, jarLoader).newInstance();
Try to specify concrete versions for those dependencies in <dependencyManagement/> section of you pom.xml.

Difference between Apache CXF Maven distribution and CXF distribution

I need to use Apache CXF and Maven in my current project.
When I downloaded CXF from the Apache site I noticed a set of Jars in the distribution.
But when I added the cxf-rt-frontend-jaxws dependency to pom.xml and issued an mvn package command, the lib folder had some different files, for e.g.
cxf-api-2.2.7.jar
What is the difference between the 2 distributions (if there is one)?
In general, the downloaded distribution is not needed at all if using Maven. The downloaded distro does provide some useful examples, etc... that can be helpful, but to build applications, you don't really need it.
The lib dir in the download, however, uses the "cxf-bundle" jar (renamed to just cxf-VERSION.jar) instead of the individual jars. If you use maven, you likely will use the individual modules (like cxf-rt-frontend-jaxws). You can delete the lib/cxf-VERSION.jar and copy all the jars from modules/*.jar to lib and pretty much accomplish the same thing with the download. Thats just a BUNCH of jars though.
Note: you really should use CXF 2.6.2, not 2.2.7. 2.2.x is unsupported and has various security issues with it that are fixed in the newer versions.

Categories

Resources