views:

558

answers:

3

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.

+2  A: 

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

bastianneu
+1  A: 

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.

Don
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?
fabien7474
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)?
fabien7474
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'
Don