Jersey vs Restlet - comparative examples

Work in progress page!

Jersey is the JAX-RS reference implementation, Restlet is a popular API for creating RESTful web services. Restlet provides also a JAX-RS extension but by default its syntax is quite different from that standard. Examples provided in this page could be useful if you are planning to port some code from one library to the other.

General differences

Maven

Jersey is available on Maven Central, while for Restlet you need to add following section in your pom.xml:

<repositories>
    <repository>
        <id>maven-restlet</id>
        <name>Public online Restlet repository</name>
        <url>http://maven.restlet.com</url>
    </repository>
</repositories>

Endpoint configuration

Following example defines a service having an endpoint on /myservice/resource/info.

Jersey

Restlet

Filtering

Jersey

Restlet

JAXB

How to represent JAXB classes (classes annotated using @XmlRootElement).

Jersey

You simply need to return a MyJAXBClass in a request handler method annotated with the proper media type in @Produces and Jersey will automatically marshal it in XML.

@Path("resource")
public class MyResource {
 
    @GET
    @Produces(MediaType.APPLICATION_XML)
    public MyJAXBClass getXML() {
 
        MyJAXBClass jaxbOject = getMyJAXBObject();
        return jaxbOject;
    }

Restlet

public class MyResource extends ServerResource {
 
    @Get
    public Representation getXML() {
 
        return new WriterRepresentation(MediaType.TEXT_XML) {
 
            @Override
            public void write(Writer writer) throws IOException {
                MyJAXBClass jaxbOject = getMyJAXBObject();
                JAXB.marshal(jaxbOject, writer);
            }
        };
    }
}

Client - Big file upload

Jersey

You MUST set CHUNKED settings to avoid “OutOfMemoryError: Java heap space” due to sun.net.www.http.PosterOutputStream used by Jersey implementation.

import org.glassfish.jersey.client.ClientProperties;
 
public class MyClient {
 
    private static final int BUFFER_SIZE = 1024;
 
    public Response uploadFile(final File file) throws GeneralSecurityException, IOException {
 
        WebTarget target = ClientBuilder.newClient()
                .property(ClientProperties.CHUNKED_ENCODING_SIZE, 1024)
                .property(ClientProperties.REQUEST_ENTITY_PROCESSING, "CHUNKED")
                .target(baseURL)
                .path("myservice").path("file")
                .queryParam("fileName", file.getName());
 
        StreamingOutput out = new StreamingOutput() {
 
            @Override
            public void write(OutputStream output) throws IOException, WebApplicationException {
 
                byte[] chunk = new byte[BUFFER_SIZE];
                try (FileInputStream is = new FileInputStream(file)) {
 
                    int available;
                    while ((available = is.available()) > 0) {
                        if (available >= BUFFER_SIZE) {
                            is.read(chunk);
                            output.write(chunk);
                        } else {
                            output.write(is.read());
                        }
                    }
                }
            }
        };
 
        Response response = target.request().post(Entity.text(out));
        return response;
    }
}

Restlet

Restlet doesn't suffer from the OutOfMemoryError big file upload issue affecting Jersey.

public Status uploadFile(final File file, MediaType mediaType) throws IOException {
 
    Form fileForm = new Form();
    fileForm.add(Disposition.NAME_FILENAME, file.getName());
    Disposition disposition = new Disposition(Disposition.TYPE_INLINE, fileForm);
    FileRepresentation entity = new FileRepresentation(file, mediaType);
    entity.setDisposition(disposition);
 
    FormDataSet fds = new FormDataSet();
    fds.setMultipart(true);
    FormData fdFile = new FormData("fileToUpload", entity);
    fds.getEntries().add(fdFile);
 
    Reference reference = new Reference(userSpaceBaseURL)
            .addSegment("myservice").addSegment("file");
 
    ClientResource cr = getClientResource(reference);
    cr.post(fds);
    return cr.getStatus();
}