IntelliJ won't import modules from gradle composite builds - gradle

UPDATE: Not only is IntelliJ having trouble, but the reason seems to be because my setup fails to build in Gradle. Still unsure why.
I'm trying to set intellij up to recognize composite gradle builds. I have Project A which depends on Project B, like this:
/p/projecta
/p/projectb
I've tried MANY things, but IntelliJ can't find the declarations of anything in project-b that I try to access from project-a. For example, in ProjectA.java below, IntelliJ marks the import for Project B as Cannot resolve symbol ProjectB
// projecta/src/main/java/projecta/ProjectA.java
import projectb.ProjectB; // 'Cannot resolve symbol ProjectB'
// projectb/src/main/java/projectb/ProjectB.java
public class ProjectB {
}
// projecta/settings.gradle
rootProject.name = 'projecta'
includeBuild '../projectb'
// projectb/settings.gradle
rootProject.name = 'projectb'
Despite the above configuration, it does not work. IntelliJ continues to mark all symbols from Project B as not resolvable.
Other things I've tried
removing the includeBuild from settings.gradle, and right clicking in the gradle window on Project A, going to 'Composite Build Configuration' and adding Project B from there. Same issue.
Adding this code to build.gradle in Project A
tasks.register('run') {
dependsOn gradle.includedBuild('projectb').task(':run')
}
Putting Project B inside of Project A on the disk: /p/projecta/projectb and then changing includeBuild in projecta/settings.gradle to includeBuild 'projectb'
Many variations of #2 to try to get IntelliJ to recognize the gradle dependency.

I recently ran into this problem and figured it out so I wanted to respond here so others can benefit from my foraging through the jungle of parameters and trial and error.
I have the exact same project set up as described in the question. Using Gradle 5.0, Intellij was able to correctly import and link my sources and I was able to build correctly on the command line. When I bumped the Gradle version to 5.6 and higher, Intellij was no longer able to link the sources correctly. Re-importing my project would actually work but the dependency that represents the included build would be highlighted red and the console would say that it couldn't resolve it. This happened for every Gradle version after 5.6.
It seems the root cause was Intellij was using Java 11 for Gradle while I had sourceCompatibility set to 10. It looks like this breaks things in more recent versions of Gradle (understandably).
I was also able to fix this by adding the following to my project's build.gradle
java {
disableAutoTargetJvm()
}
However, I just updated my JDK for Gradle in Intellij to be Java 10 and everything worked....

My problem was just like for #Troy, had to make all projects work under the same JDK by adding this to the build.gradle.kts:
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(8))
}
}

Related

Copy Gradle dependencies from another subproject without deprecation warning

In a Gradle project I have multiple sub-projects. I need to copy the dependencies from the configuration of one sub-project to that of another. I can achieve this using the following, adapted from this answer here:
task copyDependencies(type: Copy) {
from project(":sub").configurations.compile
into "${buildDir}/libraries"
}
Unfortunately, with Gradle 5.1, this generates the following deprecation warning (truncated for brevity):
The configuration :sub:compile was resolved without accessing the project in a safe manner. ... This behaviour has been deprecated and is scheduled to be removed in Gradle 6.0.
What's the best way to do this now for Gradle 5.1 and later?
The warning appeared as reaching across project boundaries can cause issues when the build runs in parallel.
The proper way of doing this is to let Gradle know that the project declaring the copyDependencies task will need the project :sub's dependencies.
You can achieve this by doing the following:
configurations {
dependenciesToCopy
}
dependencies {
dependenciesToCopy project(':sub')
}
task copyDependencies(type: Copy) {
from configurations.dependenciesToCopy
into "${buildDir}/libraries"
}
This will cause Gradle to properly create an execution dependency between your project and the resolution of the dependencies of the sub project.
Relevant discussion on the Gradle forums.

How to get Intellij to recognize properties in application.yml

I am trying to get Intellij to recognize my properties using gradle. I have followed the steps here. So this means I have a #ConfigurationProperties annotated class with some properties.
I added the spring dependency to process them:
dependencies {
optional "org.springframework.boot:spring-boot-configuration-processor"
}
compileJava.dependsOn(processResources)
I added the plugin (I've tried not using the plugin and just making it a compile dependency, no change)
buildscript {
repositories {
maven { url 'http://repo.spring.io/plugins-release' }
}
dependencies { classpath 'io.spring.gradle:propdeps-plugin:0.0.9.RELEASE' }
}
apply plugin: 'propdeps'
apply plugin: 'propdeps-maven'
apply plugin: 'propdeps-idea'
When I run the build, I see a build/classes/java/main/META-INF/spring-configuration-metadata.json file is created based off of my properties.
When I try to use the property in either application.yml or application.properties, Intellij says it cannot resolve it.
The docs does say it should be called additional-spring-configuration-metadata.json and may expect it to be called that to process it, but I do not see a way to make the build name it that way nor configure Intellij to expect otherwise.
Has anyone got this working with gradle? Or is this a bug.
Edit I created a repo with a pair of projects to demonstrate this. One for gradle and one for maven. I created the projects from start.spring.io and basically just added the properties configuration. I also used a straight compile dependency in both cases instead of optional / compileOnly.
I had not confirmed this before, but the code assist does work for maven, but not gradle. Both create a spring-configuration-metadata.json in the META-INF in their respective build folders. I am not exactly sure who is not picking it up.
Misc relevant versions
Intellij: 2017.3.4
Springboot: 1.5.9
Gradle: 4.4.1
Java: 8.161
Turn the annotation processing on
Do not delegate IDE build/run actions to Gradle
Rebuild your project in IDE: Build -> Rebuild Project
As far as I can tell, IntelliJ (at the time of this writing, 2018.1.2) wants the spring-configuration-metadata.json file to either be in a main source root (src/main/resources/META-INF/ or src/main/java/META-INF/) or in its default output directory for it to pick it up for autocompletion of properties in your source tree. To expand on phospodka's comment, you can add something like this to your build.gradle to satisfy IntelliJ.
task copyConfigurationMetadata(type: Copy) {
from(compileJava) {
include 'META-INF/spring-configuration-metadata.json'
}
into "out/production/classes"
}
compileJava {
dependsOn processResources
finalizedBy copyConfigurationMetadata
}
This answer is a combination of the (at this time) other two answers with a minor twist. In my case this is what "fixed" the issue: (in 2019.03.01-Ultimate)
Turn on the default annotation processing (File>Settings>Build, Execution, Deployment>Annotation Processors>Enable Annotation processing
Select Obtain processors from project classpath
Select Store generated sources relative to module output directory
keep other defaults
click OK
Add the code in #thyme's answer to your build.gradle
EXCEPT instead of into "out/production/classes"
use: into "build/generated/sources/annotationProcessor"
Now you should be able to run gradle clean/build and Intellij should be able to find your "additional metadata" definitions.
Notice that even though the build.gradle code doesn't explicitly mention 'additional-spring-configuration-metadata.json', it is exactly that "additional metadata" that ends up in the annotationProcessor folder as "spring-configuration-metatdata.json" where Intellij finds it.
EDIT: Also note, you need to clean / rebuild after adding any new "additional metadata" items before Intellij will see the new entries (in the freshly regenerated file).

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.

Why am I getting "unsupported version of Gradle" with the tutorials app in Android Studio?

When I try to import the tutorials app to Android Studio, I get this message:
The project is using an unsupported version of Gradle.
Please point to a supported Gradle version in the project's Gradle settings or in the project's Gradle wrapper (if applicable.)
I’m new to Android Studio, and meter too. What’s the problem with Gradle?
I’m using Android Studio 1.0.1.
Android Studio 1.0.1 supports gradle 2.2.1+ and Android Gradle Plugin 1.0.0+
How to change the gradle version.
In your project you should have a folder gradle/wrapper.
Inside you will find the gradle-wrapper.properties file.
Change this line inside
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
How to change gradle plugin version:
In your project you should have a build.gradle file in the root folder.
Inside:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter() // or mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
}
}
Pay attention. Each module has a own build.gradle file. Inside you can override the default configuration.
More info here.
I too have faced this issue, To resolve this issue there are two things you need to try.
You need to remember exactly what version of gradle distribution url you were adding to your existing project.
if you didn't remember, you have to goto https://services.gradle.org/distributions/ and do trial and error. Add all versions to gradle distribution url like shown below.
distributionUrl=https://services.gradle.org/distributions/gradle-2.2.1-all.zip
only change the last version number 2.2.1-all to 3.5-all and so on.
In gradle-wrapper.properties, modify the gradle version. Change to a newer one. The reason is generally: gradle and JDK, different versions are not compatible. Change the JDK to the old version.

Resources