I am working on a jetty service, and when starting it, I get a lot of:
SomeClass scanned from multiple locations: jar: jar1!Someclass.class, jar2!Someclass.class
So a single class is provided by two jars, and which I get on runtime is undefined, which is not good. Looking at other issues I found that tattletale can help diagnosing the problem. The report, in the Multiple Jar files section lists the same classes as jetty upon startup and which jars they were in.
A subset of the conflicts are:
And looking at
mvn dependency:tree -D verbose
I get:
+- ca.uhn.hapi.fhir:hapi-fhir-jpaserver-base:jar:3.7.0:compile
| | ...
| +- org.jscience:jscience:jar:4.3.1:compile
| | \- org.javolution:javolution:jar:5.2.3:compile
And so it seems that my fhir-base-jpaserver-base dependency pulls jscience that pulls javolution. But jscience and javolution supply some of the same classes. No other dependency to javolution exists.
My question is then, how do I go about solving this?
I could do some stuff in pom.xml but I suppose jscience needs javolution, and might break?
Sounds like a bug in jscience with how they packaged their jar, might want to file an issue with them.
They should either ...
have a proper/focused jar and dependencies.
or a standalone uber jar with no dependencies.
Not mixing the two concepts.
Meanwhile, just use the <dependency>/<exclusions> to exclude specific transitive dependencies that are causing you duplicate classes.
Also, you might want to run any of the various duplicate class/resource checker maven plugins to find any other cases you might have present on your project.
Related
Due to the Log4Shell vulnerability I would like to search and find out if my Java project is implementing Log4j directly or by dependencies, and which version.
I have, for example, projects with these dependency management tools:
Maven project
Apache Ivy project
Old legacy project without any dependency management
How can I do this on these types of dependency management tools?
Details about the vulnerability (including mitigation steps):
CVE-2021-44228
Apache Log4j Security Vulnerabilities
You may run Maven dependency tree from the command line inside your project:
mvn dependency:tree
In the output do a search for log4j. If you find it, it might mean that your project is either directly including log4j, or another dependency is including log4j as a transitive dependency.
If you use Maven and Linux, you can run:
mvn dependency:tree | grep log4j
This will check your dependencies and show results only if you have Log4j as a dependency.
And if it is a transitive dependency, and you want to check the dependency it came from, you can use:
mvn dependency: tree | grep -B20 log4j
It will show 20 lines before Log4j on the screen. If you still can't see the main dependency where it comes from, you can increase from 20 to 50, and so on until you find it.
KKKK
So far I'm satisfied what Syft and Grype provide. These tools list all code dependencies of a given Docker image or a directory containing code - independent of the stack! Easy setup and quick execution.
It's Java-independent though and more generic than your specific question for a Maven-based solution. So it is up to you if it's of use or not.
I'm trying to upgrade to Hibernate 3.5.3-FINAL.
When running my unit tests, I now receive the following exception:
java.lang.NoSuchMethodError: javax.persistence.OneToMany.orphanRemoval()Z
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1837)
My classpath contains the following JAR's:
From the hibernate dist:
antlr-2.7.6.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
javassist-3.9.0.GA.jar
jta-1.1.jar
slf4j-api-1.5.8.jar
cglib-2.2.jar
hibernate-jpa-2.0-api-1.0.0.Final.jar
hibernate3.jar
Other jars:
blazeds-common-3.2.0.3978.jar
blazeds-core-3.2.0.3978.jar
blazeds-opt-3.2.0.3978.jar
blazeds-proxy-3.2.0.3978.jar
blazeds-remoting-3.2.0.3978.jar
commons-lang-2.3.jar
dbunit-2.4.7.jar
ejb3-persistence.jar // Note, I've tried excluding this, but I get different errors
guava-r05.jar
hsqldb-1.8.0.7.jar
junit-4.1.jar
lambdaj-2.0-with-dependencies.jar
log4j-1.2.14.jar
mockito-all-1.8.0.jar
persistence-api-1.0.jar
spring-security-core-2.0.0.jar
spring.jar
sqljdbc.jar
I've researched this, and I find answers that state my webserver must be JPA2 Compliant:
Unfortunately if your app server is
not JPA 2 compliant, you are likely to
be out of luck
This project is a library, not a webserver project. (Although it is eventually deployed to a webserver, I'm simply running unit tests here)
What am I missing?
<indulgent_rant>
As a sidenote, it's very frustrating that every time I upgrade Hibernate, I find myself spending hours researching conflicting jars for MethodNotFoundException or ClassNotFoundException's. There must be a simpler way?
I thought for sure that with the announcement they were merging the modules back to a single core project, that these conflicts would go away?
</indulgent_rant>
As pointed out by Timo, remove persistence-api-1.0.jar.
Just in case, here are the dependencies I'm using:
org.hibernate:hibernate-entitymanager:jar:3.5.3-Final:compile
+- org.hibernate:hibernate-core:jar:3.5.3-Final:compile
| +- antlr:antlr:jar:2.7.6:compile
| +- commons-collections:commons-collections:jar:3.2:compile
| +- dom4j:dom4j:jar:1.6.1:compile
| | \- xml-apis:xml-apis:jar:1.0.b2:compile
| \- javax.transaction:jta:jar:1.1:compile
+- org.hibernate:hibernate-annotations:jar:3.5.3-Final:compile
| \- org.hibernate:hibernate-commons-annotations:jar:3.2.0.Final:compile
+- cglib:cglib:jar:2.2:compile
| \- asm:asm:jar:3.1:compile
+- javassist:javassist:jar:3.9.0.GA:compile
\- org.hibernate.javax.persistence:hibernate-jpa-2.0-api:jar:1.0.0.Final:compile
I'm getting them from this single declaration in my pom.xml:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.5.3-Final</version>
</dependency>
This should somehow answer your indulgent rant (if I rephrase: use Maven - or know what you're doing).
Remove these files from project lib location
persistence-api-1.0.jar
ejb3-persistence.jar
add only
javax.persistence-2.0.0.jar
it contains all the required fields and atrributes.
try this it'll work for your problem.
Manish Jaiswal
Try replacing persistence-api-1.0.jar with a JPA 2.0 jar.
Discovered a fix for the issue at least with what I am working with: IBM WebSphere 7 and MyEclipse Blue (Spring), or Bling, ver. 10.6. I created an application that has dependencies on other projects, one of these using Hibernate 3.6.3, requiring JPA 2.0. IBM WS loads JPA 1.0 to support itself ahead of JPA 2.0 and resolves all references to JPA to ver. 1.0. In the case of IBM WS, this causes the error reported above. The only fix I have come across since now includes adding JPA 2.0 as a shared library, then setting the server to load that library ahead of its native classes, similar to the method discussed here:
http://www.mkyong.com/websphere/websphere-7-javaxpersistenceonetomany-orphanremoval-error/
But our server admins will not allow changes to the server-wide classloader policy. So I still needed to find a way to get my project to use JPA 2.0 and not 1.0. I tried a lot of things but finally went for a Hail Mary and it worked.
The fix is to add the JPA 2.0 .jar file to your .war and .ear projects and then edit the Class-Path line in the manifest file in both your .war and .ear projects to point to the .jar files. It seems they must be in both or the approach will not work, so the JPA 2.0 .jar has to be in both the .war and .ear.
In your app (.war project), add hibernate-jpa-2.0-api-1.0.0.Final.jar to the project root. MyEclipse Blue will show it as a file at that location and also listed under "Referenced Libraries" in the Package Explorer view. Then open the manifest file at /WebRoot/META-INF/MANIFEST.MF and make sure the Class-Path line reads:
Class-Path: /hibernate-jpa-2.0-api-1.0.0.Final.jar
In your .ear project, add hibernate-jpa-2.0-api-1.0.0.Final.jar to folder 'lib' at your project root. If there is no 'lib' folder there, create one. Then in /META-INF/MANIFEST.MF, make sure the Class-Path line reads:
Class-Path: /lib/hibernate-jpa-2.0-api-1.0.0.Final.jar
Make sure all files are saved and do a clean build. Then export the .ear and deploy it as usual by the Integrated Solutions Console. But there is another thing you must do before the change will work; it does require changing the class-load policy for the app, but not the server. You are much more likely to get your WAS admin to go for that than changing the classloader policy for the entire server. To make the necessary change, after installing the .ear file, follow the left-hand nav bar click trail "Applications\Application Types\Websphere enterprise applications" and click on the name of your application, then click "Class loading and update detection". Then select "Classes loaded with local class loader first (parent last)" under "Class loader order", then click Apply, then Save. Now back at click trail "Applications\Application Types\Websphere enterprise applications", either start or restart your application. Test out your app and hopefully you will be good to go.
Final note: Evey time you re-deploy your .ear file, you will need to set the classloader option I just discussed. The preference is not retained between deployments.
adding javax.persistence-2.0.0.jar should work fine...
Setting your server's application classloader policy to parent last will resolve this problem so long as you ensure the hibernate-jpa-2.0-api jar file is included in the EAR. If this is possible in your environment it's a much easier solution.
Tested on WebSphere 7.
I am working on my little OSS project in which I am using Maven as build tool. I split the project into smaller sub-projects to simplify development. Thus I have following structure:
project
+-- main-module
| |
| +- pom.xml
|
+-- submodule1
| |
| +- pom.xml
|
+ pom.xml
My thought was that main-module should provide interfaces which each submodule should be implementing in order to be plugged into whole application. Therefore submodule1/pom.xml contains compile time dependency reference to main-module. In its turn I also need to be able to test whole application and thus main-module/pom.xml contains test scope dependency reference to submodule1. As the result maven refuses to compile projects saying that they contain cyclic references.
My thought was that maven could first compile classes of main-module as it does not require any compile time dependency on any of submodules, then it using compiled classes of main-module could compile classes of submodule1 and after that compile test classes of main-module (to be able run tests). But seems that maven compiler does not take in account the scope of dependency and I somehow need to work around that.
The only solution I can see is to move away tests from main-module, which doesn't really make sense for me as only that module provides main logic.
My question - is there any other way around this issue except for moving away tests? Or maybe something is wrong with my understanding of how maven-reactor-plugin should work?
Instead of moving your tests away, you could move all of your API into it's own module. Then your main module would contain the application and you can freely distribute your application's API to allow others to access it. If they want to develop new functionality they do not necessarily need the sources of your app.
I consider this a much better style, because sub modules with specific functionality can now clearly separate between what is your applications API and what is the code your application needs to startup/shutdown, etc.
This is in my mind the intended way of how maven projects should look like. It also sticks with the single responsibility principle. The main modules responsibility is to startup/shutdown, etc your application. The API modules responsibility is to show how other developers can access your application. And the other submodule provide specific functionality for your application.
I know this is more of a comment, but might provide you with (not so pretty) solution:
You can seet your submodule1 as a dependency of maven-surefire-plugin (so that reactor is forced to build it) and then play with its settings... i.e. childDelegation or additionalClasspathElements
I'm trying to upgrade to Hibernate 3.5.3-FINAL.
When running my unit tests, I now receive the following exception:
java.lang.NoSuchMethodError: javax.persistence.OneToMany.orphanRemoval()Z
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1837)
My classpath contains the following JAR's:
From the hibernate dist:
antlr-2.7.6.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
javassist-3.9.0.GA.jar
jta-1.1.jar
slf4j-api-1.5.8.jar
cglib-2.2.jar
hibernate-jpa-2.0-api-1.0.0.Final.jar
hibernate3.jar
Other jars:
blazeds-common-3.2.0.3978.jar
blazeds-core-3.2.0.3978.jar
blazeds-opt-3.2.0.3978.jar
blazeds-proxy-3.2.0.3978.jar
blazeds-remoting-3.2.0.3978.jar
commons-lang-2.3.jar
dbunit-2.4.7.jar
ejb3-persistence.jar // Note, I've tried excluding this, but I get different errors
guava-r05.jar
hsqldb-1.8.0.7.jar
junit-4.1.jar
lambdaj-2.0-with-dependencies.jar
log4j-1.2.14.jar
mockito-all-1.8.0.jar
persistence-api-1.0.jar
spring-security-core-2.0.0.jar
spring.jar
sqljdbc.jar
I've researched this, and I find answers that state my webserver must be JPA2 Compliant:
Unfortunately if your app server is
not JPA 2 compliant, you are likely to
be out of luck
This project is a library, not a webserver project. (Although it is eventually deployed to a webserver, I'm simply running unit tests here)
What am I missing?
<indulgent_rant>
As a sidenote, it's very frustrating that every time I upgrade Hibernate, I find myself spending hours researching conflicting jars for MethodNotFoundException or ClassNotFoundException's. There must be a simpler way?
I thought for sure that with the announcement they were merging the modules back to a single core project, that these conflicts would go away?
</indulgent_rant>
As pointed out by Timo, remove persistence-api-1.0.jar.
Just in case, here are the dependencies I'm using:
org.hibernate:hibernate-entitymanager:jar:3.5.3-Final:compile
+- org.hibernate:hibernate-core:jar:3.5.3-Final:compile
| +- antlr:antlr:jar:2.7.6:compile
| +- commons-collections:commons-collections:jar:3.2:compile
| +- dom4j:dom4j:jar:1.6.1:compile
| | \- xml-apis:xml-apis:jar:1.0.b2:compile
| \- javax.transaction:jta:jar:1.1:compile
+- org.hibernate:hibernate-annotations:jar:3.5.3-Final:compile
| \- org.hibernate:hibernate-commons-annotations:jar:3.2.0.Final:compile
+- cglib:cglib:jar:2.2:compile
| \- asm:asm:jar:3.1:compile
+- javassist:javassist:jar:3.9.0.GA:compile
\- org.hibernate.javax.persistence:hibernate-jpa-2.0-api:jar:1.0.0.Final:compile
I'm getting them from this single declaration in my pom.xml:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.5.3-Final</version>
</dependency>
This should somehow answer your indulgent rant (if I rephrase: use Maven - or know what you're doing).
Remove these files from project lib location
persistence-api-1.0.jar
ejb3-persistence.jar
add only
javax.persistence-2.0.0.jar
it contains all the required fields and atrributes.
try this it'll work for your problem.
Manish Jaiswal
Try replacing persistence-api-1.0.jar with a JPA 2.0 jar.
Discovered a fix for the issue at least with what I am working with: IBM WebSphere 7 and MyEclipse Blue (Spring), or Bling, ver. 10.6. I created an application that has dependencies on other projects, one of these using Hibernate 3.6.3, requiring JPA 2.0. IBM WS loads JPA 1.0 to support itself ahead of JPA 2.0 and resolves all references to JPA to ver. 1.0. In the case of IBM WS, this causes the error reported above. The only fix I have come across since now includes adding JPA 2.0 as a shared library, then setting the server to load that library ahead of its native classes, similar to the method discussed here:
http://www.mkyong.com/websphere/websphere-7-javaxpersistenceonetomany-orphanremoval-error/
But our server admins will not allow changes to the server-wide classloader policy. So I still needed to find a way to get my project to use JPA 2.0 and not 1.0. I tried a lot of things but finally went for a Hail Mary and it worked.
The fix is to add the JPA 2.0 .jar file to your .war and .ear projects and then edit the Class-Path line in the manifest file in both your .war and .ear projects to point to the .jar files. It seems they must be in both or the approach will not work, so the JPA 2.0 .jar has to be in both the .war and .ear.
In your app (.war project), add hibernate-jpa-2.0-api-1.0.0.Final.jar to the project root. MyEclipse Blue will show it as a file at that location and also listed under "Referenced Libraries" in the Package Explorer view. Then open the manifest file at /WebRoot/META-INF/MANIFEST.MF and make sure the Class-Path line reads:
Class-Path: /hibernate-jpa-2.0-api-1.0.0.Final.jar
In your .ear project, add hibernate-jpa-2.0-api-1.0.0.Final.jar to folder 'lib' at your project root. If there is no 'lib' folder there, create one. Then in /META-INF/MANIFEST.MF, make sure the Class-Path line reads:
Class-Path: /lib/hibernate-jpa-2.0-api-1.0.0.Final.jar
Make sure all files are saved and do a clean build. Then export the .ear and deploy it as usual by the Integrated Solutions Console. But there is another thing you must do before the change will work; it does require changing the class-load policy for the app, but not the server. You are much more likely to get your WAS admin to go for that than changing the classloader policy for the entire server. To make the necessary change, after installing the .ear file, follow the left-hand nav bar click trail "Applications\Application Types\Websphere enterprise applications" and click on the name of your application, then click "Class loading and update detection". Then select "Classes loaded with local class loader first (parent last)" under "Class loader order", then click Apply, then Save. Now back at click trail "Applications\Application Types\Websphere enterprise applications", either start or restart your application. Test out your app and hopefully you will be good to go.
Final note: Evey time you re-deploy your .ear file, you will need to set the classloader option I just discussed. The preference is not retained between deployments.
adding javax.persistence-2.0.0.jar should work fine...
Setting your server's application classloader policy to parent last will resolve this problem so long as you ensure the hibernate-jpa-2.0-api jar file is included in the EAR. If this is possible in your environment it's a much easier solution.
Tested on WebSphere 7.
What's the best way to setup Maven for a project that has a SmartClient architecture? Consider the following packages:
myproject.core
myproject.server
myproject.client
Of course there are several sub-packages in each. Client and Server both use core. I see two main options:
Make an uber-POM in myproject to cover all three and have some sort of build parameter to identify what to build.
Make a POM in each package above (one for core, another for server and another for client).
Here are the outputs we need to build (at a minimum):
Standalone.jar: A test application that will launch the server and a client.
Server.war: A WAR file that can be deployed to Tomcat.
Client.jar: The SmartClient without any server code.
Is option #1 even possible? If so, is it good practice? From my initial research, option #2 sounds like best practice. However, jumping from POM to POM when all the code is intimately related sounds like extra work and extra clutter we may not need. Should I just stick with option #2?
Maven has a general rule that there should be only a single artifact per project. In other words, option #1 wouldn't allow you to produce a server.war, a client.jar, etc without fighting against maven. This would be a big mess and you wouldn't be able to take advantage of maven plugins. No, really, you don't want this. So just go for option #2, with a structure like (omitting the src directory):
.
|-- core
| `-- pom.xml
|-- server
| `-- pom.xml
|-- client
| `-- pom.xml
`-- pom.xml
Regarding your concern about jumping from POM to POM, well, just import all modules into your IDE and you won't really notice it. This just works pretty well for lots of people.
UPDATE (to cover questions from the OP in comments):
Fighting against Maven doesn't sound fun.
No, and you will loose :)
What is in the pom.xml at the root level?
This is a parent POM used for Project Aggregation. Quoting the Introduction to the POM document:
Project Aggregation is similar to
Project Inheritance. But instead of
specifying the parent POM from the
module, it specifies the modules from
the parent POM. By doing so, the
parent project now knows its modules,
and if a Maven command is invoked
against the parent project, that Maven
command will then be executed to the
parent's modules as well. To do
Project Aggregation, you must do the
following:
Change the parent POMs packaging to the value "pom" .
Specify in the parent POM the directories of its modules (children
POMs)
Project aggregation and project inheritance are often used together. Refer to the mentioned document for more details.
By "single artifact per project" do you mean that there should be a separate POM for Standalone.jar, Server.war, and Client.jar (three total POMs)?
Yes, this is what I mean, one project generates one artifact (there are some exceptions but this is true 99% of the time). This is a maven best practice that you should (must?) follow.
What if I also want a Server.jar, a simple server based with Grizzly included? Wouldn't server need two POM's?
I think that the maven way to handle this would be to use assemblies and there is no unique answer to your question (this might be one of the exception to the rule mentioned above). But this won't prevent you from starting.
Also, how would one kick off a build that would result in all three artifacts getting produced?
Launch your maven command from an aggregating project as we saw (aka "multi-modules build").