Interface RenderableDecorator<T>

  • Type Parameters:
    T - the type of object-to-render that this decorator decorates
    All Known Implementing Classes:
    RenderableDecoratorSupport

    public interface RenderableDecorator<T>
    Decorates an object before it is rendered.

    While this type is called renderable decorator, it is not restricted to decorating Renderable implementations but is used to decorate all types of objects to be rendered.

    Renderable decorators are able to decorate/transform objects to be rendered. That is, they effectively sit between the call to Context.render(Object) and Renderer.render(Context, Object) of the target renderer. All of the decorators that are type compatible with the object to be rendered are invoked cumulatively in the order that they are returned from the context registry.

    It is not required, but generally advisable for decorators to return a new object instead of mutating the object they receive.

    
     import ratpack.test.embed.EmbeddedApp;
     import ratpack.core.render.Renderer;
     import ratpack.core.render.RenderableDecorator;
    
     import static org.junit.jupiter.api.Assertions.*;
    
     public class Example {
       public static void main(String... args) throws Exception {
         EmbeddedApp.fromHandlers(chain -> chain
           .register(registry -> registry
             .add(Renderer.of(Integer.class, (ctx, i) -> ctx.render(i.toString())))
             .add(RenderableDecorator.of(Integer.class, (ctx, i) -> i * 2))
             .add(RenderableDecorator.of(Integer.class, (ctx, i) -> i * 2))
           )
           .get(ctx -> ctx.render(1))
         ).test(httpClient ->
           assertEquals("4", httpClient.getText())
         );
       }
     }
     

    Such decorators are often used to augment the “model” being given to a template rendering engine to include implicit services and so forth.

    Note that decorators are selected based on the exact runtime type of the object being rendered, that is based on its Object.getClass(). As such, decorators must advertise to decorate concrete types as opposed to interfaces or super classes. A decorator effectively cannot change the type of the object-to-render.

    • Method Detail

      • typeOf

        static <T> com.google.common.reflect.TypeToken<RenderableDecorator<T>> typeOf​(Class<T> type)
        Creates a type token for a decorator of objects of the given type.
        Type Parameters:
        T - the object-to-render type
        Parameters:
        type - the object-to-render type
        Returns:
        a type token for a decorator of objects of the given type
      • getType

        Class<T> getType()
        The type of objects that this decorator decorates.
        Returns:
        the type of objects that this decorator decorates
      • decorate

        Promise<T> decorate​(Context context,
                            T object)
        Decorates the given object on its way to being rendered.

        Implementations may either mutate the object and return it, or return an entirely new object.

        Parameters:
        context - the request context
        object - the object-to-render
        Returns:
        a promise for the decorated object
      • of

        static <T> RenderableDecorator<T> of​(Class<T> type,
                                             BiFunction<? super Context,​? super T,​? extends T> impl)
        Creates a renderable decorator implementation for the given type that uses the function as decorator.

        The function must return the renderable, not a promise. If the decoration needs to perform async ops, use ofAsync(Class, BiFunction).

        Type Parameters:
        T - the type of object-to-render to decorate
        Parameters:
        type - the type of object-to-render to decorate
        impl - the implementation of the decorate(Context, Object) method
        Returns:
        a renderable decorator implementation
      • ofAsync

        static <T> RenderableDecorator<T> ofAsync​(Class<T> type,
                                                  BiFunction<? super Context,​? super T,​? extends Promise<T>> impl)
        Creates a renderable decorator implementation for the given type that uses the function as decorator.

        The function must return a promise for the renderable. If the decoration does not need to perform async ops, use of(Class, BiFunction).

        Type Parameters:
        T - the type of object-to-render to decorate
        Parameters:
        type - the type of object-to-render to decorate
        impl - the implementation of the decorate(Context, Object) method
        Returns:
        a renderable decorator implementation
      • register

        default Action<RegistrySpec> register()
        A registration action, typically used with RegistrySpec.with(Action).

        Registers this object with the type RenderableDecorator<T> (where T is the value of getType()), not its concrete type.

        Returns:
        a registration action