Skip to content

Instantly share code, notes, and snippets.

@yvesf
Created January 13, 2016 16:56
Show Gist options
  • Save yvesf/80e91eed22cff9540633 to your computer and use it in GitHub Desktop.
Save yvesf/80e91eed22cff9540633 to your computer and use it in GitHub Desktop.
Grails 3 Run-Command

Grails 3 no longer contains the functionality to execute Scripts within an running application context. Grails 2.x contained the 'run-script' command and also allowed to run arbitrary scripts implemented as Gant tasks under $dir/scripts directory of any project.

As a substitute grails 3 offers ApplicationContext Commands. The downside is that they cannot be implemented in the actual project because they have to be in the gradle buildscript classpath as well. This is also not desirable because one don't want to pollute this classpath with application dependencies.

This project provides a workaround for that. It is on one side a grails project and registers exactly one command that then later at runtime can execute other commands that are only present in the application classpath.

This project has to be in the classpath of the buildscript and at least the runtime classpath of the project.

In project sources:

class TestOtherCommand implements ApplicationCommand {
  @Override
  boolean handle(ExecutionContext executionContext) {
    println 'Hello World'
    return true
  }
}
grails runCommand test-other [optional arguments to test-other]

or using gradle directly (example calling the generate-tracking command implemented in the application):

./gradlew -Dgrails.command.args='generate-tracking otherArgument' runCommand

No matter if called through gradle or grails directly, the arguments will be in the executionContext.commandLine.remainingArguments (Note: For calling from gradle there is a workaround, normally this wouldn't be the case. -PgrailsArgs is not readable for non dynamic tasks, not prefixed with grails-.).

package .....
import grails.dev.commands.ApplicationCommand
import grails.dev.commands.ApplicationContextCommandRegistry
import grails.dev.commands.ExecutionContext
import groovy.util.logging.Commons
@Commons
class RunCommandCommand implements ApplicationCommand {
@Override
boolean handle(ExecutionContext executionContext) {
def args = GradlecommandsGrailsPlugin.getArguments(executionContext)
assert args.size() > 0: 'Need at least a command name'
final command = ApplicationContextCommandRegistry.findCommand(args.first())
assert command: "Failed to find command with name ${args.first()}. Available commands are: ${availableCommands}"
executionContext.commandLine.remainingArgs.clear()
executionContext.commandLine.remainingArgs.addAll(Arrays.asList(args).drop(1))
command.setApplicationContext(applicationContext)
try {
return command.handle(executionContext)
} catch (Exception e) {
e.printStackTrace()
throw e
}
}
private static String getAvailableCommands() {
return ApplicationContextCommandRegistry.findCommands().collect { it.name }.join(', ')
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment