Search code examples
javajerseyinterceptor

422 status code - ReaderInterceptor Jersey


I am getting 422 error after introducing a ReaderInterceptor on one of my existing API calls. The call was working fine before, but started giving 422 after I introduced the ReaderInterceptor.

Here is the code for my ReaderInterceptor's aroundReadForm() method

@Override
    public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
        InputStream is = context.getInputStream();
        String body = new BufferedReader(new InputStreamReader(is)).lines().collect(Collectors.joining("\n"));
        ObjectMapper mapper = new ObjectMapper();
        try {
            SampleObject sampleObject = mapper.readValue(body, SampleObject.class);
            LOGGER.info(sampleObject.getSampleProperty());

        } catch (JsonGenerationException | JsonMappingException e) {
            LOGGER.info(e.getMessage());
        }
        return context.proceed();
    }

The thing I am trying to do is to read the body in the request, convert it to a POJO using Jackson's ObjectMapper and then move the request forward as it is. Not sure, what is the reason for this 422 status code.


Solution

  • ObjectMapper will close the request input stream. Try creating a new stream from the body variable. And calling context.setInputStream().

    public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
            InputStream is = context.getInputStream();
            String body = new BufferedReader(new InputStreamReader(is)).lines().collect(Collectors.joining("\n"));
            ObjectMapper mapper = new ObjectMapper();
            try {
                SampleObject sampleObject = mapper.readValue(body, SampleObject.class);
                LOGGER.info(sampleObject.getSampleProperty());
    
            } catch (JsonGenerationException | JsonMappingException e) {
                LOGGER.info(e.getMessage());
            }
            InputStream in = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8));
    
            context.setInputStream(in)
            return context.proceed();
        }
    

    The downside of what you are trying to do is performance. Seems you will parse the JSON string to object twice. Once in the interceptor and once in the reader.

    If the body is small this is not much of an issue.

    Resource: https://www.baeldung.com/jersey-filters-interceptors