All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ratpack.handling.HandlerDecorator Maven / Gradle / Ivy

There is a newer version: 2.0.0-rc-1
Show newest version
/*
 * Copyright 2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ratpack.handling;

import ratpack.registry.Registry;

/**
 * Decorates a handler, effectively wrapping it.
 * 

* Handler decorators can be used to contribute to the handler chain from the {@link ratpack.server.RatpackServerSpec#registry server registry}. * It is often used by libraries/extensions to participate in request handling in order to set up infrastructure for downstream handlers. *

* The {@link #prepend(Handler)} method is a convenient way to create a decorator that simply prepends a given handler to the application handlers. *

{@code
 * import ratpack.handling.Handler;
 * import ratpack.handling.HandlerDecorator;
 * import ratpack.handling.Context;
 * import ratpack.util.Types;
 * import ratpack.test.embed.EmbeddedApp;
 * import static org.junit.Assert.*;
 *
 * 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());
 *       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. *

{@code
 * import ratpack.handling.Handler;
 * import ratpack.handling.HandlerDecorator;
 * import ratpack.handling.Context;
 * import ratpack.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.Assert.*;
 *
 * 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;
 *
 *     {@literal @}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. */ public interface HandlerDecorator { /** * A handler decorator implementation that does not decorate the handler. * * That is, it just returns the given handler. * * @return a handler decorator that does not decorate the handler */ static HandlerDecorator noop() { return (registry, rest) -> rest; } /** * Creates a new handler that decorates the application handlers, given as the {@code rest} argument. *

* As the {@code rest} argument encapsulates the application handlers, the returned handler should generally delegate to it (via {@link Context#insert(Handler...)}). * * @param serverRegistry the server registry * @param rest the rest of the handlers of the application * @return a new handler * @throws Exception any */ Handler decorate(Registry serverRegistry, Handler rest) throws Exception; /** * A factory for decorator impls that effectively inserts the given handler before the “rest” of the handlers. *

* The given handler should call {@link Context#next()} to delegate to the rest of the handlers. * * @param handler the handler to prepend * @return a handler decorator implementation */ static HandlerDecorator prepend(Handler handler) { return (registry, rest) -> Handlers.chain(handler, rest); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy