citrus icon indicating copy to clipboard operation
citrus copied to clipboard

[OpenAPI] NPE when validating nullable JSON properties

Open ueberfuhr opened this issue 1 year ago • 3 comments

Citrus Version 4.2.1

Expected behavior When receiving a response with nullable JSON properties, they should only be validated if they have a value.

Actual behavior Instead, we get an NPE.

Caused by: java.lang.NullPointerException: Cannot invoke "String.length()" because "text" is null
	at java.base/java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1474)
	at java.base/java.text.DateFormat.parse(DateFormat.java:397)
	at org.citrusframework.validation.matcher.core.DatePatternValidationMatcher.validate(DatePatternValidationMatcher.java:46)
	at org.citrusframework.validation.matcher.ValidationMatcherUtils.resolveValidationMatcher(ValidationMatcherUtils.java:75)
	at org.citrusframework.validation.json.JsonElementValidator.validate(JsonElementValidator.java:53)
	at org.citrusframework.validation.json.JsonElementValidator.validateJSONObject(JsonElementValidator.java:85)
	at org.citrusframework.validation.json.JsonElementValidator.validate(JsonElementValidator.java:55)
	at org.citrusframework.validation.json.JsonTextMessageValidator.validateMessage(JsonTextMessageValidator.java:75)
	at org.citrusframework.validation.json.JsonTextMessageValidator.validateMessage(JsonTextMessageValidator.java:43)
	at org.citrusframework.validation.AbstractMessageValidator.validateMessage(AbstractMessageValidator.java:41)
	at org.citrusframework.actions.ReceiveMessageAction.validateMessage(ReceiveMessageAction.java:263)
	at org.citrusframework.actions.ReceiveMessageAction.doExecute(ReceiveMessageAction.java:167)
	at org.citrusframework.actions.AbstractTestAction.execute(AbstractTestAction.java:59)
	at org.citrusframework.DefaultTestCase.executeAction(DefaultTestCase.java:190)
	... 8 more

Test case sample This is the return type in OpenAPI:

components:
  schemas:
    Todo:
      type: object
      required:
        - title
      properties:
        id:
          format: int64
          type: integer
          readOnly: true
        title:
          minLength: 3
          type: string
        completed:
          type: boolean
        due_date:
          format: date
          type: string
          example: 2022-03-10

and the corresponding JSON response:

{
  "id": 1,
  "title": "rGH",
  "completed": false,
  "due_date": null
}

ueberfuhr avatar May 31 '24 05:05 ueberfuhr

The only way to avoid the exception is to disable validation for optional fields:

OpenApiSpecification apiSpecification = OpenApiSpecification.from(
    Resources.create("classpath:META-INF/resources/openapi.yml")
);
apiSpecification.setValidateOptionalFields(false);

But this will disable the complete validation. It should be possible to validate those fields if they are not null. So we need a possibility to influence the control message, which requires an extension to the validation matches. This could be one of the following ideas:

  • a @null()@ (which has the inverse semantic of @ignore()?) and a combination with or
  • an additional boolean parameter to the matchers that tells to validate to true or false, if the value is null (a required parameter)

ueberfuhr avatar May 31 '24 05:05 ueberfuhr

Another unpleasant thing is that, in the case of disabled validation of optional fields, the control message only contains the required fields, which will fail if the JSON validator is in strict mode. I guess, it should not fail, if we disable validation of optional fields, because they are declared in the OpenAPI.

ueberfuhr avatar May 31 '24 06:05 ueberfuhr

Agreed, we need to make the null value validation more robust. Thank you for reporting this! In case you have some time to implement your ideas contributions are very welcome! Many thanks!

christophd avatar Jun 12 '24 08:06 christophd

released in https://github.com/citrusframework/citrus/releases/tag/v4.3.0

bbortt avatar Aug 15 '24 06:08 bbortt