Create multiple .WAR files with different dependencies in Gradle - groovy

I am using the war plugin to generate a simple .WAR file for my project in gradle. I'd like to know how to configure gradle so that I can create 4 different .WAR files with different dependencies.
I've configured the dependency compile configuration with the jars that are needed to go into the distribution. None of the code in the src depends on a couple of these jars but I would like to know how to configure the project to create
a standard.WAR file that contains all of the jars in the dependency graph (Even though they aren't used - that is OK - I am testing something)
another standard-qas-only.WAR file that only contains the qas.jar
another standard-qas-log4j.WAR file that contains qas.jar and log4j
What tasks do i configure to have the artifact generated use a particular dependency configuration?
FYI: The only jar that is required for compilation is qas.jar in this case.
My example below creates a war file that only includes one jar but i'd like to have 5 different .war files generated with different jars.
build.gradle
apply plugin: 'java'
apply plugin: 'war'
dependencies {
compile files('/lib/qas.jar','/lib/axis1-1.4.jar','/lib/axis2-kernel-1.3.jar','/lib/dom4j-1.6.1.jar','/lib/log4j-1.2.14.jar')
providedCompile files('/lib/j2ee-1.4.03.jar')
}
war {
classpath = ['/lib/qas.jar']
}
task dist(dependsOn: 'war') << {
copy {
from war.archivePath
into "dist/"
}
}

I got a bit confused on how many WAR distributions you are actually trying to build. You can easily modify it to create additional WAR files. Here's one approach to make this happen:
task createStandardWar(type: War, dependsOn: classes) {
baseName = 'standard'
destinationDir = file("$buildDir/dist")
}
task createStandardWarQasOnly(type: War, dependsOn: classes) {
baseName = 'standard-qas-only'
destinationDir = file("$buildDir/dist")
classpath = war.classpath.minus(files('/lib/axis1-1.4.jar','/lib/axis2-kernel-1.3.jar','/lib/dom4j-1.6.1.jar','/lib/log4j-1.2.14.jar'))
}
task createStandardWarQasAndLog4J(type: War, dependsOn: classes) {
baseName = 'standard-qas-log4j'
destinationDir = file("$buildDir/dist")
classpath = war.classpath.minus(files('/lib/axis1-1.4.jar','/lib/axis2-kernel-1.3.jar','/lib/dom4j-1.6.1.jar'))
}
task createDists(dependsOn: [createStandardWar, createStandardWarQasOnly, createStandardWarQasAndLog4J])
This build script excerpt creates three different WAR files by declaring enhanced tasks of type War. It assumes that you still want to have your compiled source files under WEB-INF/classes within the WAR files so I didn't remove it from the classpath. The distributions end up in the directory build/dist. The task createDists creates all of them.

Related

can we import the specified classes jar file from another mincroanut project to an micronaut project

I have 2 micronaut (groovy ) projects , called project A and project B
Project B has controllers and services ( package com.service , com.controller )
but I only created jar from package com.service
the code in com.service package has #Singleton annotation and #Scheduled
and I has enabled annotation processing as link (https://docs.micronaut.io/latest/guide/index.html#ideaSetup) to both projects
please see my gradle code below to generate JAR file ( the output file is project-b-libs-0.x.jar)
task createLibraryJar(type: Jar) {
baseName( getArchivesBaseName() + "-libs")
from sourceSets.main.output
includeEmptyDirs = false
include '**/service/**/*.class'
}
Then I added proejct-b-libs-0.x.jar to Project A
The gradle's dependencies are below
dependencies {
annotationProcessor "io.micronaut:micronaut-inject-java"
implementation("io.micronaut:micronaut-validation")
implementation("io.micronaut.groovy:micronaut-runtime-groovy")
implementation("javax.annotation:javax.annotation-api")
implementation("io.micronaut:micronaut-http-client")
runtimeOnly("ch.qos.logback:logback-classic")
compileOnly files('libs/project-b-libs-0.4.jar')
compile "io.micronaut:micronaut-inject"
}
Finally after I tried call #Inject Object from the class in JAR file, it showed error on run time
Caused by: io.micronaut.context.exceptions.BeanContextException: Error
loading bean [com.service.TestService]:
com/service/StripePaymentService
Project A has com.service.TestService to call com.service.StripePaymentService which is in JAR file
Sorry for my English and Thank you to trying to understand me
compile files('libs/project-b-libs-0.4.jar')
I just use compile , not compileOnly , and can not use jar file from gralde script above when I extract jar file , some mincronaut's stuff is missing
so I try another gradle task's script as below ( change from include to exclude )
task createLibraryJar(type: Jar) {
baseName( getArchivesBaseName() + "-libs")
from sourceSets.main.output
includeEmptyDirs = false
exclude '**/controller/**/*.class'
}
and it works because the micronaut's stuff still in JAR file, I only exclude unnecessary classes from my jar file

Create a Groovy executable jar with Spock test set as to be executed

I want to create jar with two groovy files, AppLogic.groovy which consists of two few groovy classes and another file, AppSpec that has Spock test suite and I would like to have this Spock class executed (set as executable). How can I create such jar with all dependencies? I found sth similar for jUnit here: how to export (JUnit) test suite as executable jar but could not adapt it for my needs.
I use gradle for build, here is my build.gradle file:
group 'someGroup'
version '1.0'
apply plugin: 'groovy'
apply plugin: 'java'
apply plugin:'application'
sourceCompatibility = 1.7
repositories {
//some repos here
maven { url "http://repo.maven.apache.org/maven2" }
}
dependencies {
//some dependencies here
}
I was browsing around and found SpockRuntime, but I do not know if and how I can use it to achive my goal.
And the winner is:
static void main(String[] args) {
EmbeddedSpecRunner embeddedSpecRunner = new EmbeddedSpecRunner()
embeddedSpecRunner.runClass(MySpec)
}
I do not advise using the EmbeddedSpecRunner from spock implementation as described in accepted answer.
This is what I found to work reliably with gradle 4.9. The basic approach is to use:
The gradle application plugin to create a single tarfile with all testRuntimeClasspath dependencies and shell scripts to run the spock tests
The gradle maven-publish plugin to publish the tar file as an artifact to your maven repo (in my case nexus)
The build.gradle file looks like this:
apply plugin: 'java'
apply plugin: 'groovy'
apply plugin: 'maven-publish'
apply plugin: 'application'
mainClassName = 'org.junit.runner.JUnitCore' // The junit 4 test runner class
applicationName = 'run-tests-cli' // Feel free to change
repositories {
...
}
dependencies {
...
testImplementation "org.codehaus.groovy:groovy-all:${groovyVersion}"
testImplementation "org.spockframework:spock-core:${spockVersion}"
}
// Package compiled spock / junit tests to <artifact>-test-<version>.jar
task testJar(type: Jar) {
classifier = 'tests'
from sourceSets.test.output.classesDirs
}
// Copy all testRuntimeClasspath dependencies to libs folder
task copyToLibs(type: Copy) {
from configurations.testRuntimeClasspath
into "$buildDir/libs"
}
// Make sure test jar is copied
copyToLibs.dependsOn('testJar')
// Make sure platform-specific shell scripts are created after copyToLibs
startScripts.dependsOn(copyToLibs)
// Configure what goes into the tar / zip distribution file created by gradle distribution plugin assembleDist task
distributions {
main {
contents {
// Include test jar
from(testJar) {
into "lib"
}
// Include all dependencies from testRuntimeClasspath
from(copyToLibs) {
into "lib"
}
}
}
}
startScripts {
// Ensure ethat all testRuntimeClasspath dependencies are in classpath used by shell scripts
classpath = project.tasks['testJar'].outputs.files + project.configurations.testRuntimeClasspath
}
publishing {
repositories {
maven {
def releasesRepoUrl = "https://nexus.yourcompany.com/repository/maven-releases/"
def snapshotsRepoUrl = "https://nexus.yourcompany.com/repository/maven-snapshots/"
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
credentials {
username = rootProject.getProperty('NEXUS_USERNAME')
password = rootProject.getProperty('NEXUS_PASSWORD')
}
}
}
publications {
maven(MavenPublication) {
groupId = 'com.yourgroupId'
version = "${rootProject.getVersion()}"
}
TestJar(MavenPublication) {
artifact(testJar)
}
RunTestsCliTar(MavenPublication) {
artifact(distTar)
artifactId "${applicationName}"
}
}
}
Now you can do the following:
To build the project (including the tar file) without running test task: gradle -x test clean build
To publish artifacts produced by project (including tar file to maven repo - in my case nexus): gradlew -x test publish. Note you will need to provide credentials to upload artifacts to repo. It is good practice to define them (NEXUS_USERNAME, NEXUS_PASSWORD in my example) in ~/.gradle/gradle.properties or specify them via -P options on the gradle command line.

Groovy - How to Build a Jar

I've written a Groovy script which has a dependency on a SQL Server driver (sqljdbc4.jar). I can use the GroovyWrapper (link below) to compile it into a JAR, however how can I get dependencies into the Jar? I'm looking for a "best practice" sort of thing.
https://github.com/sdanzan/groovy-wrapper
Both of the replies below have been helpful, but how can I do this for signed Jar files? For instance:
Exception in thread "main" java.lang.SecurityException: Invalid signature file d
igest for Manifest main attributes
In the groovy wrapper script, you'll see this line near the bottom:
// add more jars here
That's where you can add your dependencies. If the jar file is in the same directory you're building from, add a line like this:
zipgroupfileset( dir: '.', includes: 'sqljdbc4.jar' )
Then rerun the script and your jar will include the classes from sqljdbc4.jar.
Edit:
If the jar file you depend on is signed and you need to maintain the signature, you'll have to keep the external jar. You can't include jar files inside of other jar files without using a custom classloader. You can, however, specify the dependency in the manifest to avoid having to set the classpath, i.e. your jar still executable with java -jar myjar.jar. Update the manifest section in the wrapping script to:
manifest {
attribute( name: 'Main-Class', value: mainClass )
attribute( name: 'Class-Path', value: 'sqljdbc4.jar' )
}
From your link, if you look at the source of the GroovyWrapper script, there's this line:
zipgroupfileset( dir: GROOVY_HOME, includes: 'embeddable/groovy-all-*.jar' )
zipgroupfileset( dir: GROOVY_HOME, includes: 'lib/commons*.jar' )
// add more jars here
I'd explicitly add it there.

Gradle zip packaging: copy Jar file from repository

I have to copy a jar from the repository (say local) in my ZIP packaging. I understand that we can define compile/runtime in dependencies. However, I could not use it them in ZIP.
I'm able to copy the jar file by specifying the path in my filesystem. However, I don't know how to do it from repository.
Here is how my code looks like:
task createZipFile (type: Zip, dependsOn: [...]) {
baseName 'xyz'
from(fileTree("src/main"), {
include "prjName/css/**"
include "prjName/images/**"
include "prjName/javascript/**"
include "prjName/WEB-INF/**"
exclude "prjName/WEB-INF/web.xml"
})
from file("<Absolute-path-to-jar-file-in-my-filesystem>") //this works
// how to copy the same jar file from repository ??
}
Assuming your dependencies are in the runtime configuration ie:
runtime 'org.slf4j:slf4j-log4j12:1.6.2'
you can do:
task createZipFile( type: Zip, dependsOn: [...] ) {
baseName 'xyz'
from fileTree("src/main"), {
include "prjName/css/**"
include "prjName/images/**"
include "prjName/javascript/**"
include "prjName/WEB-INF/**"
exclude "prjName/WEB-INF/web.xml"
}
from configurations.runtime.files { it.name == 'slf4j-log4j12' }
}
To add all jars downloaded for the dependency with the name slf4j-log4j12
To specify a specific jar without its dependencies, qualify it with "#jar". E.g.
"commons-beanutils:commons-beanutils:1.6#jar"
For an example that explains how to reference a set of jars using a custom configuration, see Download some dependencies and copy them to a local folder

How can I create a pathing jar in Gradle

When running groovyc in a Windows env, I am running into issues due to the length of the classpath, in my situation. I would like to work around this by creating a pathing jar, and then put that jar on the cp. How can I create a pathing jar w/ all of the classpath entries specified automatically in gradle and then add that jar to the cp?
Here is a tested solution:
task pathingJar(type: Jar) {
appendix = "pathing"
doFirst {
manifest {
attributes "Class-Path": configurations.compile.files.join(" ")
}
}
}
compileGroovy {
dependsOn(pathingJar)
classpath = files(pathingJar.archivePath)
}
Depending on your exact requirements, you might have to tweak this a bit. For example, if you have tests written in Groovy, you will also need a pathing Jar for the test compile class path. In this case you'll need to repeat above configuration as follows:
task testPathingJar(type: Jar) {
appendix = "testPathing"
doFirst {
manifest {
attributes "Class-Path": configurations.testCompile.files.join(" ")
}
}
}
compileTestGroovy {
dependsOn(testPathingJar)
classpath = files(testPathingJar.archivePath)
}
I finally got the "pathing jar" idea to work. I consider this to be a permanent workaround. This could be considered a solution if it is made part of gradle itself.
The original pathing jar code was provided by Peter, but it didn't work. The problem: classpath elements referenced in the pathing jar must be relative to the location of the pathing jar. So, this appears to work for me.
task pathingJar(type: Jar , dependsOn: 'cleanPathingJar') {
/**
* If the gradle_user_home env var has been set to
* C:\ on a Win7 machine, we may not have permission to write the jar to
* this directory, so we will write it to the caches subdir instead.
* This assumes a caches subdir containing the jars
* will always exist.
*/
gradleUserHome = new File(gradle.getGradleUserHomeDir(), "caches")
relativeClasspathEntries = configurations.compile.files.collect {
new File(gradleUserHome.getAbsolutePath()).toURI().
relativize(new File(it.getAbsolutePath()).toURI()).getPath()
}
appendix = "pathing"
destinationDir = gradleUserHome
doFirst {
manifest {
attributes "Class-Path": relativeClasspathEntries.join(" ")
}
}
}
compileGroovy {
dependsOn(pathingJar)
classpath = files(pathingJar.archivePath)
}
This is what helped me:
"The filename or extension is too long error" using gradle
In other words: use the com.github.ManifestClasspath plugin.
The other solutions did not work for me because the actual project main class ended up no being included in the classpath at execution time.

Resources