Interface HandlerDecorator
-
public interface HandlerDecorator
Decorates a handler, effectively wrapping it.Handler decorators can be used to contribute to the handler chain from the
server registry
. It is often used by libraries/extensions to participate in request handling in order to set up infrastructure for downstream handlers.The
prepend(Handler)
method is a convenient way to create a decorator that simply prepends a given handler to the application handlers.import ratpack.core.handling.Handler; import ratpack.core.handling.HandlerDecorator; import ratpack.core.handling.Context; import ratpack.func.Types; import ratpack.test.embed.EmbeddedApp; import static org.junit.jupiter.api.Assertions.*; import java.util.LinkedList; import java.util.Arrays; public class Example { public static class AddListToRequestRegistry implements Handler { public void handle(Context context) { context.getRequest().add(Types.listOf(String.class), new LinkedList<String>()); context.next(); } } public static class AddStringToList implements Handler { private final String string; public AddStringToList(String string) { this.string = string; } public void handle(Context ctx) { ctx.getRequest().get(Types.listOf(String.class)).add(string); ctx.next(); } } public static void main(String... args) throws Exception { EmbeddedApp.of(s -> s .registryOf(r -> r .add(HandlerDecorator.prepend(new AddListToRequestRegistry())) .add(HandlerDecorator.prepend(new AddStringToList("foo"))) .add(HandlerDecorator.prepend(new AddStringToList("bar"))) ) .handler(r -> ctx -> ctx.render(ctx.getRequest().get(Types.listOf(String.class)).toString()) ) ).test(httpClient -> assertEquals(Arrays.asList("foo", "bar").toString(), httpClient.getText()) ); } }
Handler decorators can't do anything that handlers can't do. In the above example, the same result could have been achieved by just using the handler implementations. Decorators are usually more useful when using something like Guice and where it is desired for a module to contribute handlers.
import ratpack.core.handling.Handler; import ratpack.core.handling.HandlerDecorator; import ratpack.core.handling.Context; import ratpack.exec.registry.Registry; import ratpack.test.embed.EmbeddedApp; import ratpack.guice.Guice; import com.google.inject.AbstractModule; import com.google.inject.Inject; import com.google.inject.multibindings.Multibinder; import static org.junit.jupiter.api.Assertions.*; import java.util.LinkedList; import java.util.Arrays; public class Example { public static class MaintenanceWindow { public boolean active = true; } public static class HandlerDecoratorImpl implements HandlerDecorator { private final MaintenanceWindow maintenanceWindow; @Inject public HandlerDecoratorImpl(MaintenanceWindow maintenanceWindow) { this.maintenanceWindow = maintenanceWindow; } public Handler decorate(Registry serverRegistry, Handler rest) { return ctx -> { if (maintenanceWindow.active) { ctx.render("down for maintenance!"); } else { ctx.insert(rest); } }; } } public static class MaintenanceWindowModule extends AbstractModule { protected void configure() { bind(MaintenanceWindow.class); // Important to use a multi binding to allow other modules to also contribute handlers Multibinder.newSetBinder(binder(), HandlerDecorator.class).addBinding().to(HandlerDecoratorImpl.class); } } public static void main(String... args) throws Exception { EmbeddedApp.of(s -> s .registry(Guice.registry(b -> b .module(MaintenanceWindowModule.class) )) .handler(r -> ctx -> ctx.render("ok!") ) ).test(httpClient -> { assertEquals("down for maintenance!", httpClient.getText()); }); } }
Handler decorators are invoked in the reverse order in which they are defined in the server registry. That is, the reverse of the order that they were added to the server registry. This means that earlier decorators decorate the handlers returned by later decorators. Said another way, the handler returned by the first decorator returned from the server registry will be the first handler to handle requests.
-
-
Method Summary
All Methods Static Methods Instance Methods Abstract Methods Modifier and Type Method Description Handler
decorate(Registry serverRegistry, Handler rest)
Creates a new handler that decorates the application handlers, given as therest
argument.static HandlerDecorator
noop()
A handler decorator implementation that does not decorate the handler.static HandlerDecorator
prepend(Class<? extends Handler> handler)
A factory for decorator impls that effectively inserts the given handler before the “rest” of the handlers.static HandlerDecorator
prepend(Handler handler)
A factory for decorator impls that effectively inserts the given handler before the “rest” of the handlers.static HandlerDecorator
prependHandlers(Class<? extends Action<? super Chain>> handlers)
A factory for decorator impls that effectively inserts the given chain before the “rest” of the handlers.static HandlerDecorator
prependHandlers(Action<? super Chain> handlers)
A factory for decorator impls that effectively inserts the given chain before the “rest” of the handlers.
-
-
-
Method Detail
-
noop
static HandlerDecorator noop()
A handler decorator implementation that does not decorate the handler. That is, it just returns the given handler.- Returns:
- a handler decorator that does not decorate the handler
-
decorate
Handler decorate(Registry serverRegistry, Handler rest) throws Exception
Creates a new handler that decorates the application handlers, given as therest
argument.As the
rest
argument encapsulates the application handlers, the returned handler should generally delegate to it (viaContext.insert(Handler...)
).- Parameters:
serverRegistry
- the server registryrest
- the rest of the handlers of the application- Returns:
- a new handler
- Throws:
Exception
- any
-
prepend
static HandlerDecorator prepend(Handler handler)
A factory for decorator impls that effectively inserts the given handler before the “rest” of the handlers.The given handler should call
Context.next()
to delegate to the rest of the handlers.- Parameters:
handler
- the handler to prependHandlers- Returns:
- a handler decorator implementation
-
prepend
static HandlerDecorator prepend(Class<? extends Handler> handler)
A factory for decorator impls that effectively inserts the given handler before the “rest” of the handlers.This is useful for cases when a handler is installed from the registry outside of the usual
RatpackServerSpec.handlers(Action)
} method, e.g. from an external module.The given handler should call
Context.next()
to delegate to the rest of the handlers.- Parameters:
handler
- a class defining the handler- Returns:
- a handler decorator implementation
- Since:
- 1.5
-
prependHandlers
static HandlerDecorator prependHandlers(Action<? super Chain> handlers)
A factory for decorator impls that effectively inserts the given chain before the “rest” of the handlers. The chain may define handlers that render results or callContext.next()
to delegate to the rest of the handlers.- Parameters:
handlers
- an action defining a handler chain- Returns:
- a handler decorator implementation
- Since:
- 1.5
-
prependHandlers
static HandlerDecorator prependHandlers(Class<? extends Action<? super Chain>> handlers)
A factory for decorator impls that effectively inserts the given chain before the “rest” of the handlers. The chain may define handlers that render results or callContext.next()
to delegate to the rest of the handlers.This is useful for cases when a group of handlers is installed from the registry outside of the usual
RatpackServerSpec.handlers(Action)
} method, e.g. from an external module.- Parameters:
handlers
- a class defining an action for a handler chain- Returns:
- a handler decorator implementation
- Since:
- 1.5
-
-