Skip to content

Weblogic 12.2.1 and GraphQL Java Servlet #61

@briancullen

Description

@briancullen

Hello I'm trying to deploy a GraphQL servlet version 4.7.0 within a Spring MVC war that will be deployed onto Weblogic 12.2.1 and whenever I try and do a request with a content type of application-json I get the following error.

Bad POST request: parsing failed com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
at [Source: weblogic.servlet.internal.ServletInputStreamImpl@14b82135; line: 1, column: 0]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:255)
at com.fasterxml.jackson.databind.ObjectReader._initForReading(ObjectReader.java:361)
at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1561)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1166)
at graphql.servlet.GraphQLServlet.lambda$new$1(GraphQLServlet.java:197)
at graphql.servlet.GraphQLServlet.doRequest(GraphQLServlet.java:255)

I think I have tracked the problem down to the post handler, specifically the part that deals with requests that are not multipart requests (starts on line 188 in the version I have). This code checks that marking is supported by the input stream and if it isn't wraps it in a BufferedInputStream so that the isBatchedQuery method can "peek" ahead at the request body and then reset back to the start of the input for the parser.

The input stream class at this stage is an implementation of ServletInputStream which is implemented different for different application containers. Most containers, like Tomcat, do not implement marking on their implementation so it will be wrapped by a BufferedInputStream. Unfortunately Weblogic does implement these methods on it's version and so will not be wrapped.

This would not cause a problem apart from the line of code where the input stream is marked, as shown below, in the isBatchedQuery method (line 449).

inputStream.mark(0);

According to the Java API the parameter (in this case zero) indicates the maximum number of bytes that can be read before the mark becomes invalid. So technically this is saying that the mark becomes invalid the moment any data is read from it. This doesn't cause an issue with BufferedInputStreams as this parameter is ignored (in fact it seems to be ignored by a lot of implementations I have seen) but the weblogic implementation does use the value passed to it. This means that when reset is called at the end of the isBatchedQuery method the input stream is not actually reset and the parsing then fails. In my case I get a no content error because there is less than 128 characters in the body so the parser gets no input.

The quick solution as far as I can see is to rewrite the method as shown in the snippet below. The difference being that we set the maximum number of characters for the mark to equal the size of the buffer we are about to read in. In that way the reset method will be able to do it's job and the parser will find the expected input.

        ByteArrayOutputStream result = new ByteArrayOutputStream();
        byte[] buffer = new byte[128];
        int length;

        inputStream.mark(128);
        while ((length = inputStream.read(buffer)) != -1) {
            result.write(buffer, 0, length);
            String chunk = result.toString();

Does this seem like a reasonable solution to the problem I'm having or have I missed something? I can create a pull request for this (although I'm away for the next week) but I thought it best to raise an issue first and ensure that this is the best approach.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions