I'm using guava and jetty in my java project, while i found an odd problem.
In guava,it depend javax.annotation has so many class while in jetty the javax.annotation has less than in guava. What's the difference between them.
What's more,the javax.annotation in jetty is signed,while in guava is not signed. When the jvm load the class from the package javax.annotation in guava.jar and jetty.jar,it throw the SecurityException cause one package is signed and the others is not signed.
So,what's the real difference of the javax.annotation package between the guava.jar and the jetty.jar.
The package in guava:
no sign and has lot of class
The package in jetty:
signed and has little class
There are different libraries that provide types in the javax.annotations package. The one Guava is using is a JAR from the (now abandoned) JSR-305 proposal. In Maven this is com.google.code.findbugs:jsr305:1.3.9.
The other JAR appears to be org.eclipse.jetty.orbit:javax.annotation:1.1.0.v201108011116. It's not clear where that JAR comes from, and it appears to have been uploaded in 2011 and then never updated since.
The conflict between these two JARs appears to be a well-known one.
It appears that the "dependency" on this JAR was added in Guava release 13, but the release notes for that version say:
Made findbugs a provided dependency to avert dep conflicts when using findbugs 2.0. The side-effect of this change is that projects which relied upon Guava to grant access to the JSR-305 annotations "for free" will break unless they provide their own direct dependency on that jar (or an equivalent). Projects should always have been directly depending on JSR-305 (per maven best-practice), but this change makes that should into a must.
Because of this, from what I understand, Guava doesn't actually have any dependency on the com.google.code.findbugs:jsr305:1.3.9 JAR. So you should be free to exclude that dependency and provide your own javax.annotations JAR that you use instead. Alternatively, if you prefer the com.google.code.findbugs:jsr305 JAR, you should exclude the org.eclipse.jetty.orbit:javax.annotation dependency from your build. You can refer to the Maven documentation for how to exclude the unwanted dependency.
Related
The app consists of modules and each module is particular maven project with one parent. These modules are used as jars in main app.
Each module uses third party SDK via maven.
These SDKs have many dependencies and these dependencies can be with the same group and artifact but with different versions. It is hard to manage them and we have problems with 'NoSuchMethodError's. As for me the simplest way to fix problem is to get sources of problematic dependencies and source of SDK, change the package (add some prefix) and imports and put it inside sdk jar.
But this approach requires: one more git repository for forked SDK's jars and private maven repository to publish them and a lot of time.
Is there maven plugin that can help with this problem, for example plugin that can build jar (our module jar) with all dependencies included inside it but can change package of all dependencies?
You can try to use the Maven shade plugin which allows you to relocate classes
https://maven.apache.org/plugins/maven-shade-plugin/examples/class-relocation.html
but I have never tried this myself.
In most cases it is better to try to align the dependencies so that you use the same versions in most places and also to reduce dependencies to a minimum.
Congratulations, you are confronted with a classpath problem called "jar hell". The only safely working solution i know is the use of different classloaders for each version of the same class (if it's not backward compatible).
A class is identified by its qualified name (package and class name) and by the classloader it has been loaded. If the application uses the default system classloader and there is the same class in different versions in the classpath only one version will be loaded by the classloader. In the oracle JDK/JRE it is the one which occurred first in the classpath. If you are lucky you can bring the classpath (order and excluding dependencies) in a special order in which your application will run, but i wouldn't recommend it since it relies heavy on the JDK/JRE implementation.
OSGI is a technology which might be helpful for this since it provides a module based framework for using different classloaders.
When developing Java libraries we're currently using the Apache Maven Shade Plugin to hide internal dependencies on other libraries (jars) by renaming their package names.
Is it possible to hide these internal library-dependencies by using the Java 9 module system and not exporting the name of the internally used libraries?
I.e:
Both module A and B include, but does not export, class org.codehaus.jackson.map.ObjectMapper (included using e.g. Maven Shade plugin) with different versions for the class
Module A uses module B
Will each module still use its implementation org.codehaus.jackson.map.ObjectMapper?
I believe it should by so, but I have found no documentation explicitely confirming this, nor any texts / examples recommending this approach for this quite usual versioning issue.
This issue is described as http://openjdk.java.net/projects/jigsaw/spec/issues/#MultiModuleExecutableJARs and there's no support for it yet. In case all dependencies are modules, it would make sense to use jlink to solve this. But as long as there is at least one non-module, there's no solution available yet. This is something that needs to be solved within the JDK/JRE.
It is still a valid case, so I would suggest to ask this question the at jigsaw-dev mailinglist and refer to #MultiModuleExecutableJARs
The module declaration defines, among other things, a module's dependencies. If I use Maven as a build tool, this is redundant because the pom.xml already contains these (and more) information. Based on that, couldn't Maven generate the module-info.java for me?
One might expect that most of the dependencies are indeed required modules as well. However, requirements can also point to modules of the JDK/JRE, which are not specified in the pom.xml. So yes, if you only look at the dependencies, probably most of them could be transformed to a required module reference.
But a module-descriptor contains much more information, which are all based on decisions to be made by the developer.
I've written an article about it which describes in detail why it is not possible to fully generate this file.
As far as I know, bnd-maven-plugin can generate module-info.class based on the configured dependencies. If you are working with maven-bundle-plugin, you need to specify the version of bndlib manually, for the latest version of maven-bundle-plugin(5.1.3) is still using the 5.x version of bndlib, and bndlib requires 6.x to support jpms.
Document: https://bnd.bndtools.org/releases/6.1.0/chapters/330-jpms.html
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.
The current version of the Google Guava libraries (10.0.1) are nicely deployed on Maven Central here http://repo1.maven.org/maven2/com/google/guava/guava/10.0.1/
My GWT compiler keeps complaining e.g. "GWT Module com.google.common.Collect.gwt.xml not found in project sources or resources." which is no surprise, given it can't find the sources anywhere. There are -sources jar in Maven Central, too, but they contain no sources. Only some shell scripts and GWT module definitions.
Why are the source jars without sources and is there another weird way to get Guava 10.0.1 play with GWT and Maven?
When you say the source jars are empty, are you talking about the guava artifact, or the guava-gwt artifact? They don't seem empty to me. The guava-gwt.jar even contains the sources (GWT needs the sources to be present in the jar you depend on, not the -sources.jar).
According to the Guava wiki, you simply need a dependency to the guava-gwt artifact (instead of guava).
Maybe a GWT expert can chime in, I haven't used it since last year.