How to declare a Groovy class in one file and use it in a Groovy script in another file? - groovy

After reading many threads I am stuck on this very simple task.
I have a sandbox project with only two files :
src/main/groovy/classes/foo
package classes.foo
class Foo{
#Override
String toString() {
return "Foo"
}
}
and src/main/groovy/scripts/script.groovy
package scripts
import classes.Foo
def foo = new Foo()
print foo.toString()
Now if I run the command :
groovy src/main/groovy/scripts/script.groovy
I get the following error :
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
src\main\groovy\scripts\utils\script.groovy: 3: unable to resolve class classes.Foo
# line 3, column 1.
import classes.Foo
^
1 error
How can I use my class Foo in my script script.groovy ?

As suggested by dagget, I had to specify the classpath based on my root folder which in my case is groovy :
groovy -cp src/main/groovy src/main/groovy/scripts/script.groovy

Related

Groovy importing static nested classes

The following two classes in the same package:
Imported.groovy
class Imported {
static class Inner {
}
}
Main.groovy
import Imported
class Main {
static main(args) {
new Imported.Inner()
}
}
When run:
$ groovy Main.groovy
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
/tmp/Main.groovy: 5: unable to resolve class Imported.Inner
# line 5, column 5.
new Imported.Inner()
^
1 error
Any reason this is happening? How to properly import static nested classes?
Just compile Imported.groovy: groovyc Imported.groovy so that you have Imported.class and Imported$Inner.class.
Then simply invoke groovy Main.groovy and it should work.
If you want to have some "import/include" functionality, check Including a groovy script in another groovy and how to simply import a groovy file in another groovy script.

opennlp.groovy has NullPointerException

I am trying to get the following code snippet from GitHub to work so that I can use OpenNLP tools in Groovy scripts.
(OpenNLP class from https://gist.github.com/nagaimasato/1178725)
#!/usr/bin/env groovy
#Grapes(
#Grab(
group='org.apache.opennlp',
module='opennlp-tools',
version='1.5.3'
)
)
import opennlp.tools.tokenize.*
import opennlp.tools.postag.*
OpenNLP nlp = new OpenNLP()
def tokens = nlp.workTokenize("Hello world")
println tokens
class OpenNLP {
static TokenizerModel tokenizerModel
static POSModel posModel
static {
def classLoader = OpenNLP.class.classLoader
classLoader.getResource('opennlp/en-token.bin').withInputStream {
tokenizerModel = new TokenizerModel(it)
}
classLoader.getResource('opennlp/en-pos-maxent.bin').withInputStream {
posModel = new POSModel(it)
}
}
Tokenizer tokenizer
POSTagger tagger
OpenNLP() {
tokenizer = new TokenizerME(tokenizerModel)
tagger = new POSTaggerME(posModel)
}
List workTokenize(String text) {
return tokenizer.tokenize(text)
}
List posTag(List tokens) {
return [tokens, tagger.tag(tokens)].transpose()
}
}
I get the following error when I try to run the script:
Caught: java.lang.ExceptionInInitializerError
java.lang.ExceptionInInitializerError
at Greetings.class$(Greetings.groovy)
at Greetings.$get$$class$OpenNLP(Greetings.groovy)
at Greetings.run(Greetings.groovy:13)
Caused by: java.lang.NullPointerException: Cannot invoke method withInputStream() on null object
at OpenNLP.<clinit>(Greetings.groovy:25)
... 3 more
I have en-token.bin and en-pos-maxent.bin in the right place for the script to find, but classLoader.getResource("opennlp/en-token.bin") is indeed null when I print it. Any ideas?
Make sure the en-token.bin and en-pos-maxent.bin files are in a directory named opennlp and that the classpath includes the parent directory of opennlp.
Note that ./ is included in the classpath when you execute your Groovy script, so if you have your opennlp directory in the same directory as your Groovy script and you also invoke the Groovy script while you are in that directory, it should work (at least it worked for me). But if you execute the script while you are not currently in that directory (e.g. by using a path like path/to/script.groovy) it won't work. In that case, you can just invoke it using groovy -cp path/to path/to/script.groovy, thus putting the parent directory of your opennlp directory into the classpath manually.

How to "include" common methods in groovys

I have developed a number of groovys used as plugins by Serviio.
Many of the methods used by these plugins are common, but when changes are made, each plugin needs to be updated. Therefore I want to "include" those methods in each plugin from a tools.groovy. I have tried 2 different approaches suggested in other posts.
I tried using
evaluate(new File("C:\\Program Files\\Serviio\\plugins\\tools.groovy"))
at the start of each plugin where tools.groovy just has
class Tools{method1{return}method2{return}}
but when executing the plugin I get
Caught: groovy.lang.MissingMethodException: No signature of method: Tools.main() is applicable for argument types: () values: []
If I then add
void main(args) { }
to class Tools, the error goes away but that Tools.main is run instead of the plugin.main and I get no output.
My second approach as suggested was to use
def script = new GroovyScriptEngine( '.' ).with {
loadScriptByName( 'C:\\Program Files\\Serviio\\plugins\\tools.groovy' )
}
this.metaClass.mixin script
This however gives the error
unexpected token: this # line 55, column 2.
this.metaClass.mixin script
Any suggestions on how to make either of these solutions work would be appreciated.
Did you try defining a common base script and giving it as a compiler configuration.
http://groovy.codehaus.org/Embedding+Groovy
From the groovy documentation...
class ScriptBaseTest {
#Test
void extend_groovy_script() {
def compiler = new CompilerConfiguration()
compiler.setScriptBaseClass("ScriptBaseTestScript")
def shell = new GroovyShell(this.class.classLoader, new Binding(), compiler)
assertEquals shell.evaluate("foo()"), "this is foo"
}
}
abstract class ScriptBaseTestScript extends Script {
def foo() {
"this is foo"
}
}

Groovyc successfully compiles invalid groovy scripts

c:\>cat invalid.groovy
com.test.build(binding)
c:\junk>groovyc invalid.groovy
c:\junk>ls invalid.class
invalid.class
Why does this not result in an compilation error? There is no such method com.test.build!
In what scenario will this compilation be successful?
As Groovy is dynamic it cannot know that there will be no com.test.build at runtime
com may be an object added to the binding at a later date in the code's execution
An example:
Say we have this bit of groovy inside Script.groovy
com.test.build( binding )
Compile it with groovyc:
groovyc Script.groovy
Then, keep the Script.class file, and throw away the groovy script to make sure we are using the class file:
rm Script.groovy
Now, say we have the following in Runner.groovy
// Create a class which you can call test.build( a ) on
class Example {
Map test = [
build : { it ->
println "build called with parameter $it"
}
]
}
// Create one of our Com objects
def variable = new Example()
// Load the Script.class, and make an instance of it
def otherscript = new GroovyClassLoader().loadClass( 'Script' ).newInstance()
// Then, set `com` in the scripts binding to be our variable from above
otherscript.binding.com = variable
// Then, run the script
otherscript.run()
That prints:
build called with parameter groovy.lang.Binding#7bf35647
So as you can see, it gets the test parameter of the com object (the map above) and calls the build closure with the binding as a parameter...
Hope this makes sense...

How to import org.codehaus.groovy.scriptom.* on Groovy?

I'm trying to run a Groovy app to manipulate Excel files on STS (by SpringSource) 2.3.0.
My Groovy version is 1.7.
Class:
package com.mytool
import org.codehaus.groovy.scriptom.ActiveXObject
/**
* #author Mulone
*
*/
class SurveyTool {
static main(args) {
print 'test'
def wshell = new ActiveXObject('Wscript.Shell')
wshell.popup("Scriptom is Groovy")
}
}
Sadly, this is what I get:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
C:\workspace\SurveyTool\src\com\geoadapta\surveytool\SurveyTool.groovy: 6: unable to resolve class org.codehaus.groovy.scriptom.ActiveXObject
# line 6, column 1.
import org.codehaus.groovy.scriptom.ActiveXObject
^
1 error
I also tried to rename ActiveXObject to ActiveXProxy with the same result.
I tried to import scriptom manually from the package scriptom-all-assembly-1.6.0 but I didn't work.
Any idea?
Cheers
Ops, I fixed it by importing all the jar files manually and by putting jacob-1.14.3-x86.dll in the project folder.

Resources