In gradle if I my project depends on another package, for example:
compile 'com.example:foo:0.82.2'
And in my javadoc, it references symbol in that package.
Then if I run javadoc task, it will say error: reference not found
I know I should add that package to class path, just like the following way to add android library
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
But how could I know the classpath for my dependency except add a hard coding path point to the gradle cache?
Related
I'm a bit confused about setting up the build script for a nested project
I've written a simple test repo here https://github.com/814k31/TestGradle
Essentially I am writing a wrapper for a module and need that wrapper to be included in a larger project, however I'm having trouble importing the module in the wrapper when it is used within a larger project
Dependency Chain
app imports OneDeep
OneDeep imports TwoDeep
Directory structure:
app
oneDeep
twoDeep
build.gradle
build.gradle
build.gradle
settings.gradle
The master branch in the test repo is written how I should expect it to work
There is also another branch where I've tweaked the settings.gradle to work, though it feels like I shouldn't do that...
Any suggestions on how to get oneDeep (the wrapper) to import twoDeep (the module)?
Thanks in advance.
You don't describe the error you get, but if we execute your example from the master branch in your repo, we get following error:
> Project with path ':twoDeep' could not be found in project ':oneDeep'.
This problem comes from the way you reference project 'twoDeep' from project 'oneDeep' script:
dependencies {
compile project(':twoDeep') // <== this won't work: there is no project with absolute path ":twoDeep"
// compile project('twoDeep') // <== use relative path to reference sub-project 'twoDeep' from project 'oneDeep'
// compile project(':oneDeep:twoDeep') // <= using absolute path will work as well
}
So you must either use relative path ( => 'twoDeep' ) or absolute path ( => ':oneDeep:twoDeep') when referencing subproject 'twoDeep' from project 'oneDeep'.
From Project DSL documentation:
Project project(String path) :
Locates a project by path. If the path is relative, it is interpreted relative to this project.
See also Project and task paths (but it's not clearly stated there what is the expected syntax for "relative" paths)
In my projects, I need to import third party jar file and Facebook SDK.
compile files('libs/SkinSDK.jar')
compile 'com.facebook.android:facebook-android-sdk:4.14.0'
Both include same BundleJSONConverter class. So, I cannot do generate signed APK. It always shows duplicate entry com/facebook/internal/BundleJSONConverter.
So, I want to exclude in Facebook or SkinSDK.jar. I tried like
compile ('com.facebook.android:facebook-android-sdk:4.14.0') {
exclude group: 'com.facebook.internal', module: 'BundleJSONConverter'
}
It's not working and showing same error.
The exclude method of the configuration closure for a dependency excludes transitive dependencies. So, if your module dependency depends on other modules, you can exclude them from your build. You can check out the transitive dependencies of the 'com.facebook.android:facebook-android-sdk:4.14.0' module on its Maven repository info page.
If the BundleJSONConverter class exists in a transitive dependency, you can exclude the specific module in the same way you are trying now. Just specify the group, the module and the version, like you do for dependencies.
If you just want to exclude one class for a dependency jar, take a look at the jar jar links tool and its Gradle plugin. It allows you to alter included jars, e.g. to change packages or remove classes.
The following (shortened) example shows the usage of the plugin and some methods to alter the dependency jar:
compile jarjar.repackage {
from 'org.apache.hive:hive-exec:0.13.0.2.1.5.0-695'
archiveBypass "commons*.jar"
archiveExclude "slf4j*.jar"
classDelete "org.apache.thrift.**"
classRename 'org.json.**', 'org.anarres.hive.json.#1'
}
Bumped into similar situation. This is what I did, not elegant as I hoped, but it works:
Rename the jar file (SkinSDK.jar in your case): .zip instead of .jar
Go "inside" the zip file (I'm using DoubleCommander, there are many other utilities for that), or extract it to a temporary folder.
Delete the duplicate class that causes the problem. Go "outside" the zip file.
Rename (or re-pack) the file from .zip to .jar . Compile.
Hope it works...
I had a similar problem with duplicated classes after importing a jar. In my case, the conflict was between a class in that jar and a class in my own project.
Below I share the solution you can use to discard classes that you have available in your own source tree, assuming the one in the jar is the right one to use:
android {
sourceSets {
main {
java {
filter.excludes = [
"com/package/Duplicated.java",
]
}
}
}
}
When adding dependencies to my project I am never sure what prefix I should give them, e.g. "classpath" or "compile".
For example, should my dependencies below be compile time or classpath?
Also, should this be in my applications build.gradle or in the module specific build.gradle?
Current build.gradle (at application level):
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile 'org.hibernate:hibernate-core:5.0.5.Final'
compile 'mysql:mysql-connector-java:5.1.38'
}
If buildscript itself needs something to run, use classpath.
If your project needs something to run, use compile.
The buildscript{} block is for the build.gradle itself.
For multi-project building, the top-level build file is for the root project, the specific build file is for sub-project (module).
Top-level build file where you can add configuration options common to all sub-projects/modules.
Do not place your application dependencies in top-level build file, they belong in the individual module build.gradle files
I'm going to guess that you're referencing compile and classpath within the dependencies {} block. If that is so, those are dependency Configurations.
A configuration is simply a named set of dependencies.
The compile configuration is created by the Java plugin. The classpath configuration is commonly seen in the buildScript {} block where one needs to declare dependencies for the build.gradle, itself (for plugins, perhaps).
If I understand correctly, you're confusing Project.dependencies script block with the Project.buildscript.dependencies script block (just like I did when I reached this question).
I'll try to answer this with what I found.
I think you should be already familiar with the Project.dependencies script block. In this block, we declare dependencies that are required by our source code. There are several ways to declare a dependency that we need for the project. See Gradle Tutorial: Dependency Types. I'll only mention the part that is the most relevant to this problem:
compile 'org.hibernate:hibernate-core:5.0.5.Final' is a module dependency declaration. The compile configuration (which is now deprecated by the implementation configuration.) is merely a keyword for Implementation only dependencies. It is not a keyword describing which type of dependency it is (by type here I'm following the three types defined in the tutorial, i.e. module, file, and project.)
In Gradle Tutorial: Organizing Build Logic it says:
If your build script needs to use external libraries, you can add them
to the script’s classpath in the build script itself. You do this
using the buildscript() method, passing in a closure which declares
the build script classpath.
This is the same way you declare, for example, the Java compilation
classpath. You can use any of the dependency types described in
Dependency Types, except project dependencies.
Having declared the build script classpath, you can use the classes in
your build script as you would any other classes on the classpath.
I hope things are getting clear to you now.
With classpath "com.android.tools.build:gradle:${Versions.android_gradle_plugin}" we're setting classpath method with com.android.tools.build:gradle:${Versions.android_gradle_plugin} which is a module dependency that is used by the build script itself rather than the source in your project.
On the other hand, with compile 'org.hibernate:hibernate-core:5.0.5.Final' we're declaring a module dependency required for your project with the compile configuration.
tl;dr: The classpath, compile, and implementation are all keywords that can be used against dependencies under different circumstances. The former is used when you want to pass in a dependency to the build script, and the latter is one of the configuration you may want to declare.
Android:
classpath in project build.gradle —— the implementation after classpath is only used by gradle it self, used in build script. So if i add the implementation (such as retrofit) in the project build.gradle classpath 'retrofit...', i can't get retrofit in my code!! Because —— my code can't see it, only the buildscript can see it.
implementation in app build.gradle —— add the implementation your code can use!!
A project runs on Google App Engine. The project has dependency that uses a class that can't be invoked on App Engine due to security constraints (it's not on the whitelist). My (very hacky) solution was to just copy a modified version of that class into my project (matching the original Class's name and package) that doesn't need the restricted class. This works on both dev and live, I assume because my source appears in the classpath before my external dependencies.
To make it a bit cleaner, I decided to put my modified version of that class into it's own project that can be packaged up in a jar and published for anyone else to use should they face this problem.
Here's my build.gradle:
// my jar that has 'fixed' version of Class.
compile files('path/to/my-hack-0.0.1.jar')
// dependency that includes class that won't run on appengine
compile 'org.elasticsearch:elasticsearch:1.4.4'
On my local dev server, this works fine, the code finds my hacked version of the class first at runtime. On live, for some unknown reason, the version in the elasticsearch dependency is loaded first.
I know having two versions of the same class in the classpath isn't ideal but I was hoping I could reliably force my version to be at the start of the classpath. Any ideas? Alternatively, is there a better way to solve this problem?
Not really sure if this is what people visiting this question were looking for, but this was what my problem and a solution that I reached at.
Jar A: contains class XYZ
Jar B: also contains class XYZ
My Project needs Jar B on the classpath before Jar A to be able to get compiled.
Problem is Gradle sorts the dependencies based on alphabetical order post resolving them which meant Jar B will be coming after Jar A in the generated classpath leading to error while compiling.
Solution:
Declare a custom configuration and patch the compileClasspath. This is how the relevant portion of build.gradle might look like.
configurations {
priority
sourceSets.main.compileClasspath = configurations.priority + sourceSets.main.compileClasspath
}
dependencies {
priority 'org.blah:JarB:2.3'
compile 'org.blah:JarA:2.4'
...
}
It's the app engine classloader I should have been investigating, not gradle...
App Engine allows you to customise the class loader JAR ordering with a little bit of xml in your appengine-web.xml. In my case:
<class-loader-config>
<priority-specifier filename="my-hack-0.0.1.jar"/>
</class-loader-config>
This places my-hack-0.0.1.jar as the first JAR file to be searched for classes, barring those in the directory war/WEB-INF/classes/.
...Thanks to a nudge in the right direction from #Danilo Tommasina :)
UPDATE 2020:
I just hit the same problem again and came across my own question... This time, live appengine was loading a different version of org.json than was being loaded in dev. Very frustrating and no amount of fiddling the build script would fix it. For future searchers, if you're getting this:
java.lang.NoSuchMethodError: org.json.JSONObject.keySet()Ljava/util/Set;
It's because it's loading an old org.json dependency from god-knows-where. I fixed it by adding this to my appengine-web.xml:
<class-loader-config>
<priority-specifier filename="json-20180130.jar"/>
</class-loader-config>
You'll also need a matching dependency in build.gradle if you don't already have one:
compile 'org.json:json:20180130'
According to gradle dependencies documentation, the order of dependencies defines the order in the classpath. So, we can simply put the libraries in the correct order in "dependencies".
But beware! here are two rules with higher priorities:
For a dynamic version, a 'higher' static version is preferred over a 'lower' version.
Modules declared by a module descriptor file (Ivy or POM file) are preferred over modules that have an artifact file only.
I'm trying to use Jackson for converting string to JSON object in java. I have both jar file and maven project of the library, with which I tried one by one but both giving error while calling writeValue function. Error says -
The type com.fasterxml.jackson.core.JsonGenerator cannot be resolved. It is indirectly referenced from required .class files
I have correctly added the library to build path.
After looking at eclipse-error-indirectly-referenced-from-required-class-files ,I realized that the problem is because of missing com.fasterxml.jackson.core.JsonGenerator class file.So Which jar file I missed to add to build path?. Tried by adding the maven project on build path too- same error.
To find which jar contains the required file, you can always use http://search.maven.org and search for the class prefixing it with fc:, like this:
http://search.maven.org/#search%7Cga%7C1%7Cfc%3Acom.fasterxml.jackson.core.JsonGenerator
Looks like you're missing jackson-core jar on your classpath.
Make sure that you have in your path jackson-databind and jackson-core
build path is used during compile. You need to set up the Deployment Assembly for run time classpath (under project settings, look for Deployment Assembly )