Gradle equivalent of Maven Assembly - maven

As long as Gradle has been around, I'd have thought this was well documented, but I'm struggling. Sorry if this is obvious to everyone else.
I have a multi-project build setup with maven, I'm setting up gradle for comparison.
Project A produces a jar file, Project B produces a war file (and depends on the jar from A). Project C I want to create an assembly, i.e. a zip file. The zip file should contain the contents of a directory within project C, the war file from Project B, and the unpacked contents of a tomcat assembly pulled down from Archiva.
The problem I'm having is that when gradle evaluates the build.gradle files, it fails because it can't find the war file - which is no surprise, the war file hasn't been built yet.
So, how do I express the dependency on the war file in such a way that it doesn't cause the failure during evaluation?
apply plugin: 'distribution'
description = """E2am Assembly"""
project(':assembly') {
dependencies {
compile project(':webapps/e2am')
}
}
dependencies {
compile group: 'com.e2open.platform', name: 'e2am', version:'9.0-SNAPSHOT', ext:'war'
compile group: 'com.e2open.platform.third-party.tomcat', name: 'tomcat-assembly',version:'7.0.42-1002', classifier:'bin', ext:'zip'
}
task explodeTomcat(type: Copy, dependsOn: ':webapps/e2am:install'){
configurations.compile.filter { it.toString().endsWith(".zip") }.each{
from zipTree(it)
}
into 'TomcatUnpacked'
configurations.compile.filter { it.toString().endsWith(".war") }.each{
from it
}
into 'war'
}
distributions {
main {
baseName = 'e2am-assembly'
contents {
from { 'tomcat' }
from { 'TomcatUnpacked' }
from { 'war' }
}
}
}
distZip.dependsOn explodeTomcat
install.dependsOn distZip
Also, the top level project applies the 'java' and 'maven' plugin to all sub projects.
The error is:
FAILURE: Build failed with an exception.
* Where:
Build file '/kwork/wkcopy/e2amA/assembly/build.gradle' line: 25
* What went wrong:
A problem occurred evaluating project ':assembly'.
> Could not resolve all dependencies for configuration ':assembly:compile'.
> Could not find com.e2open.platform:e2am:9.0-SNAPSHOT.
Required by:
com.e2open.platform:assembly:9.0-SNAPSHOT
Can someone point me to documentation or a discussion that gets me farther down the road? Thanks!

You should take a look at Multi-project Builds - Project lib dependencies in the Gradle documentation.
Something like this should work:
dependencies{
compile project(:webapps/e2am)
compile group: 'com.e2open.platform.third-party.tomcat', name: 'tomcat-assembly',version:'7.0.42-1002', classifier:'bin', ext:'zip'
}
There's also an example that looks a lot like what you are trying to do - might be worth a look :)

Related

Gradle copy local jar into cache

I need some help understanding why my build.gradle does not copy locally referred jar into its cache. On Windows, I expected to see jars in C:\Users\myusername .gradle and indeed other JARs are there.
I can't import this JAR in IntelliJ as it does not find it.
Side question: did anybody figure out how to debug Gradle's DSL? I set up remote debugging and IntelliJ never hits my breakpoint. It does not the have the checkbox on it so I guess IDE does not think it is code.
Few things are not making sense to me:
1. gradle dependencies --configuration compile
\--- com.google.guava:guava:23.5-jre
+--- com.google.code.findbugs:jsr305:1.3.9
....
MY_JAR_1.0.1.jar is not present.
2. gradle copyDependencies - this task finds and copies it.
task copyDependencies(type: Copy) {
from configurations.compile
into 'dependencies'
}
3. This task also finds my jar.
task listcompile << {
configurations.compile.each { File file -> println file.name }
}
Why does #1 not find it?
apply plugin: 'java'
repositories {
mavenCentral()
//flatDir {
// dirs 'customlibs'
//}
}
dependencies {
compile group: 'com.google.guava', name: 'guava', version: '23.5-jre'
compile files('customlibs/MY_JAR_1.0.1.jar')
}
task listcompile << {
configurations.compile.each { File file -> println file.name }
}
// copy all dependencies into this folder
task copyDependencies(type: Copy) {
from configurations.compile
into 'dependencies'
}
It seems that Gradle's dependencies task will only display modules that have a defined group:name:version coordinate. You are adding a file directly, with no associated identifier.
What you can do instead is add a flat directory repository and declare your custom JAR as a normal dependency, like so:
repositories {
flatDir {
dirs 'customlibs'
}
}
dependencies {
compile ':MY_JAR:1.0.1'
}
You will need to rename the JAR so that it matches the naming convention for Maven/Gradle, i.e. MY_NAME-1.0.1.jar (replacing the last underscore with a hyphen).

How to remove a class from the classpath after Gradle build

I have a jar that I need to include in my dependencies...
compile files('WebContent/WEB-INF/lib/wls-api.jar')
There's a class inside that jar that is causing trouble that I want to not be on the classpath when I run my app after a gradle build.
How do I get rid of that class after doing a gradle build?
it's a bit trickier than it looks like at first blink; because you will modify the original input!
You should create a configuration for the your modified artifact (this is a proof of concept build.gradle snipplet):
apply plugin: 'java'
task filteredJar(type:Jar){
// you may use a remote artifact by configuring a separate configuration for it and using a jar from:
// configurations.theConfig.resolvedConfiguration.resolvedArtifacts
from zipTree('a.jar')
archiveName 'xx.jar'
// use standard Copy/Sync like filters here, for the example i used
include '**/Tool.class'
}
configurations {
z1
}
artifacts {
z1 filteredJar
}
dependencies {
compile project(path: getPath(), configuration: 'z1')
}
or..alternatively, and might be more preferably:
put this magic into some separate project which will repackage this jar into a usebale one.

How to generate a war file based on two subprojects

I have a project which is splitted into two subprojects.
/project
/sub-project-a (backend with JAVA source which is compiled into JAR file)
/sub-project-b (frontend sources which are compiled with grunt via gradle call)
build.gradle
settings.gradle (contains include 'sub-project-a', 'sub-project-b')
My Question is how can I create a War file with sub-projects and external lib dependencies? The following code snipped is my current build.gradle:
apply plugin: 'war'
version '1.0.0'
repositories {
mavenCentral()
}
dependencies {
compile project(':sub-project-a')
compile project(':sub-project-b')
compile 'com.google.code.gson:gson:2.2.4'
}
task copy(type: Copy) {
from 'sub-project-a/build', 'sub-project-b/build'
into 'build'
}
build.dependsOn clean, copy
war {
archiveName 'project.war'
}
One detail is important. The java context listener (deep inside project code) work with compiled backend as jar file from WEB-INF/lib folder. This means that all class files can't be easily used from WEB-INF/classes folder.
As you can see I played with dependencies and a custom copy task. I'm not sure what is right gradle way. How should I do this?
SOLUTION
Define with war.from methode, where you get your static sources.
gradle docu
from(sourcePaths) -
Specifies source files or directories for a copy. The given paths are
evaluated as per Project.files().
My changed build.gradle
apply plugin: 'war'
version '1.0.0'
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.code.gson:gson:2.2.4'
}
war {
archiveName 'project.war'
from 'sub-project-a/build/dist', 'sub-project-b/build/dist'
}
SOLUTION (for cleanly closing this question) shamefully taken from the question's originator ;-)
Define subproject dependencies with the "war.from" method, where you get your static sources.
gradle documentation excerpt: from(sourcePaths) - Specifies source files or directories
for a copy. The given paths are evaluated as per Project.files().
Ronny's changed build.gradle
apply plugin: 'war'
version '1.0.0'
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.code.gson:gson:2.2.4'
}
war {
archiveName 'project.war'
from 'sub-project-a/build/dist', 'sub-project-b/build/dist'
}

Why this gradle build script is not compiling java class?

I am trying to use Cascading in my Hadoop project. I am trying to implement first example given in Enterprise Data Workflows with Cascading book. I have written java class which contains Cascading related code and I have another build.graddle file which is supposed to compile that java class and build jar file out of it.
My folder structure is as follows :
main_folder
impatient
Main.java
build.gradle
My build.gradle file looks as below :
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'eclipse'
archivesBaseName = 'impatient'
repositories {
mavenLocal()
mavenCentral()
mavenRepo name: 'conjars', url: 'http://conjars.org/repo/'
}
ext.cascadingVersion = '2.1.0'
dependencies {
compile( group: 'cascading', name: 'cascading-core', version: cascadingVersion )
compile( group: 'cascading', name: 'cascading-hadoop', version: cascadingVersion )
}
jar {
description = "Assembles a Hadoop ready jar file"
doFirst {
into( 'lib' ) {
from configurations.compile
}
}
manifest {
attributes( "Main-Class": "impatient/Main" )
}
}
When I run gradle clean jar command from command prompt, I get build successful message. I tried to run this jar file using
hadoop jar impatient.jar <input file path> <output file path>
command but then it gives me Exception in thread "main" java.lang.ClassNotFoundException: impatient.Main exception.
So I checked contentes of jar file and found that that jar does not contain impatient/Main.class file.
Please note that I do not know anything about gradle.
Request someone to please tell me if there is anything wrong with gradle script or I am making some mistake.
Thanks !!!
Move your source file to
main_folder/impatient/src/main/java/Main.java
but leave build.gradle file where it is.
By default, Gradle uses src/main/java and src/test/java to look for production and test java sources (relative to root folder, which is impatient in your case)

Gradle multiproject gives "Could not find property 'sourceSets' on project" error

I had quite good gradle configuration, that built everything just fine. But one of the projects of my multi-project build derived from the rest of them so much, that I would gladly move it to another git repo and configure submodules to handle it.
First, I moved Project and its resources to subfolder Libraries/MovedProject. After altering some lines in gradle configurations it worked fine. But then I decided to write a new build.gradle just for this project, and move all configurations there from the main one.
And this is where everything stopped working. When I try to call any task it always ends
with Could not find property 'sourceSets' on project ':Libraries/MovedProject'. Line which is responsible for it is:
dependencies {
...
if (noEclipseTask) {
testCompile project(':Libraries/MovedLibrary').sourceSets.test.output
}
}
which I use for running tests in which I use classes from other projects. If I remove that line, the build fails only when it reaches compileTestJava task of projects that make use of MovedProject. If I remove that line and call gradle :Libraries/MovedLibrary:properties I can see :
...
sourceCompatibility: 1.7
sourceSets: [source set main, source set test]
standardOutputCapture: org.gradle.logging.internal.DefaultLoggingManager#1e263938
...
while gradle :Libraries/MovedLibrary:build builds correctly.
Currently I've got everything set up as following:
directories:
/SomeMainProject1
/SomeMainProject2
/SomeMainProject3
/Libraries
/MovedProject
build.gradle
dependencies.gradle
project.gradle
tasks.gradle
/Builder
dependencies.gradle
project.gradle
tasks.gradle
build.gradle
settings.gradle
settings.gradle
include Libraries/MovedProject,
SomeMainProject1,
SomeMainProject2,
SomeMainProject3
sourceSets for MovedProject are defined in Libraries/MovedProject/project.gradle:
sourceSets {
main {
java {
srcDir 'src'
srcDir 'resources'
}
resources { srcDir 'resources' }
}
test { java {
srcDir 'test/unit'
} }
}
dependencies that makes use of sourceSets.test.output are stored in Builder/dependancies.gradle, and set for each project that needs MovedProject to run tests:
project(':SomeMainProject1') {
dependencies {
...
if (noEclipseTask) {
testCompile project(':Libraries/net.jsdpu').sourceSets.test.output
}
}
}
What would be the easiest way to get rid of that error and make gradle build projects with current directory structure? I would like to understand why gradle cannot see that property.
The line in question is problematic because it makes the assumption that project :Libraries/MovedLibrary is evaluated (not executed) before the current project, which may not be the case. And if it's not, the source sets of the other project will not have been configured yet. (There won't even be a sourceSets property because the java-base plugin hasn't been applied yet.)
In general, it's best not to reach out into project models of other projects, especially if they aren't children of the current project. In the case of project A using project B's test code, the recommended solution is to have project B expose a test Jar (via an artifacts {} block) that is then consumed by project A.
If you want to keep things as they are, you may be able to work around the problem by using gradle.projectsEvaluated {} or project.evaluationDependsOn(). See the Gradle Build Language Reference for more information.
I had a similar error happen to me in a multimodule project, but for me the cause was as simple as I had forgotten to apply the java-library plugin within the configurations, I only had maven-publish plugin in use.
Once I added the plugin, sourceSets was found normally:
configure(subprojects) {
apply plugin: 'maven-publish'
apply plugin: 'java-library'
....

Resources