Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jakarta validation field constraints in superclass are ignored in native image #31552

Closed
nexus061 opened this issue Nov 5, 2023 · 8 comments
Closed
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) theme: aot An issue related to Ahead-of-time processing type: bug A general bug
Milestone

Comments

@nexus061
Copy link

nexus061 commented Nov 5, 2023

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.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Nov 5, 2023
@moeenScape
Copy link

moeenScape commented Nov 6, 2023

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();
	}

}
  1. Override isRangeValid this in child class
@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. )

@sdeleuze
Copy link
Contributor

sdeleuze commented Nov 6, 2023

@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.

@sdeleuze sdeleuze added theme: aot An issue related to Ahead-of-time processing status: waiting-for-feedback We need additional information before we can continue labels Nov 6, 2023
@nexus061
Copy link
Author

nexus061 commented Nov 6, 2023

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

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Nov 6, 2023
@sdeleuze sdeleuze self-assigned this Nov 6, 2023
@sdeleuze sdeleuze added this to the 6.1.0 milestone Nov 6, 2023
@sdeleuze sdeleuze added status: waiting-for-feedback We need additional information before we can continue type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on status: feedback-provided Feedback has been provided labels Nov 6, 2023
sdeleuze added a commit to sdeleuze/spring-aot-smoke-tests that referenced this issue Nov 7, 2023
@sdeleuze
Copy link
Contributor

sdeleuze commented Nov 7, 2023

@nexus061 I can't reproduce with sdeleuze/spring-aot-smoke-tests@gh-31552, please provide a reproducer.

@nexus061
Copy link
Author

nexus061 commented Nov 7, 2023

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

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Nov 7, 2023
@sdeleuze
Copy link
Contributor

sdeleuze commented Nov 7, 2023

I can indeed reproduce with the repo you provided by running ./mvnw test -PnativeTest, thanks.

@sbrannen sbrannen changed the title Native compilation AOT jakarta validation into superclass are ignored Jakarta validation field constraints in superclass are ignored in native image Nov 8, 2023
@sdeleuze sdeleuze removed the status: feedback-provided Feedback has been provided label Nov 9, 2023
@sdeleuze sdeleuze modified the milestones: 6.1.0, 6.0.14 Nov 9, 2023
@sdeleuze sdeleuze added type: bug A general bug and removed type: enhancement A general enhancement labels Nov 9, 2023
@jhoeller jhoeller added the in: core Issues in core modules (aop, beans, core, context, expression) label Nov 9, 2023
@nexus061
Copy link
Author

nexus061 commented Nov 9, 2023

@sdeleuze thanks for fix, when will the next version be released?

@sdeleuze
Copy link
Contributor

sdeleuze commented Nov 9, 2023

You're welcome, you can find the date by clicking on the related milestone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) theme: aot An issue related to Ahead-of-time processing type: bug A general bug
Projects
None yet
Development

No branches or pull requests

5 participants