Is it possible to use resource files from jar in gradle? - gradle

I want to use resource files from two jar files. Is it possible ?
build.gradle
sourceSets {
main {
resources {
srcDir 'src/resources'
files('libs/myOwnFile-1.jar:src/resources')
//add another resource jar file
}
}
}
This means , I want to include resource files (mainly xml files) also from libs/myOwnFile-1.jar file. The jar is creating by other team but it's another project which cannot be linked with this project. But I know the path of resources (src/resources)
Is it possible to use src/resources under jar file ?

If an external JAR contains resources you want to use, consider just adding that JAR as a dependency to your project. That way, you can also use these resources in your own code.
For example, the following code will add all JARs in the libs folder as dependencies:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
The sourceSets property on the other hand is typically for sources/resources that are part of the project itself (and aren't part of another JAR).

Related

How to build a jar from a multi-module project when using Gradle?

I'm working on a multi-module library project which I build with Gradle. I have a dependency to another module of this project in my dependencies section:
dependencies {
compile project(':my-other-module')
}
My problem is that I want to build a .jar file which only contains the local modules in the final file, not its transitive dependencies. I tried this:
jar {
from project(':my-other-module').configurations.compile.collect { zipTree it }
}
but this added all the transitive dependencies as well. I want to create a .jar which only contains my own files, so the users of this library can have their own versions of transitive dependencies. How can I do so?
Further clarification:
I have dependencies declared in my project to external jars like apache-commons. I want these not to be in my resulting .jar file but I want the users of my library to be able to just add my library as a dependency and let Maven/Gradle download the transitive dependencies. I don't want these transitive dependencies to be in the .jar file I deploy to Maven Central. compileOnly is not an option since the dependencies I use like apache-commons are not provided by a framework or a container. They need to be present as compile dependencies. I just want to build and deploy a .jar file which has all the files in my project which has multiple modules.
I am not sure it'll help you or not but, you can try this.
In your build.gradle file, customize your jar task as follows:
// This closure will return the full directory path of folder where your classes are built
ext.moduleClassPath = { moduleName ->
def classOutputDirConst = "/classes/java/main"
return "${project(":${moduleName}").buildDir}${classOutputDirConst}"
}
// Now jar task will include only the built file of specified project
jar {
from(moduleClassPath("projectName1"), moduleClassPath("projectName2"))
}
Check the reference for the from(SourcePaths) method here: Reference: https://docs.gradle.org/current/dsl/org.gradle.jvm.tasks.Jar.html#org.gradle.jvm.tasks.Jar:from(java.lang.Object[])
Gradle has a compile-only dependency concept, similar to Maven's provided scope:
Compile-only dependencies are distinctly different than regular compile dependencies. They are not included on the runtime classpath and they are non-transitive, meaning they are not included in dependent projects.
The dependencies you don't want can be declared in the compileOnly configuration, rather than compile, eg:
dependencies {
compileOnly 'javax.servlet:servlet-api:2.5'
}
compileOnly is not even visible to unit tests, by default. We change this in a common gradle snippet which we include in each build:
// compileOnly isn't visible to tests by default, add it
plugins.withType(JavaPlugin).whenPluginAdded {
sourceSets {
test.compileClasspath += configurations.compileOnly
test.runtimeClasspath += configurations.compileOnly
}
}
For the second part, for which I believe you want to create a single "fat" jar,
I would suggest creating your jar using the very good Shadow Plugin, rather than manually extending the jar task. By default, the shadow plugin will not include anything in the compileOnly configuration in the resulting jar.

Gradle filter duplicate dependencies after they have been resolved

I have to develop a module against a live system that has a lib folder.
In order to get all the dependencies, I need to add a dependency on that folder.
Then I add my own new dependencies using the gradle way compile ...
The problem is the system already contains some of the libs I add as dependencies or that are resolved as transitive dependencies.
I would like to be able to though each dependency and if I find one with the same name in the lib folder, remove it, so I can use the one resolved from the maven repository.
Any idea where I can insert that code, or if it is possible ?
** I guess one other option would be to copy them and filter by hand into a new lib folder, I am wondering if I can make something automatic that may take into account future upgrades
I have to develop a module against a live system that has a lib folder.
The problem is the system already contains some of the libs I add as dependencies or that are resolved as transitive dependencies.
The best way to manage this case is to avoid the lib folder and just move all these libraries/dependencies in a maven (private) repo.
In this way gradle will manage all nested dependencies avoiding to duplicate libraries with different versions.
I'm guessing you've got something like this
dependencies {
compile fileTree(dir: 'lib', include: '*.jar')
}
Unfortunately when you do this, the GAV (group, artifact, version) is not known to gradle. Each jar is simply a file without a GAV or any other metadata (eg transitive dependencies). None of these jars can participate in Gradle's dependency resolution.
If you want to put your jars in a local folder, I suggest you use the maven repository directory layout (eg /someFolder/$groupIdWithSlashes/$artifactId/$version/$artifactId-$version.$extension)
You could then specify the local folder as a maven repository
repositories {
maven {
url uri('mavenRepo')
}
}
dependencies {
compile 'group1:artifact1:1.0'
compile 'group2:artifact2:2.0'
}
Jars could then be stored as
mavenRepo/group1/artifact1/1.0/artifact1-1.0.jar
mavenRepo/group2/artifact2/2.0/artifact2-2.0.jar
Optionally, you might want to add poms with transitive dependencies etc at
mavenRepo/group1/artifact1/1.0/artifact1-1.0.pom
mavenRepo/group2/artifact2/2.0/artifact2-2.0.pom
More details on maven directory layout here
Adding another answer because you don't want to do it properly, you want a hack
You could do something like this:
def libJars = fileTree(dir: 'lib', include: '*.jar')
dependencies {
compile 'foo:bar:1.0'
compile project(':anotherProject')
compile libJars
}
libJars.files.each { File libJar ->
// assuming jars are named $module-$version.jar
Pattern pattern = Pattern.compile("(.+)-.+?\\.jar")
Matcher matcher = pattern.matcher(libJar.name)
if (!matcher.matches()) throw new RuntimeException("${libJar.name} does not match ${pattern.pattern()}")
String module = matcher.group(1)
// exclude other dependencies with the same module as this "libJar"
configurations.compile.exclude [module: module]
}

How to add external jars to build.gradle from local system folder

I have created a custom plugin in groovy. now i want to add it to my build.gradle in another project:
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
}
Above lines does not seem to work for me. i have put my external jar in libs folder in project root folder. I am getting error plugin with id not found.Please correct me if i am wrong.

Gradle include jar produced by another project in war

Currently I have two projects with gradle build.gradle. The first is going to create a fat jar file, which I would like to include in a war file. I thought compiling it would be enough, but it doesn't seem to be ending up in the /lib directory of my war file. Anyone have thoughts I am quite new to gradle.
dependencies {
compile project(':JarProject')
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
providedCompile 'org.apache.tomcat:tomcat-jsp-api:7.0.55'
}
war {
archiveName 'WarProject.war'
from 'JarProject/build/libs'
webXml = file('src/web.xml')
}
Does the second project war need to be in providedRuntime? Or should I publish the jar from the other project in the local maven repo and include it that way?
The War task essentially behaves like a CopyTask with regards to stuff it packs in the war, so the documentation on working with files is useful. In essence, I think you need something like (untested):
from fileTree('JarProject/build/libs') {
into("lib")
}
That being said, using mavenLocal() and publishing there also works, but it can lead to unexpected results when the war includes some old version from local, picking up the jar explicitly from the file system like above is better.
I think the elegant solution would be to use multi project builds and project level dependencies. You would have the two builds as separate projects of the same Gradle build and add the "jar project" as a regular compile dependency.
How have you declared the dependency? I assume you have a multi-project build with subprojects A and B, both using the War plugin. I made an experiment using Gradle 2.4 and if I declare B/build.gradle like this:
apply plugin: 'war'
dependencies {
compile project(':A')
}
then B.war contains WEB-INF/lib/A.jar. If you correctly follow conventions of Gradle War plugin (place web resources in A/src/main/webapp/ and code-related resources in A/src/main/resources/), then A.jar should contain what you want.
see this

Gradle 1.2: Exclude directory under resources sourceSets

I have development related directory src/main/resources/certs/test which is needed for one external library. This has some cert files which are not needed in production build.
At the moment I exclude everything under that directory with following block in build.gradle:
sourceSets {
main {
resources {
exclude '**/test/*'
}
}
}
This does it job well, but leaves ugly empty directory test lying there. What are my options to not include this directory in final war?
I've tried excluding '**/test', but it doesn't work at all.
I use war plugin and Gradle 1.2
Using Gradle 1.1, this works for me:
apply plugin: 'war'
sourceSets {
main {
resources {
exclude '**/test/*'
exclude 'certs/test'
}
}
}
I had a similar problem with production files in a JAR file (though mine were not test files). I solved it with the following:
jar {
exclude ("DIRECTORY-TO-EXCLUDE/**")
}
e.g.
jar {
exclude ("test/**")
}
A common projet layout is to put test files under the test source set, this way you don't have to exclude them from the main source set.
From the Gradle documentation, the default project layout is like this:
src/main/java Production Java source
src/main/resources Production resources
src/test/java Test Java source
src/test/resources Test resources

Resources