How to execute a Groovy Script from my Grails app?
Asked Answered
S

5

6

Well, it seems a simple task but I didn't manage to make it run.

I have a groovy script that runs fine under Windows Vista when calling from prompt:

> cd MY_GAILS_PROJECT_DIR
> groovy cp src/groovy scripts/myscript.groovy

Now, I want to execute this script (and passing to it some input arguments) through my my Maintenance Service Class (called from a controller) as below,

class MaintenanceService {
  def executeMyScript() {
    "groovy cp src/groovy scripts/myscript.groovy".execute()
  }
}

It does not work at all! I don't even manage to have the execute() method recognizing any command (like "cd .".execute()) throwing exception:

Error 500: java.io.IOException: Cannot run program "cd": CreateProcess error=2, The system cannot find the file specified

1- How can I execute a groovy script from my grails application?

2- What are the best practices here? For instance, should I use the QuartzPlugin and then the triggerNow method for executing a script? should I use a Gant Task? If yes, how to do it?

Thank you.

Spelldown answered 18/12, 2009 at 10:28 Comment(2)
Is there a specific reason it has to be a groovy "script", rather than a class you can call, as bastianneu suggests below?Nutt
Yes. I need this groovy script to be executed without Grails environment as well.Spelldown
M
5

If you don't mind your script running asynchronously (in a separate process to the service method), the following should work assuming groovy is on your PATH variable:

def cmd = ['groovy.bat', 'cp', 'src/groovy scripts/myscript.groovy']
cmd.execute()

If you want to view the output of the process in the application console, you should try something like this instead

// Helper class for redirecting output of process
class StreamPrinter extends Thread {
    InputStream inputStream

    StreamPrinter(InputStream is) {
        this.inputStream = is
    }

    public void run() {
        new BufferedReader(new InputStreamReader(inputStream)).withReader {reader ->
            String line
            while ((line = reader.readLine()) != null) {
                println(line)
            }
        }
    }
}

// Execute the script
def cmd = ['groovy', 'cp', 'src/groovy scripts/myscript.groovy']
Process executingProcess = cmd.execute()

// Read process output and print on console
def errorStreamPrinter = new StreamPrinter(executingProcess.err)
def outputStreamPrinter = new StreamPrinter(executingProcess.in)
[errorStreamPrinter, outputStreamPrinter]*.start()

Update: In response to your comment below, try the following (which assumes you're on Windows):

1: Create the file C:\tmp\foo.groovy. The content of this file should be simply:

println 'it works!'

2: In the groovy console, run the following:

cmd = ['groovy.bat', 'C:\\tmp\\foo.groovy']
cmd.execute().text

3: You should see the result of the script (the text 'it works!') shown in the Groovy console

If you can't get this simple example working, there's something wrong with your environment, e.g. 'groovy.bat' is not on your PATH. If you can get this example working, then you should be able to work forward from it to achieve your objective.

Mucosa answered 18/12, 2009 at 15:54 Comment(3)
Hi. thank you for your answer but it throws exactly the same result. For instance def cmd = ['cd', 'd:/temp']; cmd.execute() => The system cannot find the file specified. Do you have an idea?Spelldown
Thanks a lot! Back from your example, I managed to make it work with backslashes for path and "groovy.bat" instead of groovy. And now it works !! Thx. One question : do you know why 'groovy.bat' works but not 'groovy' (whereas in a command prompt both works)?Spelldown
I guess it's because in a command prompt '.bat' is recognised as an executable file type, but at the OS level you need to provide the full filename unless it's '.exe'. Incidentally, on Linux you can use either 'grails' or 'grails.sh'Antichlor
E
4

As of grails 1.3.6 the run-script command is built in to let you run

grails run-script myScript.groovy

For earlier versions of grails, check out my updated blog post from what Carlos posted above.

Empathic answered 1/1, 2011 at 23:28 Comment(0)
A
2

Easiest Way:

Generate an Groovy Class and place at in your /src/groovy Folder of your Grails Project. Import that Class in your Domain Class and use the Functions you defined.

My 2 Cents...

Ayotte answered 18/12, 2009 at 11:14 Comment(0)
C
0

Another decision you can use GroovyScriptEngine for example:

file MyScript.groovy:

static String showMessage() {
    println("Message from showMessage")
}

file BootStrap.groovy:

class BootStrap {

    def init = { servletContext ->
        new GroovyScriptEngine("scripts")
                .loadScriptByName("MyScript.groovy")
                .showMessage()
    }
    def destroy = {

    }
}
Cindycine answered 13/5, 2021 at 13:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.