I'm using OkHttp3 to build up a simple connection API for a pure Java app, and I've run into a build problem that seems triggered by the fact that Square uses the same package name for multiple dependency artefacts.
I've seen some previous Q&A that discusses Maven dependencies and messaging from Eclipse, but all of those indicate that a Maven or Gradle build still works even if Eclipse annotates imports with module errors. In this case the Gradle build fails as soon as I simply add a dependency and make no other changes.
The app is a pure Java 11 module build. I'm using a very recent Eclipse with Gradle nature as an IDE, but I don't think this is strictly relevant. I'm using OkHttp3 to turn private endpoints into API, and one of those endpoints requires a CookieJar. Hoping to just use the default implementation, I add 'com.squareup.okhttp3:okhttp-urlconnection:3.14.9' as a dependency in a project that has already pulled in 'com.squareup.okhttp3:okhttp:3.14.9' as a transitive dependency. Both of these technically offer classes using the same package name: "okhttp3".
e.g., all I do is uncomment the dependency line seen in this snippet and save the build.gradle:
dependencies {
implementation ('com.squareup.retrofit2:retrofit:2.9.0')
implementation ('com.squareup.retrofit2:converter-gson:2.9.0')
implementation ('com.squareup.okhttp3:logging-interceptor:3.14.9')
// implementation ('com.squareup.okhttp3:okhttp-urlconnection:3.14.9')
As soon as the project refreshes I get annotations in Eclipse for all "okhttp3" imports:
The package okhttp3 is accessible from more than one module: okhttp3, okhttp3.logging, okhttp3.urlconnection
A clean build results in:
$ ./gradlew clean build
[...]
> Task :compileJava FAILED
error: the unnamed module reads package okhttp3 from both okhttp3.urlconnection and okhttp3
error: module retrofit2.converter.gson reads package okhttp3 from both okhttp3 and okhttp3.urlconnection
error: module retrofit2 reads package okhttp3 from both okhttp3 and okhttp3.urlconnection
error: module org.apache.commons.io reads package okhttp3 from both okhttp3 and okhttp3.urlconnection
error: module httpcore5 reads package okhttp3 from both okhttp3 and okhttp3.urlconnection
[...]
I don't think it matters, but I'm using Gradle wrapper 5.6.4.
All OkHttp3 libraries, as far as I know, have set module info enough to satisfy Java 9+. The module stuff in Eclipse seems satisfied by that. It looks like neither Eclipse or Gradle like the fact that two different dependencies advertise their Java package as "okhttp3". It seems to me that any Gradle or Maven based project using Java 9 or higher will fail with split-package dependencies.
Based on some advice I read elsewhere, I've tried excluding 'com.squareup.okhttp3:okhttp' from all the dependencies that include it transitively and then pull it in separately, but this did not help (not that I thought it would, but I'm trying any hail-mary at this point).
Workarounds include hacks like simply dropping the two Kotlin classes I want into the project directly and renaming the package that way. This is an egregious hack, and is probably contrary to the library license. I can also implement the cookie stuff I need directly, but I'm lazy (though, apparently, I want to spend my energy solving this problem instead of implementing a cookie class using the interface I already have).
I feel like this is a bug on the part of Square and how they package these libraries/modules. Since their focus is so much on Android maybe I'm the only one who has wanted okhttp-urlconnection on Java 9 or higher? So, this Question is more about seeing if I should raise this as a defect, and also maybe I've overlooked something obvious.
It's OkHttp’s fault and we can fix it for you. Please open a tracking bug with a link to this issue.
We'll move those two classes to a new package. For backwards compatible we'll also need to leave delegating implementations behind. Hopefully the tools permit this!
It's too bad that JPMS has this constraint. We already fixed some of our other open source projects but didn't fix this one.
Related
I'm trying to parse WSDL files using the EasyWSDL library on my (atlassian) maven plugin project. I keep getting this error when I try to parse the file and it fails when the project tries to reach the TransformerFactoryImpl class from said "xalan" package. The package is located inside the JDK, so it's supposed to be available to runtime, yet for some reason it can't reach it.
I've tried importing the package through
<import-package>com.sun.org.apache.xalan.internal.*,</import-package>
section of the pom.xml, but that gives me the following error:
Unresolved requirements: [[my.plugin.package [304](R 304.0)] osgi.wiring.package; (osgi.wiring.package=com.sun.org.apache.xalan.internal.xsltc.trax)]
Which makes it seem like the other packages of xalan are found, except for the xsltc.trax one.
I've tried creating a bundle extension for OSGi that exports this one package and exposes it to the classpath but due to lack of experience and pretty poor documentation on that matter I can't get that working either. Adding Xalan as a dependency and using <scope>provided</scope> does nothing as well.
I need to find a way to put this specific package on the classpath when the program is running. When I run unit-tests on my implementations they work just fine, so it seems to purely be a runtime classpath problem.
Is there anyone with experience on this matter? I've little experience with OSGi, and my experience with maven isn't huge either. So I'm hoping it's something I did wrong myself instead of this being an impossible problem to solve.
I am finishing a project written by someone else. The project is written in Kotlin, but I could not get their build system (wemi) to recognize JavaFX, and so I ported it to Gradle instead, since the JavaFX developers have approved instructions for using Gradle (see those here). Gradle downloads these dependencies normally, and IntelliJ lists them in my external libraries, but I cannot import them into my code.
I am using JVM 11 and Kotlin 1.3.31 with JavaFX 11.0.2. I have followed these instructions to the letter, and it still does not work.
The error is upon importing classes from JavaFX. When I attempt to import a class from any JavaFX module, IntelliJ fails to resolve the 'javafx' package. No other errors appear. By all accounts, if the dependency shows in my dependency list, I should be able to import it, but this is not the case. What can I do to fix this?
I have an android project with following structure:
-- Calendar
------app (app module)
----------build.gradle (module level)
------build.gradle (project level)
------Commons(A common project which i reuse across various projects)
----------common (common module in Commons project)
-------------build.gradle (for only common module level)
----------build.gradle(for Commons Project)
Now the problem is that if I compile Commons, deploy it to bintray and then use it as implementation 'com.amitkma.Commons:common:1.0.0' in app module, all the dependencies (which are implemented in common build.gradle) is available to use in app module also. But if I use it like following
implementation project(:Commons:common), only dependencies provided using api is available to use.
I want to know what is the difference between api and implementation with respect to module is compiled or used directly like above?
There are two things at play here:
The separation of api and implementation when declaring dependencies. In short dependencies in the implementation scope are only visible at runtime because they are an implementation detail. Such libraries will use the runtime scope in their published Maven metadata. More information in the documentation
Before Gradle 5.0, the Maven metadata scopes compile and runtime were mixed by Gradle and thus all runtime dependencies did appear on the compile classpath. Gradle 5 changes this
So when you publish your component, the limitation of Gradle 4.x means that your common dependencies are available to app. Note that moving to Gradle 5 will cause a breakage there, as documented.
And when you use the project directly, the separation is properly enforced.
The fix is to simply promote dependencies that are part of the common api to the api configuration in common and for the runtime ones, declare them in app as after all they are directly required by it.
I am trying to modularize a JHipster 5 (Spring Boot 2) application and I ran into a split package problem.
In module-info.java I have the following conflicting automatic modules:
requires problem.spring.web;
requires problem;
requires jackson.datatype.problem;
When I build the project with Maven, I get several errors due to conflicting package name org.zalando.problem like this:
error: the unnamed module reads package org.zalando.problem from both problem and jackson.datatype.problem
error: module problem.spring.web reads package org.zalando.problem from both jackson.datatype.problem and problem
I would like to know how can I solve this issue. Would I have to wait for the third party library to be modularized too? What would be a nice way to solve this conflict?
This article explains a bit on how to solve Split Packages problems. I applied it to solve the split package between jsr305 and java.xml.ws.annotation by using --patch-module argument when building, as explained here. However the project did not compile when I tried the same for these packages.
The source for this project is available on GitHub
If you want to use JARs that split a package as modules, --patch-module is the only way, but it's an arduous one. Beyond patching, you also need to craft the rest of the module graph. Say you're patching module megacorp with the content of start.up, then:
you have to make megacorp read all of start.up's dependencies with --add-reads
you have to make all modules that use start.up read megacorp with --add-reads
you have to ensure that start.up is not on the module path
This can be quite complicated, particularly if you're fighting Maven along the way. Are you sure, there is no way to simply merge the two artifacts?
If not, I'd say this project might not be ready for modularization.
I'm using STS, and with a Web (WTP); Maven; Groovy stack.
By default, it appears that the Groovy classpath entries weren't marked to be exported, and I was issued with the following warning:
Classpath entry GROOVY_DSL_SUPPORT will not be exported or published.
Runtime ClassNotFoundExceptions may result. Classpath entry
GROOVY_SUPPORT will not be exported or published. Runtime
ClassNotFoundExceptions may result.
So, I added the libraries from Project Properties -> Deployment Assembly -> Add...
However, now I get the following error:
Invalid classpath publish/export dependency
/Users/martypitt/springsource/2.8.1.RELEASE/sts-2.8.1.RELEASE/plugins/org.codehaus.groovy_1.8.4.xx-20111212-0900-e37-RELEASE/lib/antlr-2.7.7.jar.
The project contains another dependency with the same archive name.
I worked around by excluding antlr manually from my pom.xml. However, this seems counter-intuitive, and leaves me concerned about issues later when I deploy to a server outside of STS.
Is there a more appropriate way to resolve this issue?
You do not need to export the DSL support container. It provides editing support for some built in Groovy AST transforms. There is nothing in the classpath container required for compilation or runtime.
Looks like your project is groovy project. Go to eclipse and install groovy addon - from software site - http://dist.springsource.org/snapshot/GRECLIPSE/e4.6/
After this restart eclipse and you should have these in path/eclipse to work with.
Detailed instructions # https://github.com/groovy/groovy-eclipse/wiki
Make sure you have the proxy configured properly - if any.