We have several options to define a Ratpack application. We can use a Java syntax to set up the bindings and handlers. Or we can use the very nice Groovy DSL. It turns out we can use both together as well. For example we can define the handlers with the Groovy DSL and the rest of the application definition is written in Java. To combine both we start with the Java configuration and use the bindings
and handlers
method of the Groovy.Script
class to inject the files with the Groovy DSL.
We start with a sample application where we use Java configuration to set up our Ratpack application:
// File: src/main/java/mrhaki/ratpack/Application.java package mrhaki.ratpack; import ratpack.func.Action; import ratpack.handling.Chain; import ratpack.handling.Handler; import ratpack.registry.RegistrySpec; import ratpack.server.RatpackServer; import java.util.Optional; public class Application { public static void main(String[] args) throws Exception { new Application().startServer(); } void startServer() throws Exception { RatpackServer.start(server -> server .registryOf(registry()) .handlers(chain())); } private Action<RegistrySpec> registry() { return registry -> registry .add(new RecipeRenderer()) .add(RecipeRepository.class, new RecipesList()); } private Action<Chain> chain() { return chain -> chain.post("recipe", recipeHandler()); } private Handler recipeHandler() { return ctx -> ctx .parse(RecipeRequest.class) .flatMap(recipeRequest -> ctx .get(RecipeRepository.class) .findRecipeByName(recipeRequest.getName())) .then((Optional<Recipe> optionalRecipe) -> ctx.render(optionalRecipe)); } }
We can use the Groovy DSL for the bindings and handlers definitions and use them in our Java class with the Groovy.Script
class. First we create the files bindings.groovy
and handlers.groovy
in the directory src/main/resources
so they will be in the class path of the Java application. We can use the Groovy DSL syntax in the files:
// File: src/main/resources/bindings.groovy import mrhaki.ratpack.RecipeRenderer import mrhaki.ratpack.RecipeRepository import mrhaki.ratpack.RecipesList import static ratpack.groovy.Groovy.ratpack ratpack { bindings { add new RecipeRenderer() add RecipeRepository, new RecipesList() } }
// File: src/main/resources/handlers.groovy import mrhaki.ratpack.Recipe import mrhaki.ratpack.RecipeRepository import mrhaki.ratpack.RecipeRequest import static ratpack.groovy.Groovy.ratpack ratpack { handlers { post('recipe') { RecipeRepository recipeRepository -> parse(RecipeRequest) .flatMap { RecipeRequest recipeRequest -> recipeRepository.findRecipeByName(recipeRequest.name) } .then { Optional<Recipe> optionalRecipe -> render(optionalRecipe) } } } }
We have our Groovy DSL files with the definitions. To use them in our Java code to define the Ratpack application we must make sure Ratpack can find them. Therefore we create an empty marker file .ratpack
in src/main/resources
. With this file in place we can use Ratpack's findBaseDir
method to set the base directory for finding external files. It is time to refactor our application:
// File: src/main/java/mrhaki/ratpack/Application.java package mrhaki.ratpack; import ratpack.func.Action; import ratpack.groovy.Groovy; import ratpack.handling.Chain; import ratpack.handling.Handler; import ratpack.registry.RegistrySpec; import ratpack.server.RatpackServer; import java.util.Optional; public class Application { public static void main(String[] args) throws Exception { new Application().startServer(); } void startServer() throws Exception { RatpackServer.start(server -> server // Set base dir with directory that // contains marker file .ratpack. .serverConfig(config -> config.findBaseDir()) // Use bindings.groovy with static compilation. .registry(Groovy.Script.bindings(true)) // Use handlers.groovy with static compilation. .handler(Groovy.Script.handlers(true))); } }
Written with Ratpack 1.4.5.