In a previous blog post we learned how to use HandlerDecorator.prepend
to add common handlers via the registry in our application. The type of handlers suitable for this approach were handlers that had common functionality for the rest of the handlers. If we want to add a Chain
implementation, containing handlers and maybe even path information, we cannot use the prepend
method, must write our own implementation of the HandlerDecorator
interface. This can be useful when we want to re-use a Chain
in multiple applications. We write a module that adds the Chain
implementation to the registry and we don't have to write any code in the handlers
section for the Chain
to work. This blog post is inspired by a conversation on the Ratpack Slack channel recently. First we create a simple handler that renders a result:
// File: src/main/groovy/com/mrhaki/ratpack/Ping.groovy
package com.mrhaki.ratpack
import ratpack.groovy.handling.GroovyChainAction
/**
* Implementation of a {@link ratpack.handling.Chain} interface
* by extending {@link GroovyChainAction}, so
* we can use Groovy DSL support in the
* {@link Ping#execute} method.
*/
class Ping extends GroovyChainAction {
@Override
void execute() throws Exception {
// What we normally would write
// in the handlers{} section
// of Ratpack.groovy.
path('pingpong') {
render 'Ratpack rules!'
}
}
}
Continue reading →
In our Ratpack application we can have handlers that need to be invoked for every request. For example the handler needs to set a response header and will use the Context.next()
method to continue with the rest of the handlers. When we have such a handler we can use the all
method of a Chain
instance. This happens in the handlers
section of our application definition. We can also register such handlers directly in the registry. We can even use a Module
to register the handler implementation. To register a handler in the registry we must use the HandlerDecorator
interface. The interface has a method prepend
that will encapsulate a Handler
implementation and makes it available before any other handlers.
In the following sample we have a Handler
implementation that checks if the RequestId
object is available. If so then the value is set as a response header:
Continue reading →
A client of our Ratpack application can send a HTTP Accept header to indicate the type of response the client expects or can handle. We can restrict our application to certain types with the accepts
method of the Handlers
class. We can define one or more String
values that denote the types that a client can use and our application responds to. If the value for the Accept header is one of the given values then the next handlers are invoked otherwise a client error 406 Not Acceptable
is returned.
In the following example Ratpack application definition we use the accepts
method so only values of application/json
and application/xml
:
Continue reading →
If we write our own handler class it is not so difficult to get objects from the registry and use them in the code. In our handler we have a handle
method and we get a Context
object as argument. From the Context
we get access to objects in the registry. Instead of writing code to get the objects from the registry we can use the InjectionHandler
as superclass for our handler. The InjectionHandler
class has a handle
method that will look for a handle
method in our implementation class with a first argument of type Context
. Then at least one other argument must be defined in the method signature. The types of the other arguments are used to get the corresponding objects from the registry. We don't write the code to get the object from the registry ourselves, but rely on the implementation in the InjectionHandler
class.
The following example handler class extends from the InjectionHandler
. We write a handle
method and from the signature we see that we have a dependency on the type Messages
. In the implementation of the handle
method we can rely on the InjectionHandler
class to get an object from the registry with type Messages
.
Continue reading →
Interesting links for week 3 2016:
Continue reading →
The logging framework SLF4J supports Mapped Diagnostic Context (MDC). With MDC we can use a logging context that can be identified by something unique. This is useful, because then we can distinguish log messages from a big logging stream by something unique. Normally MDC is implemented on a per thread basis, but that is not useful in a Ratpack application. Ratpack provides the MDCInterceptor
class to use SLF4J's MDC support in a Ratpack application. We must register an instance of MDCInterceptor
with the registry. We can use the static method instance
to create a new instance. With the method withInit
we can define an action to be executed for the initialisation of the instance. An Execution
parameter is used with the action and we can use it to check for objects in the registry.
In the following example we initialise the MDCInterceptor
and check if there is a RequestId
object in the registry (as described in the Javadoc of MDCInterceptor
). If the RequestId
object is available we set the MDC logging context variable requestId
with the value of the RequestId
object. Later in our logging configuration we can use this value so we can distinguish all logging statements belonging to a single request (with the given identifier).
Continue reading →
Ratpack has the ratpack.server.Service
interface with the methods onStart
and onStop
. If we write an implementation class for the Service
interface and register it with the Ratpack registry, then Ratpack will invoke the onStart
method when the application starts and the onStop
method when the application stops. The methods take an event object as argument and we can use the event object to access the registry if we need to. Writing an implementation for the Service
interface can be useful for example to bootstrap the application with initial data or do other things.
In the following example implementation we log when the application starts and stops. In the onStart
method we also display a Ratpack banner on the console.
Continue reading →
In Ratpack we can use the byContent
method on the Context
object to send different responses based on the requested MIME type from the client. There is already support for application/json
, application/xml
, text/plain
and text/html
MIME types with corresponding methods of the ByContentSpec
object that is passed as argument to the byContent
method. We can match on a custom MIME type with the method type
and specify the MIME type. If the type matches we can create a response.
In the following example application we have a custom renderer for a User
object:
Continue reading →
When we use the render
method in our Ratpack application then Ratpack will use the type of the object we want to render to find an appropriate renderer. Some renderers are built-in, like a Promise
or CharSequence
renderer. We can write our own renderers by implementing the ratpack.render.Renderer
interface. Next we must register our renderer in the Ratpack registry.
In our example application we have a very simple User
class:
Continue reading →
Ratpack has the class ratpack.handling.ReponseTimer
which adds a header with the name X-Response-Time
to the response. The value is the time spent in code from when the request comes in and the response is sent out. ResponseTimer
is a handler we can add in our application. Alternatively we can use the static method decorator
to get a handler decorator. With a handler decorator we can use the registry to add handler logic in our application.
First we use the ResponseTimer
as a handler:
Continue reading →
Russel Hart has a nice example on how to extend the Ratpack Groovy DSL in the hands on ratpack project on Github. We can use the Groovy extension module feature to add new methods to arbitrary classes. If we use this to add new methods to the GroovyChain
class we can use those methods in the DSL of our Groovy Ratpack application.
A Groovy extension module is just a class with a definition of the new methods we want to add to a class. The first argument of the method is the class the method is added to and the remaining arguments can be used by the implementation. We also need to create a supporting file org.codehaus.groovy.runtime.ExtensionModule
with some information about our extension class. This supporting file needs to be in the classpath in the directory META-INF/services
.
Continue reading →
In a previous post we have seen how to use regular expressions for path tokens. We can also name the path token for which the regular expression applies. This makes it easier to get the value in our handler code: we can just refer to the name. Also we can add a question mark to the name to make the token optional.
In the following example we use the name conferenceName
for the path token with the regular expression Gr\w+
:
Continue reading →