Usually in our Ratpack application we use a registry to store components that we want to use in our application code. The calling code for the registry doesn't need to know how the registry is implemented. Ratpack support Google Guice for example, but Spring is also supported. This means we can define the components for our registry using Spring and we only have to tell Ratpack where to look for the Spring configuration files. Ratpack provides for us the ratpack.spring.Spring
class with the static method spring
. This method returns a Ratpack registry implementation we can use in our application.
To enable Spring support we must add the Ratpack spring-boot dependency to our build file:
// File: build.gradle ... dependencies { compile ratpack.dependency('spring-boot') } ...
In our first example we first write a simple Spring configuration file. In the file we also use Spring's profile support, so depending on the active profile different beans are defined:
// File: src/main/groovy/mrhaki/ratpack/spring/MessageConfig.groovy package mrhaki.spring import groovy.transform.CompileStatic import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Profile @CompileStatic @Configuration class MessageConfig { @Bean Message messageDefault() { new MessageImpl('DEFAULT') } @Bean @Profile('dev') Message messageDevelopment() { new MessageImpl('DEV') } @Bean @Profile('prod') Message messageProduction() { new MessageImpl('PROD') } } @CompileStatic interface Message { String message() } @CompileStatic class MessageImpl implements Message { private final String env MessageImpl(final String env) { this.env = env } @Override String message() { return "Hello from Spring! - running in $env" } }
To turn this Spring configuration into a Ratpack registry we simply use the static spring
method of the ratpack.spring.Spring
class:
import mrhaki.spring.Message import mrhaki.spring.MessageConfig import org.springframework.context.annotation.AnnotationConfigApplicationContext import ratpack.spring.Spring import static ratpack.groovy.Groovy.ratpack ratpack { handlers { // Use Spring Application context as registry // for components to be used in our Ratpack application. // With the register() method we make the Registry // available for all handlers. register Spring.spring(new AnnotationConfigApplicationContext(MessageConfig)) get { Message message -> render message.message() } } }
If we make a request for the URL http://localhost:5050/
we get the following output: Hello from Spring! - running in DEFAULT.
In this example we use the spring
method that accepts a ListableBeanFactory
implementation to create the new registry. But actually we can also provide one or more Spring configuration classes directly to the spring
method. We can use Spring Boot configuration to define our registry. So we can rely on all the auto configuration features of Spring Boot to create a new registry in our Ratpack application. We can also pass arguments with the spring
method that normally would come from the command line for a Spring application. Let's rewrite our previous example and use the configuration class with an argument to select a Spring profile:
import mrhaki.spring.Message import mrhaki.spring.MessageConfig import ratpack.server.ServerConfig import ratpack.spring.Spring import static ratpack.groovy.Groovy.ratpack ratpack { handlers { // Instead of the register() method we use all() // together with next() method to define registry // for the handlers. all { // Use Spring configuration as registry // for components to be used in our Ratpack application. // We pass extra arguments to select a Spring profile. final Boolean devMode = get(ServerConfig).development next(Spring.spring(MessageConfig, "--spring.profiles.active=${devMode ? 'dev' : 'prod'}")) } get { Message message -> render message.message() } } }
So if we start the Ratpack application in development mode we get a different implementation for the Message
interface than if we would start in non-development mode, because the value of spring.profiles.active
determines which profile is active. Let's open http://localhost:5050/
when we run in development mode and we get the following output: Hello from Spring! - running in DEV.
Finally we can use a SpringApplicationBuilder
object with the spring
method. We can for example turn of the banner or disable the logging of startup information:
import mrhaki.spring.Message import mrhaki.spring.MessageConfig import org.springframework.boot.Banner import org.springframework.boot.builder.SpringApplicationBuilder import ratpack.spring.Spring import static ratpack.groovy.Groovy.ratpack ratpack { handlers { // Using SpringApplicationBuilder for further customization. // We can add multiple configuration sources to the constructor. final SpringApplicationBuilder springApp = new SpringApplicationBuilder(MessageConfig) .bannerMode(Banner.Mode.OFF) .logStartupInfo(true) // We could also pass arguments like in the previous // example using this spring() method implementation. register Spring.spring(springApp) get { Message message -> render message.message() } } }
We start our Ratpack application and we get the following logging on our console:
[main] INFO ratpack.server.RatpackServer - Starting server... [main] INFO ratpack.server.RatpackServer - Building registry... [2016-05-30 07:12:21.161] - 61301 INFO [main] --- ratpack.groovy.GroovyRatpackMain: Starting GroovyRatpackMain on mrhaki-laptop with PID 61301 (/Users/mrhaki/.gradle/caches/modules-2/files-2.1/io.ratpack/ratpack-groovy/1.3.3/34230f9bf9c4e1b0e8c0fd253b9b4f62ef154096/ratpack-groovy-1.3.3.jar started by mrhaki in /Users/mrhaki/Projects/mrhaki.com/blog/posts/samples/ratpack/spring) [2016-05-30 07:12:21.164] - 61301 INFO [main] --- ratpack.groovy.GroovyRatpackMain: No profiles are active [2016-05-30 07:12:21.190] - 61301 INFO [main] --- org.springframework.context.annotation.AnnotationConfigApplicationContext: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5ca1f591: startup date [Mon May 30 07:12:21 CEST 2016]; root of context hierarchy [2016-05-30 07:12:21.275] - 61301 INFO [main] --- org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring [2016-05-30 07:12:21.325] - 61301 INFO [main] --- ratpack.groovy.GroovyRatpackMain: Started GroovyRatpackMain in 0.314 seconds (JVM running for 1.874) [main] INFO ratpack.server.RatpackServer - Ratpack started (development) for http://localhost:5050
Written with Ratpack 1.3.3