Search code examples
javarestlet

Restlet reuse InputStream


Consider the next code.

Filter:

public class InputFilter extends Filter {

  @Override
  protected int beforeHandle(Request request, Response response) {

    int result = CONTINUE;
    InputStream inputStream = request.getEntity().getStream();
    StringWriter writer = new StringWriter();
    IOUtils.copy(inputStream, writer, "UTF-8");

    String theString = writer.toString();
    JsonRepresentation jRep = new JsonRepresentation(theString);

    String token = jRep.getJsonObject().getString("token");
    .
    .
    .
    return result;
  }
}

Resource:

public class inputResource extends GsServerResource {

  @Post
  public JsonRepresentation getInput(JsonRepresentation jRep) {
    String token = jRep.getJsonObject().getString("token");
    .
    .
    .
  }
}

jRep is NULL.

I use the stream once in the filter and it is closed for later use due to the fact that it is not transient.

My current fix:

in the filter (after retrieving the Stream):

request.getAttributes().putIfAbsent("token", token);

in the resource:

String token = (String) getRequest().getAttributes().get("token");

Is there any other solution than putting the data in to the context in the filter and later retrieving it in the resource?


Solution

  • In fact, you can set again within the filter the entity for the request based on a StringRepresentation based on the entity text you extracted from the request, as described below:

    // Get entity text
    Representation repr = request.getEntity();
    String content = repr.getText();
    
    // Use entity text
    InputStream inputStream = request.getEntity().getStream();
    StringWriter writer = new StringWriter();
    IOUtils.copy(inputStream, writer, "UTF-8");
    
    String theString = writer.toString();
    JsonRepresentation jRep = new JsonRepresentation(theString);
    
    String token = jRep.getJsonObject().getString("token");
    
    // Set again the entity for the request
    StringRepresentation sRepr = new StringRepresentation(
                               content, repr.getMediaType());
    request.setEntity(sRepr);
    

    Using this approach, you can read again the request entity within the resource behind the filter.

    Hope it helps you, Thierry