swagger-core icon indicating copy to clipboard operation
swagger-core copied to clipboard

Custom NotNull annotations stopped working between 2.2.28 and 2.2.29

Open kevinm416 opened this issue 6 months ago • 4 comments

I'm using springdoc to generate OpenAPI documents for my application. In order to generate improved error messages, I'm using my own @NotNull annotations instead of jakarta.validation.constraints.NotNull. This was working fantastic for me until swagger v2.2.29, when my @NotNull annotations stopped generating the appropriate required fields.

See more details here: https://github.com/springdoc/springdoc-openapi/issues/3004#issuecomment-2955732679.

Ideally I would like the previous behavior reinstated where I can use any annotation with the name NotNull to mark required fields.

If that does not happen, are there any extension points I can use to keep my model generation working? I have hundreds of models annotated with @NotNull, and maintaining this is essential for my api clients to work correctly.

kevinm416 avatar Jun 09 '25 14:06 kevinm416

This seems to be broken by this change in 2.2.29: https://github.com/swagger-api/swagger-core/pull/4853

The code that processes ModelResolver.NOT_NULL_ANNOTATIONS is now being called only when Configuration.GroupsValidationStrategy is ALWAYS:

if (strategy.equals(GroupsValidationStrategy.ALWAYS)) {
     return this.applyBeanValidatorAnnotationsNoGroups(property, annotations, parent, applyNotNullAnnotations);
} else
...

while it is default by default.

plebedev avatar Jun 11 '25 17:06 plebedev

Can I set Configuration.GroupsValidationStrategy to ALWAYS manually to work around this issue? How would I do that?

kevinm416 avatar Jun 11 '25 23:06 kevinm416

I did not find a good way to do it. The workaround I have is to do something like this at some point of your app's initialization:

final var config = new io.swagger.v3.core.util.Configuration();
    config.setOpenAPI31(true);
    config.setGroupsValidationStrategy(
        io.swagger.v3.core.util.Configuration.GroupsValidationStrategy.ALWAYS);
    ModelConverters.getInstance(config);

    config.setOpenAPI31(false);
    ModelConverters.getInstance(config);

plebedev avatar Jun 12 '25 11:06 plebedev

Great, I added it to the static initialization block I already had for other swagger workarounds, and I was able to successfully work around this issue as well:

  static {
    // https://github.com/springdoc/springdoc-openapi/issues/232#issuecomment-748607672
    io.swagger.v3.core.jackson.ModelResolver.enumsAsRef = true;
    // https://stackoverflow.com/a/73321304
    SpringDocUtils.getConfig().replaceWithClass(LocalTime.class, String.class);

    // https://github.com/swagger-api/swagger-core/issues/4909
    final var config = new io.swagger.v3.core.util.Configuration();
    config.setOpenAPI31(true);
    config.setGroupsValidationStrategy(GroupsValidationStrategy.ALWAYS);
    ModelConverters.getInstance(config);
    config.setOpenAPI31(false);
    ModelConverters.getInstance(config);
  }

kevinm416 avatar Jun 22 '25 14:06 kevinm416