LevelResolver is not Thread Safe

Issue #251 resolved
Brandon Chapman created an issue

The getLevel method on LevelResolver is not thread safe. One thread could be calling levels.containsKey(key) while another is calling levels.put(key, result). This will manifest itself as a null pointer exception as levels.get(key) will return null if the put operation has not completed.

java.lang.NullPointerException: A level is required

                at java.base/java.util.Objects.requireNonNull(Objects.java:246)
                at com.atlassian.oai.validator.report.ImmutableMessage.<init>(ImmutableMessage.java:52)
                at com.atlassian.oai.validator.report.ImmutableMessage.<init>(ImmutableMessage.java:41)
                at com.atlassian.oai.validator.report.ImmutableMessage.<init>(ImmutableMessage.java:33)
                at com.atlassian.oai.validator.report.MessageResolver.get(MessageResolver.java:63)
                at com.atlassian.oai.validator.interaction.request.RequestValidator.validateMediaTypes(RequestValidator.java:173)
                at com.atlassian.oai.validator.interaction.request.RequestValidator.validateAccepts(RequestValidator.java:124)
                at com.atlassian.oai.validator.interaction.request.RequestValidator.validateRequest(RequestValidator.java:100)
                at com.atlassian.oai.validator.OpenApiInteractionValidator.lambda$validate$0(OpenApiInteractionValidator.java:217)
                at java.base/java.util.function.Function.lambda$andThen$1(Function.java:88)
                at com.atlassian.oai.validator.OpenApiInteractionValidator.validateOnApiOperation(OpenApiInteractionValidator.java:296)
                at com.atlassian.oai.validator.OpenApiInteractionValidator.validate(OpenApiInteractionValidator.java:213)
                at com.atlassian.oai.validator.restassured.OpenApiValidationFilter.filter(OpenApiValidationFilter.java:58)
                at io.restassured.filter.Filter$filter.call(Unknown Source)

Comments (8)

  1. James Navin

    Thanks for raising (and fixing!) this. So I can understand better - what is the use case you have that results in this thread race?

  2. Brandon Chapman reporter

    We have a test suite that uses RestAssured to send real HTTP requests to our service while all of our service's external dependencies are mocked with WireMock. We have the swagger validator configured to validate each request and response sent by our tests. Recently we upgraded to junit 5 and enabled parallel testing. We started seeing unexpected behavior from the LevelResolver. For example we had used the property file to allow additionalProperties but we started seeing random error reports that either the request or response had additional properties. To work around it, we just added them as additional exclusions in the property file. This worked for a while but eventually we started getting the null pointer exception. The root cause of all of these issues was the getLevel method due to how concurrent access works on normal HashMaps.

  3. Log in to comment