How can I get current value of CLASSPATH in Groovy?
Shameless stolen from http://blog.blindgaenger.net/print_groovys_classpath_for_debugging.html
This code will go up the classloader tree and printout each classloader and the associated classpath.
def printClassPath(classLoader) {
println "$classLoader"
classLoader.getURLs().each {url->
println "- ${url.toString()}"
}
if (classLoader.parent) {
printClassPath(classLoader.parent)
}
}
printClassPath this.class.classLoader
You should be able to get the classpath from the SystemClassLoader, providing it is an URLClassLoader:
URL[] classPathUrls = ClassLoader.getSystemClassLoader().getURLs();
java.class.path doesn't work properly, at least in Groovy 2.1.6 (Mac OS X 10.6.8).
HelloWorld.groovy:
public class HelloWorld {
public static void main(def args) {
System.out.println( "Hello, world!\n");
System.out.println(System.getenv("CLASSPATH")+"\n");
System.out.println(System.getProperty("java.class.path"));
}
}
Then
export CLASSPATH=/etc
groovy -classpath /usr HelloWorld.groovy
Result:
Hello, World!
/etc
/Applications/groovy-2.1.6/lib/groovy-2.1.6.jar
Now, this is HelloWorld.java: (I had to change it a bit as Groovy and Java are not 100% compatible):
public class HelloWorld {
public static void main(String args[]) {
System.out.println( "Hello, world!\n");
System.out.println(System.getenv("CLASSPATH")+"\n");
System.out.println(System.getProperty("java.class.path"));
}
}
Now:
javac HelloWorld.java
export CLASSPATH=/etc
java -classpath /usr HelloWorld
Result:
Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld
Caused by: java.lang.ClassNotFoundException: HelloWorld
etc. ...................
Then:
java -classpath /usr:. HelloWorld
Result:
Hello, world!
/etc
/usr:.
I'll update if I find out how to make it work in Groovy...
Get the CLASSPATH and files if you want in the those CLASSPATH if needed you can view it
System.getProperty("java.class.path", ".").tokenize(File.pathSeparator).each {
println it
}
This doesn't work?
System.getProperty('java.class.path')
def classpath = System.properties["java.class.path"]
Related
How to configure dagger to inject groovy classes, and to inject into groovy classes?
I was initially trying to get dagger to inject a groovy class into my java app, and I found dagger was complaining the groovy class is not found. Looking at the log, it seems that compileGroovy happens after compileJava. And the annotation processing of dagger compiler seems to be in compileJava. I guessed that might be the problem -- no groovy classes are available at this time. But I've yet figured out a way to coerce either of dagger or groovy to work with the other.
It seems I could not upload a .tar.gz. But if anyone needs a minimal demo code for what I meant to achieve, these might help (with gradle 7):
build.gradle:
plugins {
id 'groovy'
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
annotationProcessor 'com.google.dagger:dagger-compiler:2.+'
implementation 'com.google.dagger:dagger:2.+'
implementation 'org.codehaus.groovy:groovy-all:3.+'
}
settings.gradle:
rootProject.name = 'groovy-dagger1'
src/main/groovy/org/example/dagger/MainComponent.groovy:
package org.example.dagger
import dagger.Component
#Component(modules = [
MainModule,
])
interface MainComponent {
String message();
}
src/main/groovy/org/example/dagger/MainModule.groovy:
package org.example.dagger
import dagger.Module
import dagger.Provides
#Module
final class MainModule {
#Provides
static String message() {
return 'Hello Groovy Dagger!'
}
}
src/main/groovy/org/example/main/Main.groovy:
package org.example.main;
class Main {
static void main(String[] args) {
// Dagger component does not exist :/
// println DaggerMainComponent.create().message()
}
}
By default, the groovy compiler will not run the java annotation processors...
You can add this to your build.gradle:
compileGroovy {
groovyOptions.javaAnnotationProcessing = true
}
You will of course need to add an import
import org.example.dagger.DaggerMainComponent
To Main.groovy
leftShift is deprecated in Gradle now.
I am trying to add a java class initialization inside the gradle build file like below:
task javaClassInGradleTask {
doLast {
class Myclass {
public void message() {
System.out.println("this is message from java class");
}
}
Myclass testObject = new Myclass();
testObject.message();
}
}
and I am trying to run the file:
gradle javaClassInGradleTask
My error result is below
FAILURE: Build failed with an exception.
* Where:
Build file '/Users/folder/build.gradle' line: 3
What went wrong:
Could not compile build file '/Users/folder/build.gradle'.
startup failed:
build file '/Users/folder/build.gradle': 3: Class definition not expected here. Please define the class at an appropriate place or perhaps try using a block/Closure instead. at line: 3 column: 2. File: BuildScript # line 3, column 2.
class Myclass {
^
1 error
Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
Get more help at https://help.gradle.org
BUILD FAILED in 0s
But when I try to add the class using leftShift it works well.
Any idea to add class inside the gradle file?
It doesn't work for both doLast and <<. Try:
task javaClassInGradleTask {
doLast {
Myclass testObject = new Myclass()
testObject.message();
}
}
class Myclass {
public void message() {
System.out.println("this is message from java class");
}
}
I have couple of OSGi bundles; am spinning a thread in one bundle and inside the run method, I am trying to create instance of a class from another bundle but it just fails, throws ClassNotFoundException
Bundle 1:
package com.test.bnd1;
public Class A {
}
pom.xml :
Export-package: com.test.bnd1.*
Bundle 2:
public com.test.bnd2;
public Class B {
public void init() {
MyThd thd = new MyThd();
thd.start();
}
}
public Class MyThd extends Thread {
public void run() {
A a = new A(); //throws ClassNotFoundException
}
}
pom.xml :
Import-package: com.test.bnd1.*
blueprint.xml:
<bean id="testB" class="com.test.bnd2.B" init-method="init"/>
Can someone help?
There are no headers in OSGi called exports-package or imports-package.
You need to use Export-Package and Import-Package respectively.
After reading this article I have reset the current thread's TCCL to the bundle class loader and got the classes from other bundles loaded. If anyone else has a better solution, please let me know.
I need to make a standalone Groovy script that does not require compilation and runs without Groovy installed. It works well, but it fails to recognize any other script than the main script.
My folder structure is the following:
libs\
groovy-all-2.4.3.jar
ivy-2.4.0.jar
src\
makeRelease.groovy
ReleaseHelper.groovy
I am launching the script this way from the src folder:
java -cp "../libs/*" makeRelease.groovy
makeRelease looks like this:
public class makeRelease {
public static void main(String... args) {
new ReleaseHelper()
...
}
}
When run this is the output:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
src\makeRelease.groovy: 5: unable to resolve class ReleaseHelper
How can I include other classes (that reside in separate files) in such portable scripts?
I think that it is easier than you think:
libs\
groovy-all-2.4.3.jar
src\
main.groovy
Greeter.groovy
Where main.groovy
public class Main {
public static void main(args) {
println 'Main script starting...'
def greeter = new Greeter()
greeter.sayHello()
}
}
and Greeter.groovy
class Greeter {
def sayHello() {
println 'Hello!'
}
}
Simply add to the classpath the folders where you have the classes in separate files:
java -cp .;..\libs\groovy-all-2.4.3.jar groovy.ui.GroovyMain main.groovy
The above yields:
Main script starting...
Hello!
I am trying to come up with a way for my users to supply plugins into the main groovy application by dynamically loading their source file. But their groovy file contains import statements and I don't know how to make them work even with an apparently good classpath.
The main application is a shell script, bin/top.sh:
#!/bin/bash
groovy-2.4.1/bin/groovy -cp lib lib/Top.groovy
The lib/Top.groovy class:
public class Top {
public static void main(String[] args) {
ClassLoader parent = getClass().getClassLoader()
GroovyClassLoader loader = new GroovyClassLoader(parent)
Class groovyClass = loader.parseClass(new File("UserPlugin.groovy"))
GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance()
groovyObject.invokeMethod("run",args)
}
}
The user class UserPlugin.groovy:
// The following import can be found in the classpath
// passed by the shell script (under lib/, next to Top.groovy)
import Lib
class UserPlugin {
def UserPlugin() {
Lib lib = new Lib()
}
def run(String [] args) {
println("Running with: "+args)
}
}
And the lib/Lib.groovy:
class Lib {
def Lib() {
println("Lib")
}
}
When I run with bin/top.sh, I get: UserPlugin.groovy: 3: unable to resolve class Lib
When I add lib to the class loader like so loader.addClasspath('lib'), it's rather catastrophic:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
General error during class generation: java.lang.NoClassDefFoundError: groovy/lang/GroovyObject
java.lang.RuntimeException: java.lang.NoClassDefFoundError: groovy/lang/GroovyObject
at org.codehaus.groovy.control.CompilationUnit.convertUncaughtExceptionToCompilationError(CompilationUnit.java:1088)
How can this work while keeping it all scripted and not compiled? Is this even possible?
Sorry I don't have time to find the bug but I think the problem is with the setting of the context classloader. GroovyShell.run takes care of that for you which I recommend over replicating that code.
Top.groovy
public class Top {
public static void main(String[] args) {
new GroovyShell().run(new File("UserPlugin.groovy"), args)
}
}
If you're willing to make Top.groovy a script rather than class then you can do this:
Top.groovy
run(new File("UserPlugin.groovy"), args)
The UserPlugin.groovy then needs to be either a class (with a main method) or a script to use the standard Groovy calling logic.