Gradle compile dependencies not included in Jar - plugins

I have a jar, build-plugins.jar with a gradle plugin that is build with this in build.gradle:
apply plugin 'java'
dependencies {
compile gradleApi()
compile localGroovy()
compile('eviware:maven-soapui-plugin:4.5.1')
compile('org.antlr:stringtemplate:4.0.2')
compile('commons-io:commons-io:2.4')
compile('joda-time:joda-time:2.1')
}
This builds build-plugins.jar. And the project that consumes the plugin references the plugin jar by file
apply plugin 'thepluginwahoo'
buildscript {
dependencies {
classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:2.2.1'
classpath files('/path/to/build-plugins.jar')
}
}
The problem is when I run any task of the second project, I get "class proxy could not be created for class xyz" with the root cause being that the four dependencies (joda-time, commons-io, stringtemplate, maven-soapui-plugin) are not there. If I add the dependencies to the plugin-consuming project then it works just fine:
apply plugin 'thepluginwahoo'
buildscript {
dependencies {
classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:2.2.1'
classpath files('/path/to/build-plugins.jar')
classpath 'eviware:maven-soapui-plugin:4.5.1'
classpath 'org.antlr:stringtemplate:4.0.2'
classpath 'joda-time:joda-time:2.1'
classpath 'commons-io:commons-io:2.4'
}
}
My question is why don't the classes of the "compile" dependencies in the plugin project appear in the plugin-consuming project when the jar is included in the classpath of the buildscript of the plugin-consuming project.

Jars typically do not contain their dependencies. Instead, they are published to a repository along with some kind of metadata descriptor (pom.xml or ivy.xml) which describes the artifact's dependencies. When you refer to the jar file directly as a dependency, Gradle has no way of knowing what its transitive dependencies are. You have a couple of ways to deal with this:
Publish your plugin jar to a repository, along with the necessary metadata (which Gradle will do for you) and bring it in as an external module dependency
Explicitly declare the plugin's transitive dependencies using a client module dependency.
Use something like the Gradle fatjar or shadow plugins to bundle dependencies within your jar.

Related

Eclipse is not using gradle dependencies jar during run or debug

I am trying to do basic hibernate task using Gradle project.
Dependency jars are download by Gradle and placed in Project and External Dependencies library.
I don't get any compile time error. But when I try to run or debug the main class in Eclipse, I am getting class not found NoClassDefFoundError.
Exception in thread "main" java.lang.NoClassDefFoundError: org/hibernate/cfg/Configuration
When I checked the build path, I could see the dependency library is configured with required jars but still eclipse is not using it.
But when I add the jar manually in the build path, I am not getting this exception.
Build.gradle File
plugins {
// Apply the java-library plugin to add support for Java Library
id 'java-library'
}
apply plugin: "eclipse"
dependencies {
// This dependency is exported to consumers, that is to say found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:23.0'
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
// https://mvnrepository.com/artifact/org.hibernate/hibernate-core
compile group: 'org.hibernate', name: 'hibernate-core', version: '5.3.6.Final'
// https://mvnrepository.com/artifact/com.oracle.jdbc/ojdbc6
runtime group: 'com.oracle.jdbc', name: 'ojdbc6', version: '11.1.0.6.0'
// https://mvnrepository.com/artifact/com.oracle/ojdbc6
runtime group: 'com.oracle', name: 'ojdbc6', version: '11.2.0.4.0-atlassian-hosted'
}
// In this section you declare where to find the dependencies of your project
repositories {
// Use jcenter for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
mavenCentral()
}
Thanks in advance!!!
I think you should update the classpath with the latest changes in the build file. Eclipse does not do that automatically in all versions.
Go to package explorer, right-click the build.gradle file, then from the context menu select gradle->refresh gradle project.
You can also enable auto sync from the preferences menus, go to gradle, and check the "Automatic Project Synchronization" checkbox.
Remove/comment this dependency and try.
runtime group: 'com.oracle.jdbc', name: 'ojdbc6', version: '11.1.0.6.0'
My Build.gradle:
plugins {
// Apply the java-library plugin to add support for Java Library
id 'java-library'
}
dependencies {
// This dependency is exported to consumers, that is to say found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:23.0'
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
// https://mvnrepository.com/artifact/org.hibernate/hibernate-core
compile group: 'org.hibernate', name: 'hibernate-core', version: '5.3.6.Final'
// https://mvnrepository.com/artifact/com.oracle.jdbc/ojdbc6
// runtime group: 'com.oracle.jdbc', name: 'ojdbc6', version: '11.1.0.6.0'
// https://mvnrepository.com/artifact/com.oracle/ojdbc6
runtime group: 'com.oracle', name: 'ojdbc6', version: '11.2.0.4.0-atlassian-hosted'
}
// In this section you declare where to find the dependencies of your project
repositories {
// Use jcenter for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
With the eclipse plugin, there are different build tasks being added:
./gradlew cleanEclipse eclipse

importing dependencies into eclipse using gradle

I've got what appears to be an adequate gradle file but eclipse refuses to recognise the dependancy I'm trying to import (despite refreshing the gradle project after implementing the dependancy)
My gradle file lacks a buildscript{} block but I'm not familar enough with gradle to implement it. My build file was autogenerated by eclipse so I don't see why it'd be an issue.
I'm trying to import "com.intrinio:sdk:0.0.1"
build.gradle:
// Apply the java-library plugin to add support for Java Library
apply plugin: 'java-library'
// In this section you declare where to find the dependencies of your project
repositories {
// Use jcenter for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
dependencies {
// This dependency is exported to consumers, that is to say found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
compile "com.intrinio:sdk:0.0.1"
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:21.0'
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
}
I think this is the lib you want to use.
As it's not deployed in a public repository, you have to manually install it. Checkout the project from github and do as below :
Installation
To install the Intrinio Java SDK to your local Maven repository, simply execute:
mvn install
Then, in your gradle file, add mavenLocal() in the repository section and it should just work fine.

How can the source attachment, Javadoc location and native library location be specified for a Gradle project's local dependency, in Eclipse?

The Eclipse IDE for Java Developers (Neon) as well as the default Gradle plugin (Buildship?) are used.
A Gradle Git project was created using the Eclipse IDE. A local JAR is stored within the workspace/ProjectName/lib/nameOfJAR.jar directory. It was added to this project as a dependency, using the following build.gradle configuration.
...
repositories {
// Use 'jcenter' for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
flatDir {
dirs 'lib/'
}
}
dependencies {
// The production code uses the SLF4J logging API at compile time
compile 'org.slf4j:slf4j-api:1.7.21'
compile name: 'nameOfJAR'
// Declare the dependency for your favourite test framework you want to use in your tests.
// TestNG is also supported by the Gradle Test task. Just change the
// testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add
// 'test.useTestNG()' to your build script.
testCompile 'junit:junit:4.12'
}
Then Project Explorer > Project A > Gradle > Refresh Gradle Project was used to update the Eclipse GUI, to display this new local dependency, via Project Explorer > Project A > Build Path > Configure Build Path > Libraries > Project and External Dependencies > [Name of JAR].
However, when expanding this section, source attachment, Javadoc location and native library location are shown as non modifiable. Can these be set from the Gradle configuration files?
How can these be set through Eclipse and Gradle?
You can place nameOfJar-sources.jar file next to the actual library in the same directory. Gradle will use that as a source attachment. I suppose the same would work for javadocs, that is nameOfJar-javadoc.jar would be picked up. I don't know how native libs are handled.
This is probably described somewhere in the Gradle docs, but I don't know where to find them.

Gradle: produced WAR file has two versions of JAR from child project

I have a root project that builds WAR, and two child projects that build JARs. The root project references the child project in this way:
apply plugin: 'war'
jar.enabled = false
war {
dependencies {
runtime project(':application1')
runtime project(':application2')
}
}
application2 depends on application1:
dependencies {
compile '...:application1:1.+'
}
The WAR file includes two versions of application1.jar: one from repository, another just built.
EDIT: Application2 has to depend on application1 as a JAR because that simplifies debugging in Eclipse with embedded Jetty: Eclipse automatically adds application1.jar to classpath of Jetty server launch configuration.
You have specified dependency on application1 project differently for the root project and for the application2.
For your application2 it was made as dependency on a library within some repository, but your root project depends on it as on a subproject. Gradle can't determine, that some library in the repo is the same, as subproject's artifact.
If you don't want to get 2 versions of the same lib, you have to make it dependent from the same library: either as
compile '...:application1:1.+'
or as
runtime project(':application1')
Anyway, it seems to be prefferable, to make it depending on the same subproject in both cases, rather then on some project and on the library in repo.

How to import multiproject build in buildSrc dir in Gradle?

Hi in my buildSrc dir I have two separate projects, lets name them one and two.
I add build.gradle and settings.gradle file in buildSrc dir and in them I wrote:
settings.gradle
include \
"one",
"two"
But when I tried to use some of the plugins, which are provided from this projects, Gradle says that this imports can not be found. I searched for simmilar problems and found that I have to write in build.gradle file in buildSrc:
dependencies {
runtime subprojects.collect { owner.project(it.path) }
}
What does this line mean? And why I have to add it? BuildSrc adds copiled classes automatically on the classpath,or I am wrong?
Gradle puts the "buildSrc project" and it's runtime dependencies on the buildscript classpath automatically but does not automatically put subprojects of buildSrc on your buildscript classpath.
If you have a multiproject build like described above, buildSrc is the root project but your custom logic is in the subprojects. Now when gradle puts buildSrc.jar on the buildscript classpath it is more or less empty.
The snippet
dependencies {
runtime subprojects.collect { owner.project(it.path) }
}
adds all your subproject as runtime dependencies to your root buildSrc project. This should fix your problem as Gradle puts the buildSrc AND it's runtime dependencies on the buildscript classpath.