Error loading Groovy config file from JAR - groovy

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).

Related

groovy configslurper Environment No such property when compiled to jar

I'm having a trouble reading an environment configuration stored in a .groovy script from a jar created as a compiled version of my main script. The script version runs fine. The "sandbox3" reference in the error message refers to an environment defined in the config file. This it the error message I get:
server_control_web_services>runobiadmin2 -e sandbox3
Caught: groovy.lang.MissingPropertyException: No such property: sandbox3 for class: script_from_command_line
groovy.lang.MissingPropertyException: No such property: sandbox3 for class: script_from_command_line
at script_from_command_line.run(script_from_command_line:1)
Groovy 2.4.5
When running the original script the code below behaves as expected setting config to the environment passed from the command line. obieeadmincfg.groovy is located in the same directory as the jar file.
URL url = OBIEEAdmin.class.getClassLoader().getResource('obieeadmincfg.groovy')
config = new ConfigSlurper(opt.e).parse(url)

An activeweb-bootstrap can not find controller

I dowloaded the ActiveWeb Bootstrap project from gtihub and have troubles with it.
First, it was imposssible to import it into Eclipse so I executed mvn eclipse:eclipse and then imported the project into eclipse and converted it to maven.
Then I started jetty server from Eclipse and I got an error with path http://localhost:8080/activeweb-bootstrap/
URI Full Path: /activeweb-bootstrap/
URI Path: /activeweb-bootstrap/
Method: GET
org.javalite.activeweb.ClassLoadException: java.lang.ClassNotFoundException: app.controllers.ActivewebBootstrapController
at org.javalite.activeweb.DynamicClassFactory.getCompiledClass(DynamicClassFactory.java:62)
at org.javalite.activeweb.DynamicClassFactory.createInstance(DynamicClassFactory.java:23)
at org.javalite.activeweb.ControllerFactory.createControllerInstance(ControllerFactory.java:27)
at org.javalite.activeweb.Router.recognize(Router.java:80)
at org.javal
I was able to run this project properly only when export it as war file. Why I get this error if start the project with Jetty from Eclipse?
updated:
62406 [qtp31348584-11] WARN org.javalite.activeweb.RequestDispatcher - ActiveWeb 404 WARNING:
Request URL: http://localhost:8080/activeweb-bootstrap/
ContextPath:
Query String: null
URI Full Path: /activeweb-bootstrap/
URI Path: /activeweb-bootstrap/
Method: GET
org.javalite.activeweb.ClassLoadException: java.lang.ClassNotFoundException: app.controllers.ActivewebBootstrapController
62406 [qtp31348584-11] WARN org.javalite.activeweb.ParamCopy - found 'session' value set by controller. It is reserved by ActiveWeb and will be overwritten.
62438 [qtp31348584-11] INFO org.javalite.activeweb.freemarker.FreeMarkerTemplateManager - Rendered template: '/system/404' with layout: '/layouts/default_layout'
Apparently this example had an old version of a dependency. Please, clone and try again. It is fixed already.
ANSWER UPDATE:
The link on the README.md file was incorrect. The project is mapped to root, so instead of accessing http://localhost:8080/activeweb-bootstrap/, you need to access:
http://localhost:8080/.
The README.md file was updated accordingly: https://github.com/javalite/activeweb-bootstrap
The message you are getting:
org.javalite.activeweb.ClassLoadException: java.lang.ClassNotFoundException: app.controllers.ActivewebBootstrapController
is perfectly valid, since the framework is trying to interpret your URI: "activeweb-bootstrap" as a route to controller app.controllers.ActivewebBootstrapController.
Such controller does not exist, so you get a 404.

Unable to load so file from Java in Eclipse On Ubuntu

I have some code that tries to load a C library as follows :-
public ThreadAffinity() {
ctest = (CTest) Native.loadLibrary("ctest", CTest.class);
}
However I get the following error when trying to build the project; The error I get is as follows :-
UnsatisfiedLinkError: Unable to load library 'libctest': liblibctest.so: cannot open shared object file: No such file or directory
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:166)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:239)
at com.sun.jna.Library$Handler.<init>(Library.java:140)
at com.sun.jna.Native.loadLibrary(Native.java:393)
at com.sun.jna.Native.loadLibrary(Native.java:378)
at com.threads.ThreadAffinity.<init>(ThreadAffinity.java:11)
at com.threads.ThreadAffinity.main(ThreadAffinity.java:45)
The current working directory is the root of the project and thats where the so file is located. I also tried modifying the LD_PRELOAD variable to point to my so file; however the error persists.
It works just fine on my OSX where the dylib is located exactly where the so file is currently(project root).
What am I doing wrong?
From the exception:
UnsatisfiedLinkError: Unable to load library 'libctest': liblibctest.so: cannot open shared object file: No such file or directory
It implies you used something like:
public ThreadAffinity() {
ctest = (CTest) Native.loadLibrary("libctest", CTest.class);
}
and not:
public ThreadAffinity() {
ctest = (CTest) Native.loadLibrary("ctest", CTest.class);
}
hence you see the JNA added prefix of lib and postfix of .so added to libctest (liblibctest.so)
LD_PRELOAD is used when you want to prefer one particular version of the same shared library over another, which doesn't apply here.
Define jna.library.path to point to your project root, and JNA should be able to find it.
Also make sure your library has been built as libctest.so and wasn't inadvertently named libctest.dylib.

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.

How do you get the path of the running script in groovy?

I'm writing a groovy script that I want to be controlled via a properties file stored in the same folder. However, I want to be able to call this script from anywhere. When I run the script it always looks for the properties file based on where it is run from, not where the script is.
How can I access the path of the script file from within the script?
You are correct that new File(".").getCanonicalPath() does not work. That returns the working directory.
To get the script directory
scriptDir = new File(getClass().protectionDomain.codeSource.location.path).parent
To get the script file path
scriptFile = getClass().protectionDomain.codeSource.location.path
As of Groovy 2.3.0 the #SourceURI annotation can be used to populate a variable with the URI of the script's location. This URI can then be used to get the path to the script:
import groovy.transform.SourceURI
import java.nio.file.Path
import java.nio.file.Paths
#SourceURI
URI sourceUri
Path scriptLocation = Paths.get(sourceUri)
Note that this will only work if the URI is a file: URI (or another URI scheme type with an installed FileSystemProvider), otherwise a FileSystemNotFoundException will be thrown by the Paths.get(URI) call. In particular, certain Groovy runtimes such as groovyshell and nextflow return a data: URI, which will not typically match an installed FileSystemProvider.
This makes sense if you are running the Groovy code as a script, otherwise the whole idea gets a little confusing, IMO. The workaround is here: https://issues.apache.org/jira/browse/GROOVY-1642
Basically this involves changing startGroovy.sh to pass in the location of the Groovy script as an environment variable.
As long as this information is not provided directly by Groovy, it's possible to modify the groovy.(sh|bat) starter script to make this property available as system property:
For unix boxes just change $GROOVY_HOME/bin/groovy (the sh script) to do
export JAVA_OPTS="$JAVA_OPTS -Dscript.name=$0"
before calling startGroovy
For Windows:
In startGroovy.bat add the following 2 lines right after the line with
the :init label (just before the parameter slurping starts):
#rem get name of script to launch with full path
set GROOVY_SCRIPT_NAME=%~f1
A bit further down in the batch file after the line that says "set
JAVA_OPTS=%JAVA_OPTS% -Dgroovy.starter.conf="%STARTER_CONF%" add the
line
set JAVA_OPTS=%JAVA_OPTS% -Dscript.name="%GROOVY_SCRIPT_NAME%"
For gradle user
I have same issue when I'm starting to work with gradle. I want to compile my thrift by remote thrift compiler (custom by my company).
Below is how I solved my issue:
task compileThrift {
doLast {
def projectLocation = projectDir.getAbsolutePath(); // HERE is what you've been looking for.
ssh.run {
session(remotes.compilerServer) {
// Delete existing thrift file.
cleanGeneratedFiles()
new File("$projectLocation/thrift/").eachFile() { f ->
def fileName=f.getName()
if(f.absolutePath.endsWith(".thrift")){
put from: f, into: "$compilerLocation/$fileName"
}
}
execute "mkdir -p $compilerLocation/gen-java"
def compileResult = execute "bash $compilerLocation/genjar $serviceName", logging: 'stdout', pty: true
assert compileResult.contains('SUCCESSFUL')
get from: "$compilerLocation/$serviceName" + '.jar', into: "$projectLocation/libs/"
}
}
}
}
One more solution. It works perfect even you run the script using GrovyConsole
File getScriptFile(){
new File(this.class.classLoader.getResourceLoader().loadGroovySource(this.class.name).toURI())
}
println getScriptFile()
workaround: for us it was running in an ANT environment and storing some location parent (knowing the subpath) in the Java environment properties (System.setProperty( "dirAncestor", "/foo" )) we could access the dir ancestor via Groovy's properties.get('dirAncestor').
maybe this will help for some scenarios mentioned here.

Resources