local dependencies from root multi project build in gradle - gradle

I have been working on an android app built using the ResearchStack skin framework pulled in through the gradle dependency:
implementation 'org.researchstack:skin:1.1.2'.
I am interested in possibly doing some customization to the underlying ResearchStack skin framework:
https://github.com/ResearchStack/ResearchStack.
Can anyone walk me through updating my project to be dependent on local ResearchStack build artifacts so that I can make changes to the framework and see those changes in my local application.
I tried just pointing to the build output:
implementation fileTree(dir: '../../ResearchStack/skin/build/outputs/aar', include: ['*.aar'])
but that leaves me with unresolved transitive dependencies and some build issues that I couldn't quite get worked out.
Thanks!!

John,
Put 'ResearchStack skin framework code' in another directory 'myResearchStack' at root level parallel to 'app' directory.
And update the root level 'build.gradle' as
apply plugin: 'com.android.application'
android { ... }
dependencies {
// Dependency on a local library module
implementation project(":myResearchStack")
}

Related

javax.json module not found building JavaFX application with Gradle

I am trying to run a modular JavaFX application, with few other modular and non modular dependencies, using Gradle, but I am stuck with dependencies resolution.
The project is in Eclipse, using OpenJDK 14-. I have been able ot run, build and package the same application as non-modular using the org.beryx.runtime pluging https://badass-runtime-plugin.beryx.org/releases/latest/ , but I would like to go a step forward and make it modular, so now I am using the Badass JLink Plugin https://badass-jlink-plugin.beryx.org
To go step by step, I downloaded and tested this example: https://github.com/beryx-gist/badass-jlink-example-log4j2-javafx which is similar to my project and I succesfully ran it. Anyway, Eclipse marks lots of errors due to unresolved imports, which I would like to understand how to remove, but indeed the project compiles and runs.
The next step have been to modify this working example by adding the dependencies I need for my real project, which are mainly javax.json and jOpenDocument. The latter cannot be found as a module.
Here is the modified module-info.java
module hellofx {
requires javafx.controls;
requires org.apache.logging.log4j;
requires javax.json;
requires org.glassfish;
exports org.openjfx;
}
and the build.gradle
plugins {
id 'application'
id 'org.javamodularity.moduleplugin' version '1.8.9'
id 'org.openjfx.javafxplugin' version '0.0.10'
id "org.beryx.jlink" version "2.24.1"
}
repositories {
mavenCentral()
}
sourceCompatibility = "11"
targetCompatibility = "11"
dependencies {
implementation 'org.apache.logging.log4j:log4j-core:2.11.1'
implementation 'javax.json:javax.json-api:1.1.4'
implementation 'org.glassfish:javax.json:1.1.4'
implementation 'org.jopendocument:jOpenDocument:1.3'
}
javafx {
version = 16
modules = ['javafx.controls']
}
application {
mainClass = "org.openjfx.HelloFX"
mainModule = "hellofx"
}
The compileJava task fails with the following errors:
C:\Users\xxx\badass-jlink-example-log4j2-javafx-master\src\main\java\module-info.java:5: error: module not found: javax.json
requires javax.json;
^
C:\Users\xxx\badass-jlink-example-log4j2-javafx-master\src\main\java\module-info.java:6: error: module not found: org.glassfish
requires org.glassfish;
does anybody have a hint to start solving this issue?
The problem seemed to be related to the module-info.class file included in the older javax.json imported as org.glassfish:javax.json:1.1.4. The library has been relocated to jakarta and the new one org.glassfish:jakarta.json:2.0.1 does not show the original problem anymore. So the solution is to switch to the newer library.

JavaFXPorts project as a library for other JavaFXPorts projects

I currently struggle with probably very simple problem: How can I use one JavaFXPorts specific project as a dependency within another project of the same kind?
With pure separated projects, I have no idea how to combine them (have to admit, I'm not as up-to-date with Gradle, as I probably need to...).
I thought about using the apply plugin: 'maven' to install and grab the library to and from the local maven cache. But then there would be no separation of the platform specific code (everything - main, android, ios, desktop - would be merged together into one single JAR file.
Maybe if I reduce the problem to the pure part of the main source tree, I could create a standalone JavaFX-only project, this should be easy...
Or I could access the other project via a relative path. But for whatever reason I kind of dislike that idea.
What is the best practice for JavaFXPorts? I simply don't what to copy some stuff over and over into new projects (obviously).
Thanks in advance,
Daniel
This is a very simple example of how you can set a Gradle multi project, containing two subprojects:
Common: a regular JavaFX (gradle) project, with common code that can be reused later on in other projects.
GluonApplication: a simple Gluon Mobile project, that makes use of the common one.
I've used NetBeans to create the Gradle Root project and add the subproject, but it can be done from other IDEs or command line as well.
1. Gradle Root Project
Create a Gradle Root Project. Set the project name (GradleProject in this case), the location, and a Maven Group ID (com.gluonhq in this case), and a Maven Version (default 1.0-SNAPSHOT).
2. Gradle Common Subproject
Create a new Gradle Subproject. Choose a name (Common), and make sure that the location of this project is the GradleProject folder. Select a main class (com.gluonhq.common.Common).
Add some code:
package com.gluonhq.common;
public class Common {
public static double sum(double a, double b) {
return a + b;
}
}
3. Gluon Mobile Subproject
Add a Gluon Mobile Subproject with the Gluon plugin for your IDE. For instance select Single View project. Choose a name (GluonApplication), and again make sure that the location of this project is the GradleProject folder. Select the package name (com.gluonhq.application) and the main class (GluonApplication).
You can run this project as is, from command line in the project root: gradle :GluonApplication:run, or from your IDE (tasks -> Run).
4. Include a Common dependency
Edit the build.gradle file from the Gluon Mobile subproject, and add the Common dependency.
Since both subprojects belong to the same root project you can simple do:
dependencies {
compile 'com.gluonhq:charm:4.3.7'
compile project(":Common")
}
Save and reload the project. Now on your code you can call Common.sum:
button.setOnAction(e -> label.setText("3 + 4: " + Common.sum(3, 4)));
Run again and see that it works. You can deploy to mobile as well.
5. Installing the Common module
If you plan to reuse the Common project in this or other Gluon Mobile projects, you can install it in your .m2 repository.
On command line, from the project's root, run:
gradle :Common:install
and you'll see that the project is installed under <user>/.m2/repository/com/gluonhq/common/1.0-SNAPSHOT, including the common-1.0-SNAPSHOT.jar file.
6. Reusing the Common jar
Finally, you can include the common jar in any of your projects.
For that, edit the build.gradle file from the Gluon Mobile subproject, include the local repository, and add the Common dependency.
repositories {
mavenLocal()
jcenter()
maven {
url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
}
}
dependencies {
compile 'com.gluonhq:charm:4.3.7'
compile 'com.gluonhq:common:1.0-SNAPSHOT'
}
Save and reload the project. And your common code will be available.
Of course, this works locally on your machine, but you can publish the artifact to a private or public repo as well, and then you should just include the proper repo in the above list.

Gradle artifactory plugin saying "Cannot cast object 'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention'..."

Here's the configuration to get the artifactory plugin:
buildscript {
repositories {
mavenCentral()
maven { url 'http://jcenter.bintray.com' }
}
dependencies {
classpath group:'org.jfrog.buildinfo', name: 'build-info-extractor-gradle', version: '3.0.1'
}
}
apply plugin:'com.jfrog.artifactory'
apply plugin:'ivy-publish'
...some publish spec stuff...
I run gradle (2.3) and I get:
> Failed to apply plugin [id 'com.jfrog.artifactory']
> Cannot cast object 'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention#6b6c7be4' with class 'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention' to class 'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention'
Certainly looks like a classpath issue, but I literally have this project and a sibling project using this same set of gradle/artifactory configurations and one works and the other does not. Both are part of the same top level project. Same JDK (1.8.0_20). Same Gradle. Same everything.
I'm baffled...
The problem was that when I added the various bits to the sibling project that meant I had two projects defining the buildscript {} section.
buildscript {
...
dependencies {
classpath group:'org.jfrog.buildinfo', name: 'build-info-extractor-gradle', version: '3.0.1'
}
}
Apparently that caused two different versions of the dependency to exist in the classpath, hence the error.
The solution was to move the buildscript bit into the master project so those dependencies are only defined once:
buildscript {
repositories {
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath group:'org.jfrog.buildinfo', name: 'build-info-extractor-gradle', version: '3.0.1'
}
}
Here's another potential cause. All of this looks to be a problem with rival classloaders defining the class. The full qualified classes include the loader. so, load A foo.bar is not loader B foo.bar and crossing that divide is a complex dance requiring interfaces and careful definition.
So, when using the Jenkins artifactory plugin to build your gradle project with the gradle artifactory plugin, you must add the usesPlugin or jenkins plugin will generate an init script which adds the gradle plugin on to a class loader.
def server = Artifactory.server "artifactory"
def rtGradle = Artifactory.newGradleBuild()
rtGradle.usesPlugin = true // Artifactory plugin already defined in build script
...
My problem was, desktop build OK, jenkins build shows this post's problem
I was getting a similar exception when building with Jenkins. For me the conflict was with Jenkin's version and the version in the Build script:
To address this the Artifactory section of the build has a flag you can check specifying that you want to use the version from the gradle file:
This fixed my issue. Hope it helps.
I had a similar problem. Gradle seems to try to reach across and do some checking or evaluation across siblings. I have a top level settings.gradle with 10 or so subprojects.
The fix for me was to put the buildscript block and dependencies at the top level build.gradle and put it in each of the individual subprojects build.gradle files where needed.
My guess as to the reason this works is that the plugin gets loaded in the parent which will be a parent classloader, then each child project inherits that classloader such that the declaration in the lower child script uses that classloaders class and CCE does not occur. The problem is they are the same class, but not assignable since the different classloaders per subproject if nothing is declared at the top. This was Gradle 2.4, and using IntelliJ 14.
In case it helps someone, I got the same error, but for a different reason.
I had the following in my build.gradle:
dependencies {
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:+"
}
At some point the artifactory plugin updated itself from version 3.x to version 4.x while building, because no specific version was specified for the dependency. After it updated I got the error (Could not find any convention object of type ArtifactoryPluginConvention).
I guess the problem was that the rest of the configuration in my build script doesn't work with the new plugin version. Setting the dependency to use version 3.x fixed the problem for me:
dependencies {
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:3.+"
}
While the currently accepted answer correctly identifies the cause of this issue, the proposed solution doesn't work when you still need to be able to build individual subprojects (because then of course they no longer have access to the buildscript defined repositories and dependencies). The solution that worked for me was to have identical buildscript blocks in each of my subprojects, that seemed to be the key. Any variations would cause the original error.
I got the same exception thrown by bamboo:
'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention#18eb2827' with class 'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention' to class 'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention'
Since the bamboo Bamboo Artifactory Plugin by default looks for the gradle.propeties file in each sub-project module, it has to be provided there.
There is no need for publishing logic in the build.gradle file since the Bamboo Artifactory plugin will read the gradle.properties file for each module respectively, containing:
group=com.example
artifactId=your-project
version=1.0.0
The reason that I got the ArtifactoryPluginConvention exception thrown was that my configured build plan on Bamboo was misconfigured.
With misconfigured, the build ordered of the tasks was not correct. Have a look at your bamboo building tasks/preferably clone a Bamboo plan that is already working.

Android Gradle dependencies - only Maven?

I'm trying to get to know the Android Studio / Gradle build system, having come from Eclipse and Ant. In particular, I don't understand how the dependencies block in my build.gradle file works.
My current project has the following structure:
In my project I am using both the android support library (v4), and the jxl spreadsheet library. My build.gradle (the one inside the sub-module, not the root level one) currently looks like this:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.6.+'
}
}
apply plugin: 'android'
repositories {
mavenCentral()
}
android {
compileSdkVersion 18
buildToolsVersion "18.1.1"
defaultConfig {
minSdkVersion 14
targetSdkVersion 19
}
buildTypes {
release {
runProguard true
proguardFile getDefaultProguardFile('proguard-android-optimize.txt')
}
}
productFlavors {
defaultFlavor {
proguardFile 'proguard-rules.txt'
}
}
}
dependencies {
compile 'net.sourceforge.jexcelapi:jxl:2.6.+'
compile 'com.android.support:support-v4:13.0.+'
//compile fileTree(dir: 'libs', include: '*.jar')
}
On the second last line, you can see I've tried using the local copies of android-support-v4.jar and jxl.jar. I've also tried using the lines
compile files('libs/android-support-v4.jar')
compile files('libs/jxl.jar')
However, whenever I try to use the local .jar files, my build fails, saying that the Android support and jxl libraries cannot be found. I've seen lots of posts saying that you can simply use local .jars like this, however I cannot get this to work. If possible, I would like to be able to use my locally stored .jar files so I can work offline, when Maven isn't available.
Can anyone tell me why using the local .jar files doesn't work?
EDIT: I've also tried restarting the Android Studio IDE, and cleaning and re-building my project after adding the local jar dependency lines.
It's not finding the libs directory because it needs to be located at your module root instead of inside src/main. The paths in build.gradle are relative to the location of the build.gradle file, which lives in your module root.
For the Android support library, I'd recommend using the Maven dependency (e.g. compile 'com.android.support:support-v4:13.0.+') instead of including the jar file. With the support library, the Android Gradle plugin actually looks for it in your SDK instead of going out to the network for it; you have to have the support repository installed via the SDK manager. This is actually a little confusing and trips up a lot of users since it's not well-documented. But if you access it this way instead of just including the JAR, then the build system can be smarter about not trying to include duplicate copies of it and causing errors if you include other library projects that depend on it.

Resolve Gradle Transitive Dependency Conflict with file system libs (ie. not maven, ivy)

We have a java project with dependencies that looks something like this.
A -> B -> httpcore-4.0.1
\
C -> httpcore-4.1.3
So there is transitive dependency conflict in A. The gradle docs say that the resolution policy is to select the newest (http://gradle.org/docs/current/userguide/dependency_management.html). However, we get compile errors due to function signature differences so the latest doesn't seem to be selected. I've seen various exclude methods but not sure how they apply when we are using a file system based dependency lib (not maven or ivy). Eclipse seems to resolve the problem okay and compile but gradle barfs. I've tried various forms of:
configurations {
all*.exclude group:'org.apache', name: 'httpcore', version:'4.0.1'
all*.exclude group:'org.apache.httpcomponents', name: 'httpcore', version:'4.0.1'
}
What am I missing here?
I'm using Gradle 1.0-milestone-8a
It's just not done. See http://forums.gradle.org/gradle/topics/resolve_gradle_transitive_dependency_conflict_with_file_system_libs_ie_not_maven_ivy
You have to use a local or remote repos.

Resources