I'm using jarX that has embedded dependencies that conflict with my own dependencies, so I'm creating a classloader to isolate jarX's dependencies from my main classloader.
jarX is outside my app's classpath, but my classes that use jarX's classes are in my classpath, so when I instantiate my classes loaded via the custom classloader, I run into the class identity crisis in the form of ClassCastException as the JVM's version of my classes are considered different from those loaded by my custom classloader.
I found this blog post where they solved a similar problem by only interacting with the custom classloader loaded classes via reflection, which seems to solve this problem.
It just feels like it should be easier than this. Does anyone know a better way to handle this problem?
The easiest way is to open jarX, remove the offending classes, and done. It is a bad practice to embed dependencies in a JAR unless that is JAR is meant to be used only as a standalone runnable fat-jar. JARs that are meant to be used as libraries should not embed dependencies.
When you notice that people package third-party classes in their JARs, I'd recommend pointing out to them that this is generally not a good idea and to encourage them to refrain from doing so. If a project provides a runnable fat-jar including all dependencies, that is fine. But, it should not be the only JAR they provide. A plain JAR or set of JARs without any third-party code should also be offered. In the rare cases that third-party code was modified and must be included, it should be done under the package namespace of the provider, not of the original third-party.
Finally, for real solutions to building modular Java applications and handling classloader isolation, check out one of the several OSGi implementations or project Jigsaw.
Can you post which jar is it and what are the classes that it overlaps, with the full stacktrace? Have a look at this tool I wrote to generate a list of duplicate classes in the WAR, there is an option to exclude duplicates of the same size.
These are some measures that can be done to solve this:
Try to reduce the number of duplicates by doing a case by case analysis of why the overlap exists. Add maven exclusions for jars that are complete duplicates.
Check if there is a version of the same jar without the dependencies that you could use, which jar is it, xerces, etc?
If there is no jar without dependencies, you can you exclude the other jar that overlaps jarX and see if the application still works. This means all components that need the jar have a compatible version of the jarX library
Separate the application into two WARs each with the version of the library you need. This will reduce the number of libraries in which
These where measures that are likelly to be more maintainable long-term
If the previous measures do not work:
open the jar, delete the duplicate classes and publish in the maven repository with a different name jarX-patched
you can configure nexus to serve a patched jar instead of an unpatched jar transparently
If your container supports OSGI that would be even better, but if you don't use a OSGI container for development as well, then the application would not work in development.
Related
I have several huge legacy applications that I am now working on. After months of testing, we finally reached deployment only to have a "failed to load webapplicationcontext" which foiled the whole endeavor. That specific failure was due to a name space conflict between two transitive dependencies. i.e., both jars had a class to load as: org.something.somethingelse.ClassName.
There are ~100 jars pulled in via maven for this single project. Several explicit, most transitive. Ideally, I would like to know every single jar I'm putting on my classpath. Practically, though, I don't have enough experience or time to look through every one of them for potential issues.
Is there a tool, technique, or eclipse/intelliJ feature that I can use to scan a set of jars for similar namespaces?
You can try with enforcer plugin. In a maven project, it's very usefull when you need to detect different jar depenndencies of same artifact with different version.
You can read this post too.
So there were a couple of different solutions here. I ended up using jhades (http://jhades.github.io/) to identify conflicts within the war, and then tattletale (a utility provided by JBOSS support) to identify conflicts between the war and the container.
I added 'exclude *' tags to all the explicit dependencies to prevent any transitive dependencies from loading. I added explicit dependencies for anything that still wasn't present. After ensuring that all compiled dependencies played nicely, I set any libraries identified by tattletale to provided and added the necessary module to standalone.xml. These things like hibernate, apache libs, servlet APIs etc.
The other thing I discovered which made this so difficult to identify in the first place is that JBOSS's classloader indexes libraries according to how the hosting file system orders them. On Windows, which is where we do 90% of our development, they are always loaded alphabetically. On linux, where we do our production deployments, the order is pseudo random. Our production servers are built from the same images, so a RHEL 3.4 server will load in the same order as another 3.4, but a 3.5 will load entirely differently. Thus, we did not see a failure until the stars aligned and we deployed to a 3.6 server. In production.
Hope this helps someone.
I have an application that uses Jasper to generate reports. In order to encapsulate the complexity and provide a uniform interface with the Jasper API, I have created a "intermediate" interface that wraps the Jasper classes and delegates client calls to them. This will also make it easier to change the report machine in the future - to Crystal Reports, for instance.
The thing is, since the Jasper classes are in the classpath, developers (including myself) can accidentally use some of its classes directly in the business code, and that may pass unnoticed for a long time. I would like to avoid that, or at least be notified when that happens.
The environment is basically eclipse, maven, git, sonar, bamboo ci.
I'm sure this is not an uncommon scenario, so, what is the best way to deal? Design patterns, eclipse/maven plugins, sonar alerts? Or maybe something dead simple that I'm just not seeing?
In maven you can specify a library is for runtime only. This allows you to not compile against that library at all. If you don't use Jasper from maven, you could avoid including it at all. You can force this by adding an <exclusion> if it is a transient dependency.
You should have two separate eclipse projects: One for the reporting library, one for the rest.
The reporting library project contains your interfaces, the Jasper jar files and the Jasper-specific implementation of the interfaces.
The other project depends on the reporting library project (you can set project dependencies in the projects properties dialog under "Java Build Path" -> "Projects").
As the reporting project only exports the source folder to the other project, the jasper classes are not visible to it at development time.
I haven't used it much myself, but if you ever need more control over your dependencies you could try DCL Suite, an Eclipse plugin. It lets you define constraints between modules and you can declare the modules to be a class, a set of classes, packages, etc
That would only be possible if you handled classloading of Jasper and included it as a resource (a jar file) inside your own jar. Then no one would know it was available directly. Here's an example of how you can include jars inside your own jar file -> An embedded jar classloader in under 100 lines.
I am writing an application plugin in Java, and my plugin has dependencies on several third-party JARs. I am bundling these dependencies with my plugin so that I can deploy just a single JAR file.
The host application may also be running plugins from other vendors. Unfortunately the host application puts all the plugins on the classpath, and I am not able to change this behavior. If another vendor's plugin is loaded before mine and uses an incompatible version of a dependency, my plugin could crash.
I am not able to test compatibility between my plugin and other plugins ahead of time. It is also not acceptable for me to say that there is an incompatibility between the plugins--if my plugin crashes, it reflects poorly on my company. The customer does not care why my plugin crashes, they will attribute it to poor programming on my end.
I am looking for a way to prevent other vendors' plugins from interfering with my own. Is it possible?
I've heard of custom classloaders but I'm not sure if that solution will work for me.
You can use Uberjar. What it does is move all your jars/classes to a custom namespace so that none of your classes clash because your dependencies have a different namespace.
You might want to look at maven-shade
You could try to embed an OSGi container in your plugin. This would allow you to run and load dependencies as OSGi bundles in isolation from the system classloader.
Instructions for Felix.
I use maven to manage a core package and two appliaction packages that both depends on the core package. For technical reasons, I can't make a full assembly for each application package, which means that I've to distribute each application package with the core package as a separate JAR which will be put in the classpath of the application.
I also need to obfuctate my JARs. I can achieve this easily for a single assembly, however, I'm not sure if it is possible to obfuscate all classes while keeping my JAR separated ?
Someone has already been faced to this problem, and if so, is there any possibility to do this with maven and proguard ?
Thanks in advance!
Although I not sure if you could obfuscate two jars separately which depend on each other, but I have seen similar things done.
This can be achievedi by keeping some clean interface(s) between the two jars. This will allow you to keep the interface between the jars as unobfuscated and rest of the classes can be safely obfuscated without breaking the dependency.
This was done on one of the product I have worked on which exposed public APIs to clients to code to but the implementation classes were obfuscated.
This solution could be painful to implement practically and will depend on degree of inter dependency between your two jars.
While downloading Google Guice I noticed two main "types" of artifacts available on their downloads page:
guice-3.0.zip; and
guice-3.0-src.zip
Upon downloading them both and inspecting their contents, they seem to be two totally different "perspectives" of the Guice 3.0 release.
The guice-3.0.zip just contains the Guice jar and its dependencies. The guice-3.0-src.zip, however, did not contain the actual Guice jar, but it did contain all sorts of other goodness: javadocs, examples, etc.
So it got me thinking: there must be different "configurations" of jars that get released inside Java projects. Crossing this idea with what little I know from build tools like Ivy (which has the concept of artifact configurations) and Maven (which has the concept of artifact scopes), I am wondering what the relation is between artifact configuration/scope and the end deliverable (the jar).
Let's say I was making a utility jar called my-utils.jar. In its Ivy descriptor, I could cite log4j as a compile-time dependency, and junit as a test dependency. I could then specify which of these two "configurations" to resolve against at buildtime.
What I want to know is: what is the "mapping" between these configurations and the content of the jars that are produced in the end result?
For instance, I might package all of my compile configuration dependencies wind up in the main my-utils.jar, but would there ever be a reason to package my test dependencies into a my-utils-test.jar? And what kind of dependencies would go in the my-utils-src.jar?
I know these are a lot of tiny questions, so I guess you can sum everything up as follows:
For a major project, what are the typical varieties of jars that get released (such as guice-3.0.zip vs guice-3.0-src.zip, etc.), what are the typical contents of each, and how do they map back to the concept of Ivy configurations or Maven scopes?
The one you need to run is guice-3.0.zip. It has the .class files in the correct package structure.
The other JAR, guice-3.0-src.zip, has the .java source files and other things that you might find useful. A smart IDE, like IntelliJ, can use the source JAR to allow you to step into the Guice code with a debugger and see what's going on.
You can also learn a lot by reading the Guice source code. It helps to see how developers who are smarter than you and me write code.
I'd say that the best example I've found is the Efficient Java Matrix Library at Google Code. That has an extensive JUnit test suite that's available along with the source, the docs, and everything else that you need. I think it's most impressive. I'd like to emulate it myself.