I wanted to see if I could streamline the environment, and have my locally installed tomcat run my grails application. It is possible to use the excellent tomcat plugin to export a WAR of your project to an external tomcat instance via tomcat's manager application. The problem with this configuration is that you lose the "hot-deploy" features of grails which was a deal breaker for me.
After quite a bit of head scratching, googling, and yelling at my computer, I finally got pointed in the right direction from Graeme Rocher via the grails-user mailing list. If you are not aware, grails uses tomcat's embedded version under the hood as of 1.2. I was aware that grails emits numerous lifecycle events that you can hook into, but was unaware that the tomcat plugin uses this system to announce a "TomcatConfigured" event that exposes the underlying tomcat API. During startup of your grails project, the tomcat plugin will configure the embedded engine, and then announce the "TomcatConfigured" event, and pass along the newly configured tomcat. This can be used to manage and configure every aspect of the tomcat engine.
My current implementation supports only one specific web application. In the future, I plan on updating this code to support multiple applications which will be configurable via Config.groovy, which should be rather trivial.
Begin by adding your project specific configuration to Config.groovy:
grails.myproject.contextRoot = "/myproject" grails.myproject.build.path = "/myproject/WEB-INF/classes" grails.myproject.web.root = "/myproject/"
Next we need to add the event handler to our Grails application. This is done by simply creating a new file named _Events.groovy and placing it in the /scripts directory of your project.
import org.apache.catalina.* import org.apache.catalina.connector.* import org.apache.catalina.loader.WebappLoader import org.codehaus.groovy.grails.commons.ConfigurationHolder eventConfigureTomcat = {tomcat -> println "### Starting load of custom application" def contextRoot = ConfigurationHolder.config.grails.myproject.contextRoot def buildroot= ConfigurationHolder.config.grails.myproject.build.path def webroot = ConfigurationHolder.config.grails.myproject.web.root File appDir = new File(webroot); context = tomcat.addWebapp(contextRoot, appDir.getAbsolutePath()); context.reloadable = true WebappLoader loader = new WebappLoader(tomcat.class.classLoader) loader.addRepository(new File(buildroot).toURI().toURL().toString()); context.loader = loader loader.container = context println "### Ending load of custom application" }
You can now start you application with the grails run-app command, and your java web application will be available under the context you set in Config.groovy.
As a side note, if you need to support having an apache web server sit in fron of your application, you can add the following to turn on AJP connections for the embedded tomcat container.
// enable AJP to allow apache to front tomcat def ajpConnector = new Connector("org.apache.jk.server.JkCoyoteHandler") ajpConnector.port = 8009 ajpConnector.setProperty("redirectPort", "8443") ajpConnector.setProperty("protocol", "AJP/1.3") ajpConnector.setProperty("enableLookups", "false") tomcat.service.addConnector ajpConnector