Groovy - How to Build a Jar - groovy

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.

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

Which directory contains third party libraries for Spark

When we use
spark-submit
which directory contains third party libraries that will be loaded on each of the slaves? I would like to scp one or more libraries to each of the slaves instead of shipping the contents in the application uber-jar.
Note: I did try adding to
$SPARK_HOME/lib_managed/jars
But the spark-submit still results in a ClassNotFoundException for classes included in the added library.
Hope these points will help you.
$SPARK_HOME/lib/ [contains the jar files ]
$SPARK_HOME/bin/ [contains the launch scripts - Spark-Submit,Spark-Class,pySpark,compute-classpath.sh etc]
Spark-Submit ---will call ---> Spark-Class.
Spark-class internally calls compute-Classpath.sh before executing / launching the job.
compute-Classpath.sh will pick the jars availble in $SPARK_HOME/lib to CLASSPATH.
(execute ./compute-classpath.sh //returns jars in lib dir)
So try these options.
option-1 - Placing user-specific-jars in $SPARK_HOME/lib/ will works
option-2 - Tweak compute-classpath.sh so that it will be able to pic
your jars specified in a user specific jars dir

Error loading Groovy config file from JAR

I have an application that is running on compiled Groovy code in a jar.
The groovy code is all being loaded/executed correctly, however, I have a step that attempts to load a groovy-config file from the root of the JAR, but it is failing.
The code below is from a groovy class that is being run from the JAR, and here it attempts to load the groovy config file config.props from the root of the jar:
URL url = this.getClass().getClassLoader().getResource("config.props")
logger.info( url.toString() )
if(!url)throw new IllegalArgumentException("'$resource' not found ")
GroovyScriptEngine gse = new GroovyScriptEngine( url )
...
gse.run(url.file, binding)
When I run the above I get the following error:
Message: Cannot open URL: jar:file:/usr/local/libs/test-all.jar!/config.props
Does anyone have any idea how to load a file from a root of a jar? I have temporarily set the permissions to 777 and have checked that the file exists/spelling correct.
Ok - I think I have resolved this.
It looks like the error was in
gse.run(url.file, binding)
the url.file passed the full absolute path including file: protocol to the gse - I changed this to just "config.props" and it seemed to have got past this (there is another error now, but seems to be further on).

Create multiple .WAR files with different dependencies in Gradle

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.

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

Resources