I'm using Gradle to create an ear, but I'm having a hard time figuring out how to properly include dependencies in the lib folder.
I know that I can use
earlib project (group:name:version)
to include jars there. And that also those jars' compile dependencies are going to be added in the ear's lib folder.
My problem is that I also have jars that are listed in the ear's build.gradle as
deploy project (':jar-name')
How can I add their dependencies in the lib folder?
The only way I found is to add them as earlib or as dependencies of an earlib, but this forces me to write them twice and feels harder than it should be (with Maven you just need to specify your dependencies in the subprojects and they will be added in the ear\lib directory)
EDIT
Basically what I would like to end up with, is a transitive deploy configuration.
Related
I have built two jars and put them in Artifactory. One of the jars depends on the other (the dependency is in its build.gradle file). When I download the main jar as a dependency of my main app, the dependent jar is not downloaded. The only way I can get both is to put two compile statements in the build.gradle. How do I cause the dependent jar to also get downloaded?
The main jar file is user-cache.jar and it depends on blue-redis.jar. The build.gradle in the app that uses my main jar uses this compile statement:
compile(group: 'etd.user-cache', name: 'user-cache', version: '1.0.2', ext: '12.SNAPSHOT.jar')
The build.gradle for user-cache has this in it:
compile(group: 'etd.blue-redis', name: 'blue-redis', version: '1.0.1', ext: '4.SNAPSHOT.jar')
When I build my app, it only gets user-cache.jar. That makes it necessary to put both compile statements in my app's build.jar
What should I do to cause the blue-redis.jar to also be downloaded without needing its compile statement?
I assume that you are using a maven repository in Artifactory. When gradle is doing dependency resolution it will attempt to download a POM file and check for transitive dependencies as well as parent poms which may list additional dependencies.
To get the desired behavior, when you publish the main jar to Artifactory you need to include in its POM file a dependency on the other JAR.
I am trying out Gradle, and am wondering, what is supposed to happen to a project's dependencies after you run gradle build? For example, my sample projects don't run on the command line after they are built, because they are missing dependencies. They seem to compile fine, as gradle doesn't give me errors or warnings about finding the dependencies.
Gradle projects I've made in IntelliJ Idea have the same problem. They compile and run inside the IDE, but are missing dependencies and can't run on the command line.
So what is supposed to happen to the dependencies I declare in the build.gradle file? Shouldn't they be output somewhere together with my .class files? Otherwise, what is the point of gradle when I could manage this by editing my classpath?
Edit: Here is my build.gradle file:
apply plugin: 'java'
jar {
manifest {
attributes('Main-Class': 'Animals')
}
}
repositories {
flatDir{
dirs "D:\\libs\\gradleRepo"
}
}
dependencies {
compile name: "AnimalTypes-1.0-SNAPSHOT"
}
sourceSets{
main{
java {
srcDirs=['src']
}
}
}
Your Gradle build only takes care of the compile time and allows you to use the specified dependencies in your code (it adds them to the compile classpath). But it does not take care of the runtime. Once the JAR is build, you need to specify the runtime classpath and provide all required dependencies.
You may think, that this is bad or a disadvantage, but actually it is totally fine and intended, because if you build a Java library, you won't need to execute it, you just want to specify it as a dependency for another project. If you would distribute your library to a Maven repository, all dependencies from Maven repositories (module dependencies) would end up in a POM descriptor as transitive dependencies.
Now, if you want to build a runnable Java application, simply use the Gradle Application Plugin (apply plugin: 'application'), which will create a ZIP file containing the dependencies and start scripts providing your runtime classpath for execution.
Third-party plugins can also produce so-called fat JARs, which are JAR files with all dependencies included. It depends on your use case if you should use them, because often dependency management via repositories is the better way to go.
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]
}
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
In gradle, is there a way to reference external jars. I have some external jars, sitting in another folder outside the project structure. Is there a way to add a reference to these jars in my build.gradle file, so that they are picked up during the compilation process?
Thanks
Edit:
I modified mu build.gradle with an allprojects task having the following 'sub-tasks(?)' as follows:
repositories{
flatDir name:'ExternalJars',dirs:'<path to the jars>'
dependencies{
compile: 'jarname:jarname:version'
}
}
This seems to make my build run just fine. Can someone shed some light on what exactly is happenning when I create the repository and specify the dependencies? - Thanks
The basic idea is that it looks for jar files in the root directory(s) you specified in flatDir that match [artifact]-[version].[ext] pattern.
Note: artifact group is ignored (so you can specify them as :jarname:version), and also all artifacts assumed to have no transitive dependencies.
By the way, another way to reference local jars is to create a local ivy repository. You'll need to use this if you want to declare transitive dependencies.