Skip to content
JakeHoward edited this page Jul 16, 2015 · 1 revision

Resource methods in Utterlyidle can return different types of objects. When you return a Response object, you can explicitly set the headers and the entity. When you return a String or any other object then it will be automatically wrapped in a Response and whatever you return will end up in the entity body. Before you return the response to the client you can modify the response in a ResponseHandlersModule. Why would you want to do that?

Let's take a look at the example.

In your resource you have a method like that:

@GET
@Path("list")
public Model newsInCategory(@QueryParam("category") @DefaultValue("politics") String category) {
    List<Article> news = newsRepository.getNews(category, 10);
    return Model.model().add("news", news);
}

It returns a Model that contains a list of news in a given category. It doesn't matter what the model is. It can be a wrapper around a map or a more complex data structure. You could also return a map directly. Utterlyidle will wrap this Model in the Response entity.

In the ResponseHandlersModule you can define how this Model should be rendered:

import com.googlecode.utterlyidle.modules.ResponseHandlersModule;
import com.googlecode.totallylazy.Predicate;
import com.googlecode.utterlyidle.ResponseHandler;
import com.googlecode.totallylazy.Pair;
...
public class UIModule implements ResponseHandlersModule, RequestScopedModule {
    public ResponseHandlers addResponseHandlers(ResponseHandlers handlers) throws Exception {
        Predicate<Pair<Request,Response>> predicate = ...;
        ResponseHandler responseHandler = ...
        handlers.add(predicate, responseHandler);

        return handlers;
    }
    ...
}

As you can see in the code above we need to define a predicate and a response handler. Predicate is an instance of com.googlecode.totallylazy.Predicate and it let's you define what Request, Response pair (com.googlecode.totallylazy.Pair) is eligible for being modified by a response handler.

You can manually create a predicate:

import com.googlecode.totallylazy.Pair;
import com.googlecode.totallylazy.Predicate;
import com.googlecode.utterlyidle.Request;
import com.googlecode.utterlyidle.Response;
...
Predicate<Pair<Request, Response>> predicate = new Predicate<Pair<Request, Response>>() {
    public boolean matches(Pair<Request, Response> requestAndResponse) {
        ...
    }
};

Alternatively, you can use one of the built-in predicates:

import com.googlecode.totallylazy.Predicates;
import com.googlecode.totallylazy.Predicate;
import com.googlecode.utterlyidle.handlers.HandlerRule;
...
Predicate<Pair<Request,Response>> predicate = Predicates.where(HandlerRule.entity(), is(instanceOf(Model.class)));

Once you defined a predicate, you can add a matching response handler:

import com.googlecode.utterlyidle.ResponseHandler;
import com.googlecode.utterlyidle.Response;
...
ResponseHandler responseHandler = new ResponseHandler() {
    public Response handle(Response response) throws Exception {
        ...
    }
};

Inside the handle method you can create a copy of the original response with a modified entity. E.g. you can take a model/map you returned in a resource and use a template engine to put the model values in a JSON, XML, HTML document or any other format you want.

Utterlyidle also gives you a higher level utility to handle entities:

import com.googlecode.utterlyidle.handlers.RenderingResponseHandler;
...
ResponseHandler renderer = RenderingResponseHandler.renderer(ModelRenderer.class);
public class ModelRenderer implements Renderer<Model> {
    public ModelRenderer(TemplateEngine engine) {
        ....
    }

    public String render(Model value) throws Exception {
        // translate model to String using your template engine of choice
    }
}

In the code above, we registered a renderer for our Model. ModelRenderer can have a dependency on a template engine that translates our model/map to a textual representation.

Clone this wiki locally