Affects: Spring 6.1.5 with Spring Boot 3.1.5
I have this class
@NoArgsConstructor
public class RequestDTO {
@NotNull
private String name;
@NotNull
private LocalDate startDate;
@NotNull
private LocalDate endDate;
@JsonIgnore
@AssertTrue(message = "Range not valid")
public boolean isRangeValid() {
if(getEndDate()==null) return true;
if(getStartDate()==null) return true;
if (getStartDate().isEqual(getEndDate())) return true;
return getEndDate().isAfter(getStartDate());
}
}
and a subclass:
@EqualsAndHashCode(callSuper = true)
@JsonIgnoreProperties("code")
public class RequestExtensionDTO extends RequestDTO{
public RequestExtensionDTO(){
super();
}
}
When I use the subclass with @Valid
in a POST method of controller...
@PostMapping("/simplePostChilDTO")
public ResponseEntity<?> simplePostChildDTO(@RequestBody
@Valid RequestExtensionDTO template) {
return ResponseEntity.ok().build();
}
... the annotations defined in the parent class do not trigger; @AssertTrue
defined on the method instead triggers.
The following metadata is produced:
{
"name":"test.model.RequestDTO",
"methods":[
{
"name":"getStartDate",
"parameterTypes":[
]
},
{
"name":"getEndDate",
"parameterTypes":[
]
},
{
"name":"setName",
"parameterTypes":[
"java.lang.String"
]
},
{
"name":"setStartDate",
"parameterTypes":[
"java.time.LocalDate"
]
},
{
"name":"isRangeValido",
"parameterTypes":[
]
},
{
"name":"setEndDate",
"parameterTypes":[
"java.time.LocalDate"
]
},
{
"name":"getName",
"parameterTypes":[
]
}
]
}
In order to overcome the problem I have to create a specific hint for the parent class:
hints.reflection().registerType(RequestDTO.class, MemberCategory.values());
This way the constraints are all triggered.
Is this behavior correct?
If you need it, I have a demo.
Comment From: moeenScape
This is expected issue. @AssertTrue is a method level constraint. Method level constraint are define at method level and apply only to specific class in which they are declared. By default,they are not inherited by child class. Now,when you use @Valid RequestExtensionDTO on this child class ,@valid or validation only consider the constraints define with in that class . it does not apply constraints from the parent class in this case RequestDTO.
You solution will work but it may not be stander way to handle method-level constraints in a parent class are triggered when validating in child class. I will mention some way that you can try : 1. use Costume validation group : @GroupSequence({})
public interface ResquestValidationGroup{
}
@GroupSequence({Default.class,ResquestValidationGroup.class})
@NoArgsConstructor
public class RequestDTO {
@NotNull
private String name;
@NotNull
private LocalDate startDate;
@NotNull
private LocalDate endDate;
@JsonIgnore
@AssertTrue(message = "Range not valid")
public boolean isRangeValid()
{
if(getEndDate()==null) return true;
if(getStartDate()==null) return true;
if (getStartDate().isEqual(getEndDate())) return true;
return getEndDate().isAfter(getStartDate());
}
}
@GroupSequence({Default.class,ResquestValidationGroup.class})
@EqualsAndHashCode(callSuper = true)
@JsonIgnoreProperties("code")
public class RequestExtensionDTO extends RequestDTO{
public RequestExtensionDTO(){
super();
}
}
-
Override isRangeValid this in child class ```java @EqualsAndHashCode(callSuper = true) @JsonIgnoreProperties("code") public class RequestExtensionDTO extends RequestDTO{
public RequestExtensionDTO(){ super(); }
@AssertTrue(message = "Range not valid") @Override public boolean isRangeValid() { return super.isRangeValid(); }
} ``` Node : Use custom validation group is more acceptable .
(Please Correct me if i am wrong. )
Comment From: sdeleuze
@nexus061 Yes please share your demo/repro and confirm that the issue happens only while running the application compiled as a native image, while behaving as expected with the JVM.
Comment From: nexus061
Yes please share your demo/repro and confirm that the issue happens only while running the application compiled as a native image, while behaving as expected with the JVM.
I confirm that it only occurs with native compilation, with the classic start of the jar it works.
I have a demo project that I tested with swagger, if you give me some time I will also create the test suite
Comment From: sdeleuze
@nexus061 I can't reproduce with https://github.com/sdeleuze/spring-aot-smoke-tests/commit/gh-31552, please provide a reproducer.
Comment From: nexus061
i have done this repo https://github.com/nexus061/test_spring, is possible run native test with docker image of grallvm?
@sdeleuze have done a fix for test case
Comment From: sdeleuze
I can indeed reproduce with the repo you provided by running ./mvnw test -PnativeTest
, thanks.
Comment From: nexus061
@sdeleuze thanks for fix, when will the next version be released?
Comment From: sdeleuze
You're welcome, you can find the date by clicking on the related milestone.