A Bit of Help
A Bit of Help

Reputation: 1766

JAX-RS: How to intercept json message body before sending in the response?

I am creating a JAX-RS web service that only deals with json. We are using JAX-RS 2.0 and Netbeans 8. All JPA 2.1 entities have a unique id that is used for auditing purposes. It is not the primary key. An entity may have lists of other associated entities. We need to make sure that the entity and the entities in the associated lists all have the same unique id. If there is a difference, the audit fails.

I am trying to figure out the best way to handle this validation...

I could try to use reflection, but this is slow and cumbersome...

I could create a write interceptor, determine the kind of entity, get the unique id from it, and scan any lists of objects to determine whether there is a difference. I don't like this idea because I would have to write code to validate each specific entity in our model and maintain this code whenever the model changes.

My favorite choice is to intercept the json that is generated before it is returned to the requestor. I could simply tokenize the string and find the unique id values. If any are different, I would throw an exception. This assumes that eager loading is being used, which is the only disadvantage that I can think of because it means that we have to always return the full payload rather than just the entity. For this item, I tried to use a write interceptor, but I discovered that the entity has not been serialized to json yet. So, I am at a loss about how to intercept the json before it is returned to the caller.

I would really appreciate your suggestions about the best choice for accomplishing my goal.

Thank you for your interest, suggestions, and time.

Mike

Upvotes: 4

Views: 3066

Answers (1)

lefloh
lefloh

Reputation: 10961

A WriterInterceptor is a good choice. It serializes the entity if you call context.proceed(). After that the result can be found in context.getOutputStream(). As it's not easy to read from this OutputStream you can use a ByteArrayOutputStream for serializing and restore the original stream afterwards:

@Provider
public class ResponseInterceptor implements WriterInterceptor {

    @Override
    public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
        OutputStream originalStream = context.getOutputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        context.setOutputStream(baos);
        try {
            context.proceed();
        } finally {
            // search in the response, e.g.
            JsonNode response = new ObjectMapper().readTree(baos.toByteArray());
            // ...
            // write to and restore the original Stream
            baos.writeTo(originalStream);
            baos.close();
            context.setOutputStream(originalStream);
        }
    }

}

Upvotes: 7

Related Questions