I have a Java 9 (or higher) project in which I want to include ORMLite with a H2 database. Therefore I need the two maven dependencies
<dependency>
<groupId>com.j256.ormlite</groupId>
<artifactId>ormlite-core</artifactId>
<version>5.1</version>
</dependency>
<dependency>
<groupId>com.j256.ormlite</groupId>
<artifactId>ormlite-jdbc</artifactId>
<version>5.1</version>
</dependency>
...
(+ the h2 dependency.)
Since I am using Java 9 I have to add them to my module-info.java:
module my.module {
exports my.package.to.export;
requires ormlite.core;
requires ormlite.jdbc;
...
But now I cannot compile the project anymore because both core and jdbc have the same package com.j256.ormlite.db.
[ERROR] module ormlite.core reads package com.j256.ormlite.db from both ormlite.core and ormlite.jdbc
I understand that this is as it should be, because split packages are not allowed. But how do I handle this, since this is not within my power? At least not in a clean way. I want to keep everything in maven and dont want to combine the packages as suggested in another post.
How can I solve this clean?
(I see that this is already an open issue in the orm-lite Github, but I do want to use it now)
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I do have some random issues within my application. And I suspect that the problem may arise from external dependencies. Let me elaborate.
My application is using an external jar with requests classes. Inside one of my projects, I had added the newest version of this library. But as you probably suspect, I have more dependencies than just one. And unfortunately, one of these dependencies has the same library which I added already, but with an older version. So at this moment, when I am firing mvn dependecy:tree, simplified results look like that:
+-my_project
+-request_lib.jar:1.5.0
+-required_lib.jar:1.0.0
+-random.jar:1.0.0
+-request_lib.jar:1.2.0
//more libs
//more libs
As you can see, what I need is the newest version of request_lib.jar:1.5.0, and at this moment no one can update required_lib.jar:1.0.0, and change the version or request inside of it.
How does Java handle this situation? Lets say inside of this project I am using request GetPlayerDataRequest, and in the newest version someone added a new field to this called String playerTitle. Will Java always use classes from the newest version? Or will it be mixed?
Because from what I see, sometimes users have fatal errors, where in logs we can find that method setPlayerData does not exist. I know that I can exclude the old jar in the pom. But I would like to know how it is handled by Java.
You want to use Maven's <dependencyManagement> feature. This is one of the most misunderstood and poorly documented areas of Maven and yet also one of its most powerful features.
In your pom.xml, if you have a <dependencyManagement><dependencies> section, then anything that is a child of it will apply all the way down the dependency tree, regardless of where else that dependency may be specified. (You can also include non-existing entries; if they designate a dependency that is not actually used anywhere by you or any of your transitive dependencies, then they are ignored.)
So, for example, if you want to ensure that the following dependency is used everywhere in your project no matter how it is "pulled in" or by whom:
<dependency>
<groupId>com.foo</groupId>
<artifactId>bar</artifactId>
<version>32</version>
</dependency>
…then if you add that entry to your pom.xml's <dependencyManagement><dependencies> section—even if your project itself doesn't use it, but your transitive dependencies do—so that it looks like this:
<dependencyManagement>
<dependencies>
<!-- other entries might go here -->
<!-- force version 32 of com.foo:bar no matter how it gets pulled into your project -->
<dependency>
<groupId>com.foo</groupId>
<artifactId>bar</artifactId>
<version>32</version>
</dependency>
<!-- other entries might go here -->
</dependencies>
</dependencyManagement>
…then that will do the trick.
A related thing that is not exactly documented anywhere is: dependency versions in "regular" <dependencies> entries (so <dependency> elements that do not appear as children of <dependencyManagement><dependencies> but only as children of <dependencies>) are suggestions. They are used only if an overriding <dependencyManagement> entry does not exist (which many times, of course, it does not).
Maven applies a dependency mediation mechanism, guaranteeing that only one of the two versions of the dependency gets bundled. So, in this case, Java doesn't have to handle anything really.
Relevant documentation: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
Java allows you to load different versions of the same class by using classloaders.
Using your example, you would load classes from request_lib.jar using one classloader, and required_lib.jar from another.
The topic is too extensive for a stackoverflow answer, there are many tutorials online.
It's kind of hard to explain my problem with words, so I took a pic, which shows exactly what my problem is:
As you can see, I have 3 relevant modules, a global, genui and web.
genui depends on global and web depends on genui.
Directly, web doesn't depend on global, but through genui it obviously does.
As you can see, if I take a look at the hibernate version of web->genui->global, it is 5.2.14, but if I look at it from genui->global, it's 5.3.0.
There is not, and there have never been any versions of either of these modules other than 1.0-SNAPSHOT.
I tried cleaning, deleting the files from .m2/repository, and even tried purging the local repo completely, nothing worked. I have no idea where maven gets the 5.2.14 number, I don't remember ever putting that in. The version is received from a property in parent module.
I figured out that the problem is caused by the pom.xml of web module, more specifically this part:
<dependencyManagement>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
...
</dependencyManagement>
You probably need to exclude that repeated dependency from one of the spring ones... verify all your dependencies and look which are the ones that include hibernate. Check that you also have different versions for servlet-api.
I've tried to "upgrade" a project using Hibernate to Java 9, but I am having problems getting the module to function properly.
The relevant part of my module-info.java looks like this:
module test {
...
requires java.base;
requires hibernate.core;
requires javax.transaction;
requires java.sql;
}
and the relevant dependencies in my POM are
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec, 2.0.0.Alpha1
org.hibernate:hibernate-core, 5.2.12.Final
javax.transaction:javax.transaction-api, 1.2
The problem is, if I run the program, I get a NoClassDefFoundError for javax.transaction.SystemException. I looked into this, and quite obviously, my module is missing a requires on javax.transaction.
So I add a module dependency on javax.transaction-api. I then go on and attempt to run the program again - now I'm missing java.sql.SQLException.
Here is what I am having a problem with: if I add a dependency on the module java.sql, which contains this class, I end up with a conflict:
module reads package javax.transaction.xa from both java.sql and javax.transaction.api
java.sql and javax.transaction.api contain different packages, and have one in common (javax.transaction.xa), but I require all of them.
How do I deal with this? Is there something simple I am missing?
Use version 1.3 instead of 1.2 of javax.transaction-api, in this version javax.transaction.xa has been removed.
Maven dependency:
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<version>1.3</version>
</dependency>
I am trying to build protege-server (https://github.com/protegeproject/org.protege.owl.server) from source. I downloaded the source code. Using "mvm -X package" yields the following error:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.
0:compile (default-compile) on project org.protege.owl.server: Compilation failu
re
[ERROR] /c:/Users/user/Programs/webprotege/org.protege.owl.server-master/src/mai
n/java/org/protege/owl/server/connect/local/OSGiLocalTransport.java:[11,32] type
org.osgi.framework.ServiceRegistration does not take parameters
Based on a previous question, an OSGI blogpost explains that the problem was fixed in a later (4.3.1) version of the library.
I tried to refer a newer version of this library in the POM.xml file:
<dependency>
<groupId>org.osgi</groupId>
<artifactId>core</artifactId>
<version>6.0.0</version>
<scope>system</scope>
<systemPath>/c:/Users/user/Downloads/osgi.core-6.0.0.jar</systemPath>
</dependency>
and even downloaded the newer version to specifically target it.
The error still occurs. Is there any way to solve it?
EDIT:
Attempting the solution suggested by #Balazs Zsoldos didn't help and I received the same error message. I noted an import of this package (org.osgi.framework) referring version 1:
<Bundle-Activator>org.protege.owl.server.Activator</Bundle-Activator>
<Bundle-SymbolicName>org.protege.owl.server</Bundle-SymbolicName>
<Bundle-Vendor>The Protege Development Team</Bundle-Vendor>
<Embed-Dependency>antlr, antlr-runtime, stringtemplate</Embed-Dependency>
<Export-Package>org.protege.owl.server*;version=2.0.6-SNAPSHOT</Export-Package>
<Import-Package>!org.antlr.stringtemplate,
!org.apache.commons.cli,
org.osgi.framework;version="1",
*</Import-Package>
An attempt to remove this line did not help either, as it appears in another dependency down stream. I could not find out how to override the downstream import-package instruction.
The effective pom.xml, as generated by eclipse, is attached as a link: https://docs.google.com/document/d/1eHFalUHVZ45ejLes_eqaXLw6ttjcTryphbGr_CKbhRk/edit?usp=sharing
The issue is that older versions of osgi.core are still on the classpath of the as they are imported with different group and artifact ids. Drag and drop the pom.xml to your eclipse and see the Dependency Hierarchy tab of the pom editor to get more information.
The following two are imported by dependencies:
org.osgi:org.osgi.core (by org.apache.felix.log)
org.apache.felix:org.osgi.core (by owlapi distribution)
To solve the problem, you should add the following dependency:
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
And as this does not override the org.apache.felix:org.osgi.core dependency, exclude that one:
<dependency>
<groupId>net.sourceforge.owlapi</groupId>
<artifactId>owlapi-distribution</artifactId>
<version>3.4.5</version>
<exclusions>
<exclusion>
<groupId>org.apache.felix</groupId>
<artifactId>org.osgi.core</artifactId>
</exclusion>
</exclusions>
</dependency>
(and remove the dependency with system scope as you do not need it and its artifactId is different from the standard anyway).
Edit
Just realized that the old osgi.core package is also inside org.apache.felix:org.apache.felix.framework that is pulled transitively by ProtegeLauncher via org.apache.felix:org.apache.felix.main:4.0.3. This means that you should either
Increment the version of org.apache.felix:org.apache.felix.main to the newest (or to one that at least implements osgi 4.3). In this case you do not need osgi.core at all
exclude org.apache.felix:org.apache.felix.main from edu.stanford.protege:ProtegeLauncher (and keep version 4.3.1 or higher of osgi.core)
I tried the second one and another issue comes that surfire plugin cannot be downloaded from maven central (or something similar, you will see).
Notes
The developer of this protege library was clearly not familiar how maven dependency management works and what should have been imported as a dependency. The project imports an OSGi runtime environment transitively that should never happen. For compilation only API should be imported and if the target runtime surely contains that API, it should be imported with provided scope. I would recommend to
not use this library or
clean it out (at least the maven dependency part) and send a pull request so the library can have an acceptable quality
I have a GWT project and I want to use some other in house GWT libraries as dependencies.
We do not want to include sources in our final build. Most open source GWT libraries include sources in the JAR, but we want to keep sources separate, use them to compile, then throw them away.
Is there a way to do this with Maven?
Set the scope to provided
<dependency>
<groupId>com.you.gwt</groupId>
<artifactId>gwt-ui</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
Brad's answer will fix the problem in a very narrow scenario. Setting the scope to provided totally avoids the jar from being pushed into War's lib. This is not what you would need in use case of the "lib" on to server side code. This usually happens
1) Constants.
2) DTO's/Beans.
3) RPC service interfaces
4) Request Factory proxy declarations
You have to have a mix of approaches.
1) Brad's approach when the "lib" in purely client and has no chance of being used in server clode.
2) Modularize code to have Constants/DTO's/Proxy/RF related interfaces and any such code in a project that generates two artifact jars.
A) One with classes only - to be used to push stuff in to web-inf/lib i.e scope compile/runtime.
B) Another with sources/classess - to be used with gwt compilation i.e scope provided.
Generating two jars might seem redundant. This is the only sane option i have tried. Keen on check whether there is any other option that will be suggested.
There are two kind of library (package in jar file) in GWT:
Server side library like "gwt-servlet.jar" does not contain source code in jar file and you can add maven dependency like this in your pom:
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-servlet</artifactId>
<version>${gwtVersion}</version>
<scope>runtime</scope>
</dependency>
Client side library like "gwt-user.jar" which contain source code in jar file, this kind of library does not require to package in your war file and you can add maven dependency like this in your pom:
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<version>${gwtVersion}</version>
<scope>provided</scope>
</dependency>
Have a nice time.