Fork me on GitHub

When we send a Response to the client we must specify the content type. In most cases the content type is html (text/html) but are situations (for example a REST application/module) when we want to return plain text (text/plain) or json (application/json) or xml (application/xml) or yaml (application/x-yaml).
To resolve these situations Pippo comes with a nice concept ContentTypeEngine.
Pippo comes bultin (direct or via modules) with the following content type engines:

If you want to develop a new engine of content type you can do it very easily. All you have to do is to implement ContentTypeEngine.

See below a possible implementation for XstreamEngine (an XmlEngine based on XStream):

public class XstreamEngine implements ContentTypeEngine {

    @Override
    public String getContentType() {
        return HttpConstants.ContentType.APPLICATION_XML; // "application/xml"
    }

    @Override
    public String toString(Object object) {
        return new XStream().toXML(object);
    }

    @Override
    public <T> T fromString(String content, Class<T> classOfT) {
        return (T) new XStream().fromXML(content);
    }

    @Override
    public void init(Application application) {
        // do nothing
    }

}

To register a content type engine in your application you have two options:

  • programatically add the content type engine in Application.onInit() with Application.registerContentTypeEngine(XstreamEngine.class)
  • create an Initializer in your project that register the content type engine

For above XstreamEngine we can create an XstreamInitializer with this possible content:

public class XstreamInitializer implements Initializer {

    @Override
    public void init(Application application) {
        application.registerContentTypeEngine(XstreamEngine.class);
    }

    @Override
    public void destroy(Application application) {
        // do nothing
    }

}

Below is an example how to send an xml:

public class BasicApplication extends Application {

    @Override
    protected void onInit() {
        // send xml as response
        GET("/xml", routeContext -> {
            Contact contact = createContact();
            routeContext.xml().send(contact);
        });
    }

    private Contact createContact() {
        return new Contact()
            .setId(12345)
            .setName("John")
            .setPhone("0733434435")
            .setAddress("Sunflower Street, No. 6");
    }

}

Another useful concept is Content Type Negotiation. It can be used via Response.contentType() or ResponseContext.negotiateContentType().
It attempts to set the Content-Type of the Response based on Request headers. The Accept header is preferred for negotiation but the Content-Type header may also be used if an agreeable content type engine can not be determined.
If no Content-Type can not be negotiated then the response will not be modified. This behavior allows specification of a default Content-Type using one of the methods such as xml() or json().

See below an example related to content type negotiation:

public class BasicApplication extends Application {

    @Override
    protected void onInit() {
        // send an object and negotiate the Response content-type, default to XML
        GET("/negotiate", routeContext -> {
            Contact contact = createContact();
            routeContext.xml().negotiateContentType().send(contact);
        });
    }

}

In above example routeContext.xml().negotiateContentType().send(contact) would set the default Content-Type as application/xml and then attempt to negotiate the client's preferred type. If negotiation failed, then the default application/xml would be sent and used to serialize the outgoing object.