how to copy the dependencies libraries JARs in gradle - copy

I got a runnable jar with this build.gradle
apply plugin: 'java'
apply plugin: 'application'
manifest.mainAttributes("Main-Class" : "com.test.HelloWorld")
repositories {
mavenCentral()
}
dependencies {
compile (
'commons-codec:commons-codec:1.6',
'commons-logging:commons-logging:1.1.1',
'org.apache.httpcomponents:httpclient:4.2.1',
'org.apache.httpcomponents:httpclient:4.2.1',
'org.apache.httpcomponents:httpcore:4.2.1',
'org.apache.httpcomponents:httpmime:4.2.1',
'ch.qos.logback:logback-classic:1.0.6',
'ch.qos.logback:logback-core:1.0.6',
'org.slf4j:slf4j-api:1.6.0',
'junit:junit:4.+'
)
}
but it run failed, because the dependencies jars can't find.
and then I add this code:
task copyToLib(type: Copy) {
into "$buildDir/output/libs"
from configurations.runtime
}
but nothing change. I can't find the folder output/libs.
how can I copy the dependencies libs jars to a specified folder or path?

Add:
build.dependsOn(copyToLib)
When gradle build runs, Gradle builds tasks and whatever tasks depend on it (declared by dependsOn). Without setting build.dependsOn(copyToLib), Gradle will not associate the copy task with the build task.
So:
apply plugin: 'java'
apply plugin: 'application'
manifest.mainAttributes('Main-Class': 'com.test.HelloWorld')
repositories {
mavenCentral()
}
dependencies {
compile (
'commons-codec:commons-codec:1.6',
'commons-logging:commons-logging:1.1.1',
'org.apache.httpcomponents:httpclient:4.2.1',
'org.apache.httpcomponents:httpclient:4.2.1',
'org.apache.httpcomponents:httpcore:4.2.1',
'org.apache.httpcomponents:httpmime:4.2.1',
'ch.qos.logback:logback-classic:1.0.6',
'ch.qos.logback:logback-core:1.0.6',
'org.slf4j:slf4j-api:1.6.0',
'junit:junit:4.+'
)
}
task copyToLib(type: Copy) {
into "${buildDir}/output/libs"
from configurations.runtime
}
build.dependsOn(copyToLib)

I find the application plugin way too cumbersome and too verbose in its output. Here's how I finally got a setup I was happy with, i.e., create a distribution zip file with dependency jars in subdirectory /lib and add all dependencies to Class-Path entry in the manifest file:
apply plugin: 'java'
apply plugin: 'java-library-distribution'
repositories {
mavenCentral()
}
dependencies {
compile 'org.apache.commons:commons-lang3:3.3.2'
}
// Task "distZip" added by plugin "java-library-distribution":
distZip.shouldRunAfter(build)
jar {
// Keep jar clean:
exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.MF'
manifest {
attributes 'Main-Class': 'com.somepackage.MainClass',
'Class-Path': configurations.runtime.files.collect { "lib/$it.name" }.join(' ')
}
// How-to add class path:
// http://stackoverflow.com/questions/22659463/add-classpath-in-manifest-using-gradle
// https://gist.github.com/simon04/6865179
}
Hosted as a gist here.
The result can be found in build/distributions and the unzipped contents look like this:
lib/commons-lang3-3.3.2.jar
MyJarFile.jar
Contents of MyJarFile.jar#META-INF/MANIFEST.mf:
Manifest-Version: 1.0
Main-Class: com.somepackage.MainClass
Class-Path: lib/commons-lang3-3.3.2.jar

Since Gradle 6.0 it is:
tasks {
val deps by registering(Copy::class) {
from(configurations.runtimeClasspath)
into("build/deps")
}
}

The problem with all the previous answers is that they only collect dependencies from one configuration. To get ALL of the dependencies, you should use this:
task saveDependencies(type: Copy){
configurations.each {
if (it.isCanBeResolved())
from it into "gradle_dependencies"
}
from buildscript.configurations.classpath into "gradle_dependencies"
}

The application plugin requires you to set the main class name like this:
mainClassName = "com.test.HelloWorld"
You will need to add that to your build script. Keep in mind that if you try to run your application with the java command you will also need to set the classpath with -cp.
The application plugin simplifies this process by providing the task distZip. If you run that task you a full distribution is created for you under build/distributions. The distribution contains start scripts and all dependencies. The generated start scripts already set the classpath for you so you don't have to deal with it anymore.

The java plugin can pack a jar with dependencies and there's no need for the application plugin. A task like the following would do:
task buildWithDeps(type: Jar) {
manifest {
attributes "Main-Class": "com.test.HelloWorld"
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}

As of at least Gradle 5.6.4 you'll want to do something closer to this.
dependencies {
implementation 'my.group1:my-module1:0.0.1'
implementation 'my.group2:my-module2:0.0.1'
}
jar {
from {
configurations.compileClasspath.filter { it.exists() }.collect { it.isDirectory() ? it : zipTree(it) }
}
}

For Gradle 7.4 with Groovy:
configurations {
externalLib.extendsFrom(implementation)
}
task copyLibs(type: Copy){
from configurations.externalLib{
into '<dest-dir-name>'
exclude('<if any jars need to be excluded>')
}
}

Related

Gradle-Scala Project Error - Could not load Main Class

I have created a gradle/scala project in intellij.
This is my project structure
build
gradle
- wrapper
META-INF
out
src
- main
-resources
-scala
- test
-resources
-scala
build.gradle
gradlew
gradlew.bat
settings.gradle
These are the contents of my build.gradle file
plugins {
id 'scala'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenLocal()
maven {
url = uri('<artifactory location>')
}
}
jar {
manifest {
attributes(
'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
'Main-Class': 'org.example.Hello'
)
}
}
sourceCompatibility = '12'
dependencies {
implementation 'org.scala-lang:scala-library:2.12.14'
testImplementation 'org.scalatest:scalatest_2.12:3.0.5'
testRuntimeOnly 'org.scala-lang.modules:scala-xml_2.12:1.1.1'
}
test {
useJUnitPlatform()
}
Main Class Content
package org.example
object Hello extends App {
println("hello!")
}
When I try to build the jar and execute it , it gives an error
Could not find or load main class org.example.Hello . What might be the mistake here?
I was able to resolve the issue by adding the following in the settings.gradle
rootProject.name = 'gradle-scala'
include('gradle-scala')
Basically , the include tag is used to specify the directory where the code resides .
I see out directory, can you check the gradle settings
ensure below are ticked

Idea cannot recognize a symbol even it is present in external dependencies

Does somebody understands what is a problem? Why my IDE doesn't see classes from dependencies? Idea version: 17.2.2
The root build.gradle:
subprojects.each {
apply plugin: 'idea'
}
The root setting.gradle:
include 'client'
include 'api'
rootProject.name = 'app-1-akka-reactjs'
My build.gradle of api project:
apply plugin: 'play'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.iatoki:gradle-play-idea:0.4.1'
}
}
apply plugin: 'org.iatoki.play-idea'
repositories {
jcenter()
ivy {
url "https://repo.typesafe.com/typesafe/ivy-releases/"
layout "pattern", {
ivy "[organisation]/[module]/[revision]/ivys/ivy.xml"
artifact "[organisation]/[module]/[revision]/jars/[artifact].[ext]"
}
}
}
model {
components {
play {
platform play: '2.5.8', scala: '2.11', java: '1.8'
injectedRoutesGenerator = true
}
}
}
dependencies {
play 'com.typesafe.play:play-slick_2.11:2.1.0'
play 'com.typesafe.play:play-slick-evolutions_2.11:2.1.0'
play 'org.postgresql:postgresql:9.4-1200-jdbc41'
}
The build.gradle of client is empty for now.
To generate idea's files I've used:
gradle cleanIdea idea
I faced a similar issue. I could resolve it by moving/copying the settings.xml file from $MVN_HOME/conf to ~/.m2 folder. As MVN_HOME was not detected by Idea it could not resolve the settings.xml from MVN_HOME.

Gradle execute Groovy script in GroovyShell with Eclipse Luna

I am getting a ClassNotFoundException: org.apache.ivy.core.report.ResolveReport when executing a gradle task, which uses Grapes to resolve dependencies.
I am using Eclipse Luna 4.4.0 with a Gradle/Groovy Project having this build.gradle:
apply plugin: 'groovy'
apply plugin:'application'
mainClassName = "de.my.app.package.Main"
version = 0.5
repositories { mavenCentral() }
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.4.3'
compile group: 'org.apache.ivy', name:'ivy', version:'2.2.0'
compile 'commons-io:commons-io:2.4'
compile 'commons-codec:commons-codec:1.2'
}
task myTask << {
def groovyShell = new GroovyShell()
groovyShell.run(file('/src/scripts/groovy/de/my/app/package/scripts/SomeScript.groovy'))
}
classes.finalizedBy(myTask)
My Java Build Path inside Project->Properties looks like this:
This is SomeScript.groovy inside the Folder /src/scripts/groovy/de/my/app/package/scripts:
package de.my.app.package.scripts
#Grapes(
#Grab(group='org.eclipse.birt.runtime.3_7_1', module='org.apache.commons.codec', version='1.3.0')
)
#Grapes(
#Grab(group='commons-io', module='commons-io', version='2.4')
)
import org.apache.commons.codec.binary.Hex
println Hex.toString()
Weird thing is that executing SomeScript.groovy from cmd with groovy SomeScript.groovy does not give the error. So i am guessing it is some Eclipse config I have missed.
How can SomeScript.groovy be executed by the Gradle run from the build.gradle without causing a ClassNotFoundException: org.apache.ivy.core.report.ResolveReport?
I have found a solution for my problem. I needed this build.gradle file:
apply plugin: 'groovy'
apply plugin:'application'
mainClassName = "de.my.app.package.Main"
version = 0.5
repositories { mavenCentral() }
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.4.3'
compile group: 'org.apache.ivy', name:'ivy', version:'2.2.0'
compile 'commons-io:commons-io:2.4'
compile 'commons-codec:commons-codec:1.2'
}
task myTask (type: Exec) {
def groovyHome = System.getenv("GROOVY_HOME")
def someScriptPath= new String(project.projectDir.toString()).toString() + "\\src\\scripts\\groovy\\de\\my\\app\\package\\main\\SomeScript.groovy"
commandLine "${groovyHome}\\bin\\groovy.bat", someScriptPath
}
classes.finalizedBy(myTask)
So I abandoned the approach of using the class GroovyShell, because I could not configure the classPath for it correctly.
My Script executes now before every run. Problem is solved.

New sourceSet by gradle cannot be seen in Eclipse

I have created additional source set called "integration-test" in my gradle project. Ewerything works fine, but eclipse cannot see dependency classes defined exactly for this source set.
subprojects {
apply plugin: 'java'
apply plugin: 'eclipse'
repositories {
mavenCentral()
}
sourceSets {
integrationTest {
java {
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
srcDir file('src/integration-test/java')
}
resources.srcDir file('src/integration-test/resources')
}
}
configurations {
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
}
dependencies {
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-all:1.10.19'
integrationTestCompile 'org.springframework:spring-test:4.1.7.RELEASE'
compile 'org.springframework:spring-context:4.1.7.RELEASE'
compile 'org.springframework:spring-core:4.1.7.RELEASE'
}
task integrationTest(type: Test) {
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
outputs.upToDateWhen { false }
}
check.dependsOn integrationTest
integrationTest.mustRunAfter test
version = '1.0'
}
When i build this project by command "build gradle", project is build, the only problem is with eclipse. If I change dependency 'org.springframework:spring-test:4.1.7.RELEASE' from "integrationTestCompile" to "testCompile", problem is gone.
It is a little late to answer your question, but I just found a solution to this, since I had the exact same problem.
Adding this:
eclipse {
classpath {
plusConfigurations.add configurations.integrationTestCompile
plusConfigurations.add configurations.integrationTestRuntime
}
}
to the gradle file solved the problem. I hope it does the same for you.
An approach that I found that worked really well for me is this test sets plugin: https://plugins.gradle.org/plugin/org.unbroken-dome.test-sets
It made it really easy to add integration tests to my module. And it works with the eclipse plugin automatically.

Is it possible to extend a gradle build script configured in a binary plugin?

I've created a Gradle plugin below:
class CommandServiceProjectPlugin implements Plugin<Project> {
public void apply(Project project) {
project.buildscript{
repositories {
maven: {
url: 'http://localhost:8081/artifactory/zailab-virtual-repo'
credentials: {
username = "admin"
password = "password"
}
}
}
/*Spring Boot Gradle plugin */
dependencies {
classpath: 'org.springframework.boot:spring-boot-gradle-plugin:1.1.6.RELEASE'
}
}
project.apply plugin: 'spring-boot'
project.apply plugin: 'java'
project.apply plugin: 'eclipse'
project.repositories {
maven: {
url: 'http://localhost:8081/artifactory/zailab-virtual-repo'
}
}
project.dependencies {
/*Spring Boot dependencies */
compile: 'org.springframework.boot:spring-boot-starter-test'
compile: 'org.springframework.boot:spring-boot-starter-aop'
compile: 'org.springframework.boot:spring-boot-starter-data-mongodb'
compile: 'org.springframework.boot:spring-boot-starter-integration'
compile: 'org.springframework.boot:spring-boot-starter-amqp'
/*Axon dependencies */
compile: 'org.axonframework:axon-core:2.3.1'
compile: 'org.axonframework:axon-mongo:2.3.1'
}
}
}
I then apply the plugin within another project as below, but it seems the buildscript definitions override/conflict as the 'spring-boot' plugin cannot be found. Am I attempting the impossible or is there perhaps another way to achieve what I am trying to do?
buildscript {
repositories {
maven {
url 'http://localhost:8081/artifactory/zailab-virtual-repo'
credentials {
username = "admin"
password = "password"
}
}
}
dependencies {
classpath(group: 'com.zailab', name: 'zailab-command-service-build', version: '1.0.0- SNAPSHOT')
}
}
apply plugin: 'com.zailab.command.service.project'
Thanks,
Roscoe
As far as I know, it's not possible to add build script dependencies programmatically from a plugin.
Reason for this is build script life cycle - invocation of plugins' apply method happens after the project's classpath configuration had already been resolved.
You should either configure the buildscript in project's build script, or package classpath dependencies with the plugin.