Copy jar from dependent Project in Gradle? - java

I have to gradle projects core and main. They are in a flat project structure:
/
/core
/main
Both projects use the java plugin. The main project has a settings.gradpe file with the following content:
includeFlat "core"
The build.gradle of main is:
apply plugin: 'java'
apply plugin: 'eclipse'
...
dependencies {
compile (project(':core'))
}
When I execute the build task on the main project. The core project is build first and the generated core-1.0.jar is used as dependency for the compile task of main.
When I use the build task on main I want that the core-1.0.jar from the core project is copied into the lib folder of my main project.
How can I do that?

Related

Use gradle plugin in parent project's buildSrc

How can a subproject in a multiproject Gradle build use a Gradle plugin that's defined in the root project's buildSrc folder?
I've basically got:
settings.gradle
buildSrc/src/main/groovy/com/example/conventions/JavaConventionsPlugin.groovy
buildSrc/build.gradle
common/build.gradle
and I'm trying to apply the plugin in the common project:
apply plugin: 'com.example.conventions.JavaConventionsPlugin'
but it says
Plugin with id 'com.example.conventions.JavaConventionsPlugin' not
found.
Looks like the plugin layout is different in buildSrc and I should have been following this example: https://docs.gradle.org/current/samples/sample_convention_plugins.html
buildSrc/build.gradle
buildSrc/settings.gradle
buildSrc/src/main/groovy/example.java-conventions.gradle
buildSrc/src/main/groovy/com/example/conventions/JavaConventionsPlugin.groovy
and applying using:
plugins {
id 'example.java-conventions'
}

Build is successful but the runtime dependency seems bad in Gradle dependency

dependencies {
compile 'org.slf4j:slf4j-api:1.7.13'
compile group: 'org.apache.commons', name: 'commons-math3' , version: '+'
testCompile 'junit:junit:4.12'
}
Even if I add this, when I run gradle build, it works, and codes with commons-math3 can be compiled. But when I run a jar file in build/,
it says Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/math3/complex/Complex
But the official Gradle site says, the resource in 'compile' will also be included in 'runtime' dependency. and I also tried adding the commons-math to runtime. but it does not work.
Maybe this is my misunderstood of the dependency system.
How can I include external library from maven repository into a jar file made by the Gradle.
What you are looking for is either the distribution zips produced by the application plugin or the shadow jar (also called fat jar) produced by the shadowJar plugin:
The distribution zip (application plugin)
About the distribution zip
The distribution zips look like this:
my-app-0.2.0.zip
├──bin
│ ├──my-app
│ └──my-app.bat
└──lib
├──my-app-0.2.0.jar
├──slf4j-api.1.7.13.jar
└──commons-math3-3.6.jar
You can then run your application with its dependencies by unzipping what has been produced in build/distributions/ and running either my-app.bat (on windows) or ./my-app (on linux or OS X)
Building a distribution zip
Here is a sample gradle build file for making a distribution zip:
build.gradle
apply plugin: 'java'
apply plugin: 'application'
mainClassName = 'org.myapp.Main'
repositories { jcenter() }
dependencies {
compile 'org.slf4j:slf4j-api:1.7.13'
compile 'org.apache.commons:commons-math3:3.6'
testCompile 'junit:junit:4.12'
}
Can be run with gradle distributionZip or gradle distributionTar. To just run the application, use gradle run.
The shadow jar
About the shadow jar
The shadow jar is one giant jar file that is a combination of your program and its libraries, packed together into one file. You will get a file that is self-contained and can be run by a double-click on most systems (e.g. on Windows that works, on Xubuntu it can be run by right-clicking and selecting 'Run with Oracle Java 8 Runtime', etc...).
Building a distribution zip
Here is, again, a sample build.gradle file:
apply plugin: 'java'
apply plugin: 'com.github.johnrengelman.shadow'
mainClassName = 'org.myapp.Main'
jar {
manifest {
attributes('Main-Class': mainClassName)
}
}
buildscript {
repositories { jcenter() }
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.2'
}
}
repositories { jcenter() }
dependencies {
compile 'org.slf4j:slf4j-api:1.7.13'
compile 'org.apache.commons:commons-math3:3.6'
testCompile 'junit:junit:4.12'
}
Run it with gradle shadowJar - Your jar with packed dependencies will be in build/libs and it will be named my-app-x.x.x-all.jar.
Gradle is first of all a build tool (just like maven, btw).
Its "responisiblity" starts when you feed it a source file and ends when you get your artifact (in your case its a jar).
Now when you're going to actually run your application there is a plethora of different options here.
If you just run java -jar <your_jar> you are responsible by yourself to construct the classpath.
If you run it with some kind of external runner, you should read the documentation of it and supply it a classpath.
Hope this helps

Gradle does not execute subprojects

Currently I'm trying to migrate my project to gradle from maven and to do so I'm creating a custom script which generates gradle build files from pom files taking into account all project specifics.
Script generates "build-generated.gradle" file which is meant to be executed on configuration phase from build.gradle file.
//Text of common build.gradle:
println "Configuring ${project.name}"
apply from: 'build-generated.gradle'
The problem is that when I try to run "gradle build" the result is not what I'm expecting:
An initialization phase all subprojects are included and futhermore I can print names of all subprojects using
subprojects{
println "I'm ${project.name}"
}
but at configuration and execution phase the subproject's build.gradle files are not executed.
What am I doing wrong?
The issue was adding root project into include chain in settings.gradle

How to use Gradle to build a JAR that depends on another JAR

I have a Eclipse workspace with a declared workset configured to have several projects. Some are to generate JAR files and others are web applications that use those JAR files. In my architecture I have a JAR that will consist of domain core services and another one that depends on the first one that will consist of higher level services. Finally I will have some web applications that use those both JARs.
The first JAR project is build with Gradle, based on the following script
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'application'
repositories {
mavenLocal()
mavenCentral();
}
jar {
baseName = 'br.ufpr.unidades.dominio'
version = '0.1.0'
}
dependencies {
compile 'org.hibernate:hibernate-core:4.3.7.Final'
}
task wrapper(type: Wrapper) {
gradleVersion = '1.11'
}
As anyone can see, it´s a very simple build.gradle file and the build works fine with it. The expected JAR file is generated in the expected destination folder.
Now, here comes the build script for the second JAR:
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'application'
repositories {
mavenLocal()
mavenCentral()
}
jar {
baseName = 'br.ufpr.unidades.dominio.hibernate'
version = '0.1.0'
}
dependencies {
runtime fileTree(dir: '../dominio/build/libs', include: '*.jar')
compile 'org.hibernate:hibernate-core:4.3.7.Final'
}
task wrapper(type: Wrapper) {
gradleVersion = '1.11'
}
The second file is very similar to the first one, except it has a dependency on generated JAR:
runtime fileTree(dir: '../dominio/build/libs', include: '*.jar')
Eclipse doesn´t show any problems, but when I try to build the second JAR project I get many Class not found error messages, like the one below:
[sts] -----------------------------------------------------
[sts] Starting Gradle build for the following tasks:
[sts] build
[sts] -----------------------------------------------------
:compileJava
D:\Users\alex\Documents\Eclipse\workspace\unidades\dominio.hibernate\src\main\java\dominio\hibernate\HibernateCargoRepository.java:7: error: package unidades.dominio does not exist
import unidades.dominio.Cargo;
The message is clear: I´m importing a package that is not being found during the build, so the classes such a package has cannot be referenced in my code. Such a package is declared in the first and perfectly generated JAR file. It also is visible under Referenced Libraries item in the Eclipse project, so Gradle was able to find it to reference it in design time, but not to build the second JAR.
After all that, I suspect it´s a dependency management problem, but I can´t see which it is and how to fix it.
Thanks in advance!
Are You using classes from the jar under dominio/build/libs in the second project? If so, this should be a compile dependency. I'd also recommend setting a multimodule gradle project. Here are the docs.

Gradle Dependencies aren't included in jar

I'm very new to Gradle and the main reason I use it because I need to resolve dependencies issues for my compiled jar.
Here is my build.gradle file:
apply plugin: 'java'
apply plugin: 'eclipse'
version = '0.9'
jar {
manifest {
attributes 'Main-Class': 'wd.nlp.FileImport', 'Implementation-Title': 'WD\
NLP', 'Implementation-Version': version
}
}
repositories {
flatDir(dirs: 'lib')
}
dependencies{
compile 'mallet:mallet:2.0.7'
}
My Java files all depend on a third-party library called Mallet. Here is my folder structure:
|---1.10
|-----taskArtifacts
|-build
|---classes
|-----main
|-------wd
|---------nlp
|---dependency-cache
|---libs
|---tmp
|-----jar
|-lib
|-src
|---main
|-----java
|-------wd
|---------nlp
|-----resources
I placed Mallet-2.0.7.jar inside lib under the top folder. Then I used gradle build command and try to run my class:
java -classpath build/libs/JavaClassifier-0.9.jar wd.nlp.FileImport -train ...
Then I am told:
Exception in thread "main" java.lang.NoClassDefFoundError: cc/mallet/pipe/Pipe
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2531)
The Mallet library's path is cc.mallet.*...and now I don't know what to do...please help!
The dependency is not include because you don't create a distribution of you project. In Maven it is called an assembly.
If you call your application directly from the commandline it is not a matter of Gradle.
Anyway there is a Gradle plugin which creates a distribution and adds shell scripts to execute your application.
So when you add the following line to the gradle script.
apply plugin: 'application'
you will get some new tasks to create a distribution.

Categories