I was working on our damage reporting API, specifically the POST /v1/damage-report endpoint, which creates a new damage report. The DamageReportDTO is a Java record with fields like damageType, employeeCausatorId, and others, validated using Jakarta Validation. Most fields are annotated with @NotNull(groups = OnFinalized.class), meaning they’re only required when submitting or approving a report, not at creation. Only employeeCausatorId has a plain @NotNull, so it should be the only mandatory field for the POST endpoint.
However, when I checked the Swagger UI (/swagger-ui.html), every field in the DamageReportDTO schema had a little star next to it, indicating they were all required. This was misleading—clients would think they need to send everything upfront, which isn’t true. The controller for POST /v1/damage-report doesn’t use @Validated, so those OnFinalized constraints shouldn’t apply here. Something was off with how Swagger was rendering the schema.
<aside> 💡
schema.requiredMode
is a newer way of handling required properties within OpenAPI specifications, particularly in OpenAPI 3.0 and later. It replaces the older, simpler required
boolean.
</aside>
Here’s what the DamageReportDTO looked like initially:
package com.sensey.mdf.damage_report.dto;
import com.sensey.mdf.damage_report.enums.DamageType;
import com.sensey.mdf.damage_report.validation.OnFinalized;
import jakarta.validation.constraints.NotNull;
import java.util.UUID;
public record DamageReportDTO(
UUID id,
@NotNull(groups = OnFinalized.class, message = "Damage type is required when finalizing")
DamageType damageType,
@NotNull(message = "Employee causator ID is required")
UUID employeeCausatorId,
@NotNull(groups = OnFinalized.class, message = "Employee reporter ID is required when finalizing")
UUID employeeReporterId
// ... other fields with similar annotations ...
) {}
And the controller:
@PostMapping
public ResponseEntity<DamageReportDTO> createDamageReport(@RequestBody DamageReportDTO damageDTO) {
return ResponseEntity.status(201).body(damageReportService.createDamageReport(damageDTO));
}
In Swagger UI, the schema for POST /v1/damage-report showed:
All had stars, even though only employeeCausatorId should.
I figured Swagger might be misinterpreting the @NotNull annotations. Since damageType and employeeReporterId use groups = OnFinalized.class, I assumed Swagger wasn’t smart enough to ignore those constraints for this endpoint. But why was id marked required? It didn’t even have @NotNull! Maybe it’s because it’s a record, and all fields are implicitly non-nullable in Java? I wasn’t sure.
I checked the raw OpenAPI spec at /v3/api-docs. The DamageReportDTO schema had: