Repository: asyncapi/modelina
Pull request #2176 (2025-02-07 15:44:24)

fix: the Java Constraint Generator omits `@Valid` annotation
## Description
<!-- Provide a brief description of the changes introduced by this pull request. -->
- Add missing `@Valid` annotations
- Update tests

## Related Issue
<!-- If this pull request is related to any existing issue, mention it here. -->
#2175

## Checklist
- [x] The code follows the project's coding standards and is properly linted (`npm run lint`).
- [x] Tests have been added or updated to cover the changes. (Updated existing)
- [x] Documentation has been updated to reflect the changes. (N/A)
- [x] All tests pass successfully locally.(`npm run test`).

## Additional Notes
<!-- Add any additional information or context that might be relevant to reviewers. -->


asyncapi-bot: We require all PRs to follow [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/). 
More details 👇🏼
```
 The subject "Java Constraint Generator omits `@Valid` annotation disallowing cascading validation" found in the pull request title "fix: Java Constraint Generator omits `@Valid` annotation disallowing cascading validation" should start with a lowercase character.

```
<!-- Sticky Pull Request Commentpr-title-lint-error -->
netlify[bot]: ### <span aria-hidden="true">👷</span> Deploy Preview for *modelina* processing.


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 5391b65d157f5487ac54d7f4ac432e230ea8ba3b |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/modelina/deploys/67a62a5bdd04740008270999 |
sonarqubecloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=asyncapi_generator-model-sdk&pullRequest=2176) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=asyncapi_generator-model-sdk&pullRequest=2176&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=asyncapi_generator-model-sdk&pullRequest=2176&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=asyncapi_generator-model-sdk&pullRequest=2176&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=asyncapi_generator-model-sdk&pullRequest=2176&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=asyncapi_generator-model-sdk&pullRequest=2176&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=asyncapi_generator-model-sdk&pullRequest=2176)


coveralls: ## Pull Request Test Coverage Report for [Build 13203180693](https://coveralls.io/builds/72145231)


### Details

* **2** of **2**   **(100.0%)**  changed or added relevant lines in **1** file are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage increased (+**0.005%**) to **92.402%**

---



|  Totals | [![Coverage Status](https://coveralls.io/builds/72145231/badge)](https://coveralls.io/builds/72145231) |
| :-- | --: |
| Change from base [Build 13012076762](https://coveralls.io/builds/71953974): |  0.005% |
| Covered Lines: | 6475 |
| Relevant Lines: | 6870 |

---
##### 💛  - [Coveralls](https://coveralls.io)

jonaslagoni: /rtm
jonaslagoni: Thanks for taking the time @istvan-nagy-epam :pray: 
jonaslagoni: @all-contributors please add @istvan-nagy-epam for code, test
allcontributors[bot]: @jonaslagoni 

I've put up [a pull request](https://github.com/asyncapi/modelina/pull/2177) to add @istvan-nagy-epam! :tada:

Patch:
diff --git a/examples/java-generate-jakarta-constraint-annotation/__snapshots__/index.spec.ts.snap b/examples/java-generate-jakarta-constraint-annotation/__snapshots__/index.spec.ts.snap
index d036c440..a526b1d1 100644
--- a/examples/java-generate-jakarta-constraint-annotation/__snapshots__/index.spec.ts.snap
+++ b/examples/java-generate-jakarta-constraint-annotation/__snapshots__/index.spec.ts.snap
@@ -9,6 +9,7 @@ Array [
   @NotNull
   @Max(99)
   private double maxNumberProp;
+  @Valid
   @Size(min=2, max=3)
   private Object[] arrayProp;
   @Pattern(regexp=\\"^I_\\")
diff --git a/examples/java-generate-javax-constraint-annotation/__snapshots__/index.spec.ts.snap b/examples/java-generate-javax-constraint-annotation/__snapshots__/index.spec.ts.snap
index 486bfb8a..3de8bf3b 100644
--- a/examples/java-generate-javax-constraint-annotation/__snapshots__/index.spec.ts.snap
+++ b/examples/java-generate-javax-constraint-annotation/__snapshots__/index.spec.ts.snap
@@ -9,6 +9,7 @@ Array [
   @NotNull
   @Max(99)
   private double maxNumberProp;
+  @Valid
   @Size(min=2, max=3)
   private Object[] arrayProp;
   @Pattern(regexp=\\"^I_\\")
diff --git a/src/generators/java/presets/ConstraintsPreset.ts b/src/generators/java/presets/ConstraintsPreset.ts
index c15a7e20..e82db51b 100644
--- a/src/generators/java/presets/ConstraintsPreset.ts
+++ b/src/generators/java/presets/ConstraintsPreset.ts
@@ -2,6 +2,8 @@ import {
   ConstrainedArrayModel,
   ConstrainedFloatModel,
   ConstrainedIntegerModel,
+  ConstrainedObjectModel,
+  ConstrainedReferenceModel,
   ConstrainedStringModel
 } from '../../../models';
 import { JavaPreset } from '../JavaPreset';
@@ -33,6 +35,15 @@ export const JAVA_CONSTRAINTS_PRESET: JavaPreset<JavaConstraintsPresetOptions> =
 
         const annotations: string[] = [];
 
+        // needs cascade validation
+        if (
+          property.property instanceof ConstrainedReferenceModel ||
+          property.property instanceof ConstrainedObjectModel ||
+          property.property instanceof ConstrainedArrayModel
+        ) {
+          annotations.push(renderer.renderAnnotation('Valid'));
+        }
+
         if (property.required) {
           annotations.push(renderer.renderAnnotation('NotNull'));
         }


Test patch:
diff --git a/test/generators/java/__snapshots__/JavaGenerator.spec.ts.snap b/test/generators/java/__snapshots__/JavaGenerator.spec.ts.snap
index 49481fc0..5f34dada 100644
--- a/test/generators/java/__snapshots__/JavaGenerator.spec.ts.snap
+++ b/test/generators/java/__snapshots__/JavaGenerator.spec.ts.snap
@@ -196,6 +196,7 @@ public interface Vehicle {
 exports[`JavaGenerator oneOf/discriminator with jackson preset date-time format should render java.time.OffsetDateTime 1`] = `
 Array [
   "public class Event {
+  @Valid
   @NotNull
   @JsonProperty(\\"action\\")
   private Action action;
@@ -311,6 +312,7 @@ public interface Pet {
   @NotNull
   @JsonProperty(\\"specversion\\")
   private final String specversion = \\"1.0\\";
+  @Valid
   @NotNull
   @JsonProperty(\\"type\\")
   private final CloudEventType type = CloudEventType.DOG;
@@ -431,6 +433,7 @@ public interface Pet {
   @NotNull
   @JsonProperty(\\"specversion\\")
   private final String specversion = \\"1.0\\";
+  @Valid
   @NotNull
   @JsonProperty(\\"type\\")
   private final CloudEventType type = CloudEventType.CAT;
@@ -521,6 +524,7 @@ Array [
   @NotNull
   @JsonProperty(\\"id\\")
   private String id;
+  @Valid
   @NotNull
   @JsonProperty(\\"type\\")
   private final CloudEventType type = CloudEventType.DOG;
@@ -623,6 +627,7 @@ public interface Pet {
   
 }",
   "public class Dog implements Pet {
+  @Valid
   @NotNull
   @JsonProperty(\\"type\\")
   private final DogType type = DogType.DOG;
@@ -704,6 +709,7 @@ public interface Pet {
   }
 }",
   "public class Cat implements Pet {
+  @Valid
   @NotNull
   @JsonProperty(\\"type\\")
   private final CatType type = CatType.CAT;
@@ -801,6 +807,7 @@ public interface Vehicle {
   VehicleType getVehicleType();
 }",
   "public class Cargo {
+  @Valid
   @JsonProperty(\\"vehicle\\")
   @JsonInclude(JsonInclude.Include.NON_NULL)
   private Vehicle vehicle;
@@ -854,6 +861,7 @@ public interface Vehicle {
   }
 }",
   "public class Car implements Vehicle {
+  @Valid
   @NotNull
   @JsonProperty(\\"vehicleType\\")
   private final VehicleType vehicleType = VehicleType.CAR;
@@ -935,6 +943,7 @@ public interface Vehicle {
   }
 }",
   "public class Truck implements Vehicle {
+  @Valid
   @NotNull
   @JsonProperty(\\"vehicleType\\")
   private final VehicleType vehicleType = VehicleType.TRUCK;
diff --git a/test/generators/java/presets/__snapshots__/ConstraintsPreset.spec.ts.snap b/test/generators/java/presets/__snapshots__/ConstraintsPreset.spec.ts.snap
index 5fa0e9b3..403d1373 100644
--- a/test/generators/java/presets/__snapshots__/ConstraintsPreset.spec.ts.snap
+++ b/test/generators/java/presets/__snapshots__/ConstraintsPreset.spec.ts.snap
@@ -30,6 +30,7 @@ exports[`JAVA_CONSTRAINTS_PRESET should render jakarta constraints annotations f
   @NotNull
   @Max(99)
   private double maxNumberProp;
+  @Valid
   @Size(min=2, max=3)
   private Object[] arrayProp;
   @Pattern(regexp=\\"^\\\\\\\\w+(\\\\\\"\\\\\\\\.\\\\\\\\w+)*$\\")
@@ -62,6 +63,7 @@ exports[`JAVA_CONSTRAINTS_PRESET should render javax constraints annotations by
   @NotNull
   @Max(99)
   private double maxNumberProp;
+  @Valid
   @Size(min=2, max=3)
   private Object[] arrayProp;
   @Pattern(regexp=\\"^\\\\\\\\w+(\\\\\\"\\\\\\\\.\\\\\\\\w+)*$\\")
@@ -94,6 +96,7 @@ exports[`JAVA_CONSTRAINTS_PRESET should render javax constraints annotations whe
   @NotNull
   @Max(99)
   private double maxNumberProp;
+  @Valid
   @Size(min=2, max=3)
   private Object[] arrayProp;
   @Pattern(regexp=\\"^\\\\\\\\w+(\\\\\\"\\\\\\\\.\\\\\\\\w+)*$\\")