Creating Ratpack Apps with the Gradle Application Plugin
Currently, there are two ways to run a Ratpack app, you can build and run the ratpack executable or you can use the runapp groovy script. Both methods are ok but I wanted a way to be able to easily move apps between computers and make sure I didn't miss a jar. I started poking around in the Gradle documentation and found what I needed in the application plugin.
Gradle's Application plugin provides tasks that are common to an application's lifecycle:
- run, which runs the app,
- installApp, which installs the app into a directory,
- startScripts, which creates OS-specific scripts to start the app, and
- distZip, which creates an archive of the app directories.
All of this functionality is provided mostly for free by including the following code in your build.gradle file:
apply plugin: 'application'
mainClassName = '<package and name of your class>'
In lieu of installing Ratpack to my local Maven repository and assuming anyone I sent a distro of the app would too, I dropped the file into a lib directory and created a flat repository for that directory.
repositories {
flatDir name:'lib', dirs:'lib'
mavenCentral()
}
The Ratpack build jar does not contain all of its dependencies so I copied them over to my dependencies gradle block. You could just as easily drop the dependencies into your flat repo and reference them from dependencies. I decided to let Maven do the heavy lifting and retrieve them at run-time. I set up my source directories in the default Maven style and I was ready to go. gradle run actually started the app and I was able to respond to routes.
However, things failed tragically whenever I tried to access a public file or template from either the installed version, created using gradle installApp, or the extracted archive, created using gradle distZip. I quickly realized that it was because I naively thought gradle was going to package everything in the root directory. After a little wrangling, I happened upon the required incantations to make it work. The following code explicitly copies the template and public directories to the installed app and archive.
installApp {
into('build/install/'+applicationName){
from ('templates').into '/templates'
}
into('build/install/'+applicationName){
from ('public').into '/public'
}
}
distZip {
into(applicationName){
from ('templates').into applicationName+'/templates'
}
into(applicationName){
from ('public').into applicationName+'/public'
}
}
You can view the whole file here.