javajsonservletshttpexception

JSON Object incorrect and causing HttpException


I'm trying to test this method:

private ServiceApiMetadata getConfig(final HttpServletRequest request, final String path)
    throws IOException {
  final Schema schema;
  try (final InputStream inStream = this.getClass().getResourceAsStream(path)) {
    final JSONObject origSchema = new JSONObject(new JSONTokener(inStream));
    if (isGoldStar()) {
      origSchema.getJSONObject("properties")
          .getJSONObject("notifications")
          .getJSONObject("properties")
          .getJSONObject("topic")
          .put("pattern", "^[0-9A-Za-z-.]*$");
    }
    schema = SchemaLoader.load(origSchema);
  }

  final ServiceApiMetadata config;
  try (final BufferedReader reader = request.getReader()) {
    final JSONObject json = new JSONObject(new JSONTokener(reader));
    schema.validate(json);
    config = ServiceApiMetadata.read(json);
  } catch (final ValidationException e) {
    _logger.debug(e.getMessage());
    if (e.getLocation().contains("#/properties/notifications")) {
      throw new ServiceApiException(ServiceApiError.MALFORMED_NOTIFICATIONS_ERROR,
          ServiceApiErrorMessage.MALFORMED_JSON);
    } else {
      throw new ServiceApiException(ServiceApiError.MALFORMED_JSON);
    }
  } catch (final JSONException e) {
    _logger.debug(e.getMessage());
    throw new ServiceApiException(ServiceApiError.MALFORMED_JSON);
  }

  return config;
}

As it's private I created the following method in my class:

@TestOnly
protected void runGetConfig(final HttpServletRequest request, final String schemaPath) throws IOException {
  final ServiceApiMetadata conf = getConfig(request, schemaPath);
}

When I run my test getConfig() throws an exception. The problem is that when line final JSONObject json = new JSONObject(new JSONTokener(reader)); I get this exception:

HttpException(400,{"status_code":400,"error_code":"MalformedJson","uri":"uri","message":"MalformedJson"},null)

I also see this error in my log:

at 0 [character 1 line 1]

For the HttpServletRequest I'm using org.springframework.mock.web.MockHttpServletRequest.MockHttpServletRequest() as follows:

final MockHttpServletRequest request = new MockHttpServletRequest();

Is it possible this is creating an incorrect reader which in turn means the JSONObject is incorrect and if so how do I resolve this?

Additional info I added a body to the MockHttpServletRequest but the issue is still the same. I added some logging as can be seen below:

final JSONObject rawSchema = new JSONObject(new JSONTokener(inputStream));
      _logger.info("rawSchema: " + rawSchema);
      if (isPulsar()) {
        rawSchema.getJSONObject("properties")
            .getJSONObject("notifications")
            .getJSONObject("properties")
            .getJSONObject("topic")
            .put("pattern", "^[0-9A-Za-z-._:/]*$");
      }
      schema = SchemaLoader.load(rawSchema);
    }

    final ServiceApiContainerMetadata conf;
    try (final BufferedReader reader = request.getReader()) {
      _logger.info("reader: " + reader);
      _logger.info("JSONTokener(reader): " + new JSONTokener(reader.readLine()));
      final JSONObject json = new JSONObject(new JSONTokener(reader.readLine()));

It shows me this in the output:

rawSchema: {VALID JSON STRUCTURE. IT'S TOO BIG TO INCLUDE IN THIS QUESTION}
reader: java.io.BufferedReader@4c4d27c8
JSONTokener(reader):  at 0 [character 1 line 1]

Info on MockHttpServletRequest

The body of my MockHttpServletRequest contains the Lorem ipsum text. If I add the following code below my BufferedReader that text is printed to console. That same text is also used in ``final JSONObject json = new JSONObject(new JSONTokener(reader.readLine()));so the malformed JSON error in myHttpException` is no surprise.

while ((strCurrentLine = reader.readLine()) != null) {
  _logger.info("reader: " + strCurrentLine);
}

Could this be a bug in my code? Should final JSONObject json = new JSONObject(new JSONTokener(reader.readLine())); in fact be final JSONObject json = new JSONObject(schema);? If I try that I can get see the code now reaches schema.validate(json); but there are 12 schema violations found. I can't see what these are though. Another thought is should the body be JSON?

I updated the body to JSON which resulted in 2 validation errors. One was that service_id was missing and testkey was present so I resolved that and my method no longer throws an exception when I use final JSONObject json = new JSONObject(new JSONTokener(reader));.


Solution

  • To resolve this I added a notifications key to my body JSON. This allowed final JSONObject json = new JSONObject(new JSONTokener(reader.readLine())); to work.