how to exclude jar from fileTree in upstream projects? - gradle

We have the following configuration in a project...
configurations {
//compile.exclude module: 'commons'
//all*.exclude group: 'org.gradle.test.excludes', module: 'reports'
all*.exclude module: 'log4j'
}
dependencies {
compile group: 'org.slf4j', name: 'slf4j-api', version: '1.6.6'
compile group: 'org.slf4j', name: 'log4j-over-slf4j', version: '1.6.6'
compile group: 'com.google.inject', name: 'guice', version: '3.0'
compile group: 'com.google.protobuf',name: 'protobuf-java', version: '2.4.1'
//compile group: 'org.asteriskjava',name: 'asterisk-java', version: '1.0.0.M3'
//to be erased soon
compile group: 'commons-configuration',name:'commons-configuration',version: '1.8'
//compile group: 'org.bouncycastle', name: 'bcpg-jdk16', version: '1.46'
compile project(':sdi-master')
compile project(':sdi-webserver')
}
unfortunately, the project sdi-webserver has it's own log4j brought in from a filetree like so
project(':sdi-webserver') {
project.ext.genLibDir = file('lib')
dependencies {
compile project(':sdi-master')
compile fileTree(dir: '../webserver/lib', include: '*.jar')
compile fileTree(dir: '../webserver/play-1.2.4/framework/lib', include: '*.jar')
compile fileTree(dir: '../webserver/play-1.2.4/framework', include: 'play-*.jar')
}
How do we exclude this jar so it is not part of the dependencies. The above excludes that we have only works for repositories and transitive dependencies and doesn't work for fileTree, but we still need to somehow exclude the jar file as we want eclipse task building correct .classpath, we want configurations.compile having accurate info for copying jars, etc. etc.
thanks,
Dean

Simply use an exclude on fileTree. Syntax is the same as for include.

Related

How to run custom task within gradle build?

I have a Spring Boot web application which uses Gradle and NPM. I created a package.json file and npm install works fine. But I'd like to be able to run npm install automatically when I run gradle build. Here's my build file:
plugins {
id 'org.springframework.boot' version '1.5.10.RELEASE'
id 'java'
id 'war'
id "org.ysb33r.nodejs.base" version "0.1"
id "org.ysb33r.nodejs.npm" version "0.1"
}
group 'com.Blahblah'
version '1.0-SNAPSHOT'
war {
baseName = 'Blahblah'
version = '0.0.1'
}
sourceCompatibility = 1.8
repositories {
mavenCentral()
jcenter()
maven { url "http://repo.spring.io/libs-snapshot" }
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile group: 'commons-io', name: 'commons-io', version: '2.6'
compile group: 'commons-fileupload', name: 'commons-fileupload', version: '1.3.3'
compile group: 'com.cloudinary', name: 'cloudinary-core', version: '1.17.0'
compile group: 'com.cloudinary', name: 'cloudinary-http44', version: '1.17.0'
compile group: 'mysql', name: 'mysql-connector-java', version: '6.0.6'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '1.5.10.RELEASE'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-jersey', version: '1.5.10.RELEASE'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-mail', version: '1.5.10.RELEASE'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '1.5.10.RELEASE'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-tomcat', version: '1.5.10.RELEASE'
classpath "gradle.plugin.org.ysb33r.gradle:nodejs-gradle-plugin:0.1"
testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '1.5.10.RELEASE'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
apply plugin: "org.ysb33r.nodejs.base"
apply plugin: "org.ysb33r.nodejs.npm"
I added the ysb33r parts in plugins, dependencies and apply plugin sections, but now I get an error at the line:
classpath "gradle.plugin.org.ysb33r.gradle:nodejs-gradle-plugin:0.1"
It says:
A problem occurred evaluating root project 'Blahblah'.
> Could not find method classpath() for arguments [gradle.plugin.org.ysb33r.gradle:nodejs-gradle-plugin:0.1] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
Before I added the ysb33r lines, the build worked fine. What could be the problem? And when the problem is solved, how should I proceed in order to run npm install automatically?
Thanks.
A couple of issues:
Exec.commandLine is a String array
Your println is happening in the configuration phase, put it in a doLast block so it executes in the execution phase
Eg:
task npmInstall(type: Exec) {
commandLine 'npm install'.split(' ')
doLast {
println 'DONE!'
}
}
Rather than calling npm via Exec task, you should consider one of the gradle/nodejs plugins. Most of these are able to use an embedded nodejs version, downloaded from a repository, to execute nodejs commands rather than require a nodejs installation on the machine
See: https://plugins.gradle.org/search?term=nodejs
Eg: http://ysb33rorg.gitlab.io/nodejs-gradle-plugin/

dependencies syntax in gradle (closed)

I am trying to understand Gradle.I got this in my code
testCompile group: 'org.mockito', name: 'mockito-core', version: '2.9.0'
It works.
I wanted to understand the concepts.
Remote dependencies in Gradle follow the same format as Maven. Dependencies are structured as follows
compile 'group:name:version'
or this alternative syntax:
compile group: 'xxx', name: 'xxxxx', version: 'xxxx'
The same syntax is valid also for tests.
dependencies {
testCompile "org.mockito:mockito-core:2.9.0"
}
or
dependencies {
testCompile group: 'org.mockito', name: 'mockito-core', version: '2.9.0'
}

How to exclude dependency with classifier (platform version) in Gradle?

In my project I have dependency on 'org.nd4j:nd4j-native-platform:0.6.0' which brings me transitive dependencies:
Gradle: org.nd4j:nd4j-native:linux-ppc64le:0.6.0
Gradle: org.nd4j:nd4j-native:macosx-x86_64:0.6.0
Gradle: org.nd4j:nd4j-native:windows-x86_64:0.6.0
Gradle: org.nd4j:nd4j-native:linux-x86_64:0.6.0
I want to exclude nd4j-native:linux-ppc64le and nd4j-native:macosx-x86_64 since my application does not support these platforms. I write in my Gradle file:
configurations {
all.collect { configuration ->
configuration.exclude(group: 'org.nd4j', module: 'nd4j-native', classifier: 'linux-ppc64le')
}
}
Gradle says:
Error:(44, 0) Could not set unknown property 'classifier' for object of type org.gradle.api.internal.artifacts.DefaultExcludeRule.
It seems that gradle does not support exclusion by classifier.
How to exclude such a transitive dependencies?
Update: Gradle allows us to exclude dependencies, but what if we have several dependencies with the same id and group but different classifiers?
I have faced the same issued. I have used a deeplearning4j library with Gradle dependency.
compile group: 'org.nd4j', name: 'nd4j-native-platform', version: '1.0.0-beta'
compile group: 'org.deeplearning4j', name: 'deeplearning4j-core', version: '1.0.0-beta'
When I use this it is also downloading other platform classifiers and its size is almost 500MB. but my use case is specific to the Windows platform so i don't need other classifiers for Linux and Android and other platforms.If I exclude the group it is also excluding the classifier for the windows also . And in Gradle as of my knowledge, we can not exclude specific classifiers.
So the question was how to remove the specific classifier. What I found strange is when I made jar file of the project and extracted jar it shows me the org.nd4j:nd4j-native:linux-ppc64le:0.6.0 and other jars but when I generate dependency tree it is not showing me the specific jar in the tree.
So in order to find out in which specific module and project the jar is coming from I made a separate maven project and with this
<dependency>
<groupId>org.nd4j</groupId>
<artifactId>nd4j-native-platform</artifactId>
<version>1.0.0-beta</version>
</dependency>
<dependency>
<groupId>org.deeplearning4j</groupId>
<artifactId>deeplearning4j-core</artifactId>
<version>1.0.0-beta</version>
</dependency>
and then I have generated a dependency tree. It showed me the jars in the dependency tree.
What I did is I have removed the whole module and I have added the required classifier in a particular module with a specific version and it worked for me.
compile (group: 'org.deeplearning4j', name: 'deeplearning4j-core', version: '1.0.0-beta')
{
exclude group: 'org.bytedeco.javacpp-presets', module: 'opencv-platform'
exclude group: 'org.bytedeco.javacpp-presets', module: 'leptonica-platform'
exclude group: 'org.bytedeco.javacpp-presets', module: 'hdf5-platform'
}
compile (group: 'org.nd4j', name: 'nd4j-native-platform', version: '1.0.0-beta')
{
exclude group: 'org.bytedeco.javacpp-presets', module: 'openblas-platform'
}
compile group: 'org.nd4j', name: 'nd4j-native', version: '1.0.0-beta', classifier: "windows-x86_64"
compile group: 'org.bytedeco.javacpp-presets', name: 'openblas', version: '0.2.20-1.4.1'
compile group: 'org.bytedeco.javacpp-presets', name: 'openblas', version: '0.2.20-1.4.1', classifier: "windows-x86"
compile group: 'org.bytedeco.javacpp-presets', name: 'openblas', version: '0.2.20-1.4.1', classifier: "windows-x86_64"
compile group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: '3.4.1-1.4.1'
compile group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: '3.4.1-1.4.1',classifier: "windows-x86"
compile group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: '3.4.1-1.4.1',classifier: "windows-x86_64"
compile group: 'org.bytedeco.javacpp-presets', name: 'leptonica', version: '1.75.3-1.4.1'
compile group: 'org.bytedeco.javacpp-presets', name: 'leptonica', version: '1.75.3-1.4.1',classifier: "windows-x86"
compile group: 'org.bytedeco.javacpp-presets', name: 'leptonica', version: '1.75.3-1.4.1',classifier: "windows-x86_64"
Doing this reduced my jar size to almost 250MB
How to exclude such a transitive dependencies?
I think, the only way is to exclude all transitive dependencies by it's module or group and manually provide dependencies on libraries for platforms your application supports. Because classifiers are supported in dependency declaration.
And the same way you can handle the case, when you have a number of dependencies with the same module and grooup, but with different classifiers. Just add such dependencies manually with it's classifier property.

Gradle & SLF4J refusing to exclude transitive dependencies results in IllegalStateException

I am getting this error when running unit tests on my project:
Caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError. See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.
at org.slf4j.impl.Log4jLoggerFactory.<clinit>(Log4jLoggerFactory.java:54)
... 29 more
I need SLF4J, but not the clash that the following dependencies is setting up:
dependencies {
compile("org.springframework:spring-core:$springVersion")
compile("org.springframework:spring-jdbc:$springVersion")
// compile("org.springframework:spring-orm:$springVersion"
compile("org.springframework:spring-tx:$springVersion")
compile("org.springframework.data:spring-data-jpa:1.10.1.RELEASE") {
exclude module: "slf4j-api"
exclude module: "slf4j-over-slf4j"
exclude module: "jcl-over-slf4j"
}
// tag::jetty[]
compile("org.springframework.boot:spring-boot-starter-web:1.3.5.RELEASE") {
exclude module: "spring-boot-starter-tomcat"
exclude module: "slf4j-api"
exclude module: "slf4j-over-slf4j"
exclude module: "jcl-over-slf4j"
}
compile("org.springframework.boot:spring-boot-starter-jetty")
// end::jetty[]
// tag::actuator[]
compile("org.springframework.boot:spring-boot-starter-actuator")
// end::actuator[]
testCompile("junit:junit")
compile(group: 'org.hibernate.javax.persistence', name: 'hibernate-jpa-2.1-api', version: '1.0.0.Final')
compile("org.apache.velocity:velocity:1.7")
compile(group: 'org.slf4j', name: 'slf4j-api', version: '1.7.21')
compile('org.slf4j:log4j-over-slf4j:1.7.21')
compile(group: 'org.projectlombok', name: 'lombok', version: '1.16.8')
testCompile("org.springframework.boot:spring-boot-starter-test")
testCompile(group: 'junit', name: 'junit', version: '4.11')
}
I can stop the error via:
configurations {
all*.exclude group: "org.slf4j"
}
but then I get ClassNotFoundExceptions at runtime because slf4j is needed (and its adapters).
Any ideas? I just want to exclude slf4j from Spring's dependencies. I have seen plenty of threads on this issue but not resolve it -- are my exclusions correct?
I just excluded spring-boot-starter-logging:
configurations {
all*.exclude module: 'spring-boot-starter-logging'
}
My dependencies now look like this:
dependencies {
compile "org.springframework:spring-core:$springVersion"
compile "org.springframework:spring-jdbc:$springVersion"
compile "org.springframework:spring-orm:$springVersion"
compile "org.springframework:spring-tx:$springVersion"
compile "org.springframework.data:spring-data-jpa:1.10.1.RELEASE"
compile("org.springframework.boot:spring-boot-starter-web") {
exclude module: "spring-boot-starter-tomcat"
}
compile("org.springframework.boot:spring-boot-starter-jetty")
compile group: 'org.hibernate.javax.persistence', name: 'hibernate-jpa-2.1-api', version: '1.0.0.Final'
compile "org.apache.velocity:velocity:1.7"
compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.21'
compile group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.7.21'
compile group: 'org.projectlombok', name: 'lombok', version: '1.16.8'
testCompile("junit:junit")
testCompile "org.springframework.boot:spring-boot-starter-test"
testCompile group: 'junit', name: 'junit', version: '4.11'
}
Your problem is, that you have log4j-over-slf4j - which redirects all log4j logging to slf4j - and slf4j-log4j12 - which outputs all slf4j logging to log4j - in your classpath. This means you would have an endless loop which is wrong of course.
So you have to decide what you want. Do you want to redirect all log4j logging to slf4j and then direct all slf4j logging to some other logging framework (or slf4j-simple e. g. for logging to System.out or no binding to suppress the logging) or do you want to direct all slf4j logging to log4j, then it doesn't make sense to redirect log4j logging to slf4j in the first place.
How you correctly resolve your problem heavily depends on the desired result.
You can also find out what pulls in a dependency using the gradle task dependencyInsight.

gradle eclipse always says my webapp:eclipse is UP-TO-DATE

I am trying to get the source refs in the .classpath file so I remove my webapp/.classpath, webapp/.project and webapp/.settings stuff but gradle keeps printing this every time...
:eclipseClasspath
:eclipseJdt
:eclipseProject
:eclipse
:master:eclipseClasspath
:master:eclipseJdt
:master:eclipseProject
:master:eclipse
:webapp:eclipse UP-TO-DATE
No, it's clearly not up to date since it has no .classpath file!!!! grrrrrrr, My webapp dependencies are defined like so...(where master project uses ivy to define lots of dependencies)
dependencies {
compile project(':master')
compile fileTree(dir: '../webapp/play-1.2.5/framework/lib', include: '*.jar')
//, excludes: ['*log4j*','slf4j*'])
compile fileTree(dir: '../webapp/play-1.2.5/framework', include: 'play-*.jar')
}
My master dependencies are like so
project(':master') {
project.ext.genLibDir = file('../webapp/lib')
project.ext.fixedLibDir = file('libother')
configurations {
compile.exclude module: 'commons'
all*.exclude group: 'org.springframework'
all*.exclude module: 'log4j'
all*.exclude module: 'slf4j-log4j12'
all*.exclude module: 'junit'
all*.exclude module: 'antlr'
all*.exclude module: 'snakeyaml'
}
dependencies {
compile group: 'org.acegisecurity', name: 'acegi-security', version: '1.0.7'
//compile group: 'org.hibernate', name: 'hibernate-entitymanager', version: '4.1.4.Final'
//compile group: 'org.slf4j', name: 'slf4j-api', version: '1.6.6'
compile 'org.slf4j:log4j-over-slf4j:1.6.6'
compile 'org.slf4j:jcl-over-slf4j:1.6.6'
compile 'com.ning:async-http-client:1.7.6'
//ERASE this one as this client seems to suck usability-wise!!!
compile 'org.apache.httpcomponents:httpasyncclient:4.0-beta3'
compile group: 'ch.qos.logback', name: 'logback-core', version: '1.0.6'
compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.0.6'
//compile group: 'joda-time', name: 'joda-time', version: '2.1'
compile group: 'org.codehaus.jackson', name: 'jackson-mapper-asl', version: '1.9.8'
Any ideas what could be wrong? Why will it not generate my .classpath file???
I am running "gradle eclipse"
turning on debug results in these logs for webapp:eclipse
07:34:13.822 [LIFECYCLE] [org.gradle.TaskExecutionLogger] :webapp:eclipse
07:34:13.822 [DEBUG] [org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter] Starting to execute task ':webapp:eclipse'
07:34:13.823 [INFO] [org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter] Skipping task ':webapp:eclipse' as it has no actions.
07:34:13.823 [DEBUG] [org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter] Finished executing task ':webapp:eclipse'
07:34:13.823 [LIFECYCLE] [org.gradle.TaskExecutionLogger] :webapp:eclipse UP-TO-DATE
Another section of my build file I should mention is I apply the eclipse plugin to all projects like so
allprojects {
apply plugin: 'java'
apply plugin: 'eclipse'
project structure is simple
SDI
master
webapp
In my opinion, the logging is not good enough and is therefore a bug itself as anything that is up to date should really tell you why so I could continue. Anyway to turn on more logging?
thanks,
Dean

Resources