Accessing classes from separate modules - java

I have a project with the following basic setup:
Root Project
- employee-service
- nomination-service
I need to access classes from employee-service in nomination-service, but am not able to get the dependencies down for some reason.
Here's the root project's settings.gradle:
rootProject.name = 'pair-project'
include 'applications/employee-service'
include 'applications/nomination-service'
Inside of the nomination-service build.gradle I have tried all the following (each dependency denotes one thing I've tried, they're not all present at the same time):
dependencies {
project(':employee-service')
project(':../../applications/employee-service')
compile(':../employee-service')
compile(':employee-service')
compile('./applications/employee-service')
compile('/employee-service')
}
All of these doesn't work for some reason or the other.The project ones generally tell me it can't find a project at that location. When I use compile it will usually build fine, but then can't find the import for the class I'm trying to use.
Any help would be greatly appreciated here, everything I've read online has generally suggested taking this approach, so I'm not sure what I'm doing wrong.

The applications/nominations-service/build.gradle should be:
apply plugin: 'java'
dependencies {
compile project(':applications/employee-service')
}
Generally, from here dependencies require a configuration and one or more items with a dependency notation. In this case, compile is the configuration and we are using a project dependency. All of your examples only had one, but not both.

Related

problem in Gradle adding dependencies through commandline

I'm trying to add a bunch of dependencies through the commandline. This is because my workplace has a bunch of plugins that we want to preload into every project. and we dont want devs to mess about their gradle files.
So I looked at this older issue - https://stackoverflow.com/a/40613776/112050 and tried to do the same in this repo https://github.com/arakoodev/bug-gradle
however, I'm constantly getting a "cannot find symbol" error:
error screenshot - https://github.com/arakoodev/bug-gradle/blob/main/error%20msg.png:
I'm only using an empty springboot application, but moved the dependency declaration from build.gradle into myinit-script.gradle.
The code can't find the classes from the springboot dependency.
It seems you're mixing a few patterns...
If you want to include org.springframework.boot:spring-boot-starter-web:3.0.0 as a dependency, and not merely add it as a classpath, using classpath wont accomplish this.
I did verify that if you change your myinit-script.gradle to the following, it will work:
allprojects {
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web:3.0.0'
}
}
What's going on here?
Changed initscript to allprojects to apply it to all projects.
Perhaps you could still use initscript, but I think the -I is accomplishing this. Anyway, followed the pattern from here:
https://docs.gradle.org/current/userguide/init_scripts.html
You cant include dependencies unless you have already applied the java plugin, so that was added.
classpath doesn't include a dependency, implementation does, so changed that.
Now, when I run this, gradle -I .\myinit-script.gradle clean build, I get a clean compile.

Including javax persistence in a Cordova/Android project

I am trying to incorporate ObjectBox in my hybrid Cordova/Android project. By dint of some trial and error I have managed to figure out two of the steps involved.
The app level build.gradle file has to be modified to include the ObjectBox Gradle plugin classpath "io.objectbox:objectbox-gradle-plugin:2.5.0"
Define a build-extras.gradle file to "apply" the ObjectBox plugin ext.postBuildExtras = {apply plugin: 'io.objectbox'}
The next step according to the ObjectBox docs is to define at least one Entity class
However, the issue here is that I need to import the javax.persistence.* classes into the project. It is not clear to me how I do this. I have run into suggestions along the lines of including
compile group: 'javax.persistence', name: 'javax.persistence-api', version: '2.2'
in the dependencies section of the app level build.gradle file. However, this causes gradle to complain that it does not know the compile() function. I'd be much obliged to anyone who might be able to tell me how this should be done.
For the benefit of anyone running into this thread - you can download the JAR file for javax.persistence here. Place this line in the folder src/android/libsof your custom plugin and then modify plugin.xmlwith the line
<lib-file src='src/android/libs/name-of-javax-persistence.jar'/>

Exclude one class file in gradle Android Studio

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",
]
}
}
}
}

Gradle: What is the difference between classpath and compile dependencies?

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!!

Can I force the order of dependencies in my classpath with Gradle?

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.

Categories

Resources