JAX-RS: REST Streaming Response

In this post, we are going to see how to streaming a response with JAX-RS StreamingOutput.

StreamingOutput is an interface(https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/StreamingOutput.html) and used as a resource method return value or as the entity in a Response when the application wishes to stream the output.

Consider that we have a list of person objects and each object contains first and last name and we want to create a RESTful web service to fetch the person details. Our goal is to stream the response instead of getting everything. Lets see how we can use StreamingOutput to achieve our goal.

The below is Person model class which contains two fields such as first name and last name.



package com.resource;

public class Person {

    private String firstName;
    private String lastName;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}


The below is the Resource class and the method getDetails passes StreamingOutput to streamPersonData method of PersonService class.

Produces is “application/octet-stream” because we want to save the response as a file instead of rendering that in the browser.


package com.resource;

import com.service.PersonService;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;

@Path("/person")
public class PersonResource {

    @GET
    @Produces("application/octet-stream")
    @Path("details")
    public Response getDetails() {
        return Response.ok((StreamingOutput) new PersonService()::streamPersonData).build();
    }

}


The below is the PersonService class which contains the necessary logic to get the person details and convert the person object into JSON format and then write the converted JSON to OutputStream.

Because we are writing the output as JSON array, we are adding a comma symbol at the end of each person JSON output.


package com.service;

import com.model.Person;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class PersonService {

    private ObjectMapper objectMapper = new ObjectMapper();

    public void streamPersonDetails(OutputStream output) throws IOException {
        output.write('[');
        int i = 1;
        List personDetails = getPersonDetails();
        for (Person person : personDetails) {
            output.write(objectMapper.writeValueAsBytes(person));
            if (i < personDetails.size()) {
                output.write(',');
            }
            i++;
        }
        output.write(']');
    }

    private List getPersonDetails() {
        List personList = new ArrayList();
        for (int i = 0; i < 500; i++) {
            Person person = new Person();
            person.setFirstName("Peter:" + i);
            person.setLastName("Woods:" + i);
            personList.add(person);
        }
        return personList;
    }
}


The output is given below,

Streaming_response

If we want to render the response as “JSON” and view the response in browser, then we have to change the produces like this “@Produces(MediaType.APPLICATION_JSON)” and the output look like below,

Streaming_response_JSON

Advertisements