Passing parameters between JAX-RS WriterInterceptor and ReaderInterceptor

I'm using JAX-RS and within the WriterInterceptor, I need to access some information contained in the original request.

As an example, consider the below request body.

{ 
        "ClientId": "MY_CLIENT_ID",
        "UserId": "MY_USER_ID",
        "AccountId": "MY_ACCOUNT_ID",
        "Scope" : "MY_SCOPES",
}

Within my WriteInterceptor, I need to read Client ID and User ID from the request and add those values to the response.

I am currently working on a ReadInterceptor implementation for this. I initially assumed there is a way to put parameters to ReaderInterceptorContext and then read it somehow from the WriterInterceptorContext. But It seems there is no way to do that. ( Please correct me if I'm wrong).

So, now I'm trying to use a concurrent hashmap to store these parameters in the ReaderInterceptor and retrieve it in the WriteInterceptor. I need a unique key to create the correlation between request and response. Is it ok to use the thread ID for this?

Please point me if there is a better approach to resolve this problem

Upvotes: 0

Views: 1000

Answers (1)

I resolved this problem by adding a container response filter which can add a header to the response. Read interceptor reads required parameters from the request and set those as context properties.

    @Override
     public Object aroundReadFrom(ReaderInterceptorContext   readerInterceptorContext)
        throws IOException, WebApplicationException {

    InputStream is = readerInterceptorContext.getInputStream();
    String requestBody = new Scanner(is, StandardCharsets.UTF_8.name()).useDelimiter("\\A").next();
    JSONObject request = new JSONObject(requestBody);
    //Adding the stream back to the context object
    readerInterceptorContext.setInputStream(new ByteArrayInputStream(requestBody.getBytes()));
    //Adding properties to read in filter
    readerInterceptorContext.setProperty("ClientId", request.get("ClientId"));
    readerInterceptorContext.setProperty("UserId","UserId"));
    return readerInterceptorContext.proceed();
    }

These properties are then read inside the container response filter and added as a response header.

@Override
public void filter(ContainerRequestContext containerReqContext, ContainerResponseContext containerResponseContext) {
    //Adding temporary headers to read in WriterInterceptor
    containerResponseContext.getHeaders().add(
            "ClientId", containerReqContext.getProperty("ClientId"));
    containerResponseContext.getHeaders().add(
            "UserId", containerReqContext.getProperty("UserId"));
}

Existing writer interceptor read these headers, add those to JWT and then remove as header values. I did a POC for this and it is working as expected

    @Override
public void aroundWriteTo(WriterInterceptorContext writerInterceptorContext) throws IOException {
    OutputStream outputStream = writerInterceptorContext.getOutputStream();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    writerInterceptorContext.setOutputStream(baos);
    String clientId = writerInterceptorContext.getHeaders().getFirst("ClientId").toString();
    String user = writerInterceptorContext.getHeaders().getFirst("UserId").toString();   
}

Upvotes: 1

Related Questions