Skip to content

Commit

Permalink
[issues#976] Fix api.qute condition to include jakarta constraint a…
Browse files Browse the repository at this point in the history
…nnotations to all endpoint parameters (#978)

* [issues#964] Fix beanValidationCore.qute condition to include the jakarta.validation.Valid annotation

* [issues#976] Fix api.qute condition to include constraint annotations to all endpoint params
  • Loading branch information
JPSantistebanQ authored Feb 4, 2025
1 parent fedd161 commit 2eabcb2
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class QuteTemplatingEngineAdapter extends AbstractTemplatingEngineAdapter
"additionalModelTypeAnnotations.qute",
"beanValidation.qute",
"beanValidationCore.qute",
"beanValidationInlineCore.qute",
"beanValidationHeaderParams.qute",
"bodyParams.qute",
"enumClass.qute",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,11 @@ public interface {classname} {
@org.jboss.resteasy.annotations.providers.multipart.MultipartForm {op.operationIdCamelCase}MultipartForm multipartForm{#if op.hasPathParams},{/if}
{/if}
{#if use-bean-validation}
{#for p in op.pathParams}@jakarta.validation.Valid {#include pathParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasQueryParams},{/if}
{#for p in op.queryParams}@jakarta.validation.Valid {#include queryParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasCookieParams},{/if}
{#for p in op.cookieParams}@jakarta.validation.Valid {#include cookieParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasHeaderParams},{/if}
{#for p in op.headerParams}@jakarta.validation.Valid {#include headerParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasBodyParam},
{#for p in op.bodyParams}@jakarta.validation.Valid {#include bodyParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{/if}
{#for p in op.pathParams}{#include beanValidationInlineCore.qute param=p/}{#include pathParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasQueryParams},{/if}
{#for p in op.queryParams}{#include beanValidationInlineCore.qute param=p/}{#include queryParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasCookieParams},{/if}
{#for p in op.cookieParams}{#include beanValidationInlineCore.qute param=p/}{#include cookieParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasHeaderParams},{/if}
{#for p in op.headerParams}{#include beanValidationInlineCore.qute param=p/}{#include headerParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasBodyParam},
{#for p in op.bodyParams}{#include beanValidationInlineCore.qute param=p/}{#include bodyParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{/if}
{#else}
{#for p in op.pathParams}{#include pathParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasQueryParams},{/if}
{#for p in op.queryParams}{#include queryParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasCookieParams},{/if}
Expand All @@ -149,7 +149,7 @@ public interface {classname} {
{/if}
{#else}
{#for p in op.allParams}
{#if use-bean-validation}@jakarta.validation.Valid {/if}{!
{#if use-bean-validation}{#include beanValidationInlineCore.qute param=p/}{/if}{!
!}{#include pathParams.qute param=p/}{#include queryParams.qute param=p/}{#include bodyParams.qute param=p/}{#include headerParams.qute param=p/}{#include cookieParams.qute param=p/}{#if p_hasNext}, {/if}
{/for}{/if}
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{#if p.required}@jakarta.validation.constraints.NotNull {/if}{#if p.pattern}@jakarta.validation.constraints.Pattern(regexp = "{p.pattern}") {/if}{#if p.minLength || p.minItems}@jakarta.validation.constraints.Size(min = {p.minLength}{p.minItems}) {/if}{#if p.maxLength || p.maxItems}@jakarta.validation.constraints.Size(max = {p.maxLength}{p.maxItems}) {/if}{#if p.isInteger}{#if p.minimum}@jakarta.validation.constraints.Min({p.minimum}) {/if}{#if p.maximum}@jakarta.validation.constraints.Max({p.maximum}) {/if}{/if}{#if p.isLong}{#if p.minimum}@jakarta.validation.constraints.Min({p.minimum}L) {/if}{#if p.maximum}@jakarta.validation.constraints.Max({p.maximum}L) {/if}{/if}{#if !p.isInteger && !p.isLong}{#if p.minimum}@jakarta.validation.constraints.DecimalMin("{p.minimum}") {/if}{#if p.maximum}@jakarta.validation.constraints.DecimalMax("{p.maximum}") {/if}{/if}{#if use-bean-validation}@jakarta.validation.Valid {/if}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
openapi: 3.0.3
info:
title: Test API
version: "1.0"
paths:
/{pathParam}:
post:
tags:
- ValidatedEndpointIssue976
operationId: test
parameters:
- name: queryParam
in: query
schema:
$ref: '#/components/schemas/ValidatedObjectIssue976'
- name: pathParam
in: path
description: pathParam description
required: true
schema:
type: string
maxLength: 14
minLength: 14
pattern: '^[0-9]{14}$'
example: '19318085994179'
- name: headerParam
in: header
description: 'Header description'
required: false
schema:
maxLength: 32
minLength: 32
pattern: '^[a-z0-9]{32}$'
type: string
example: 3cfdad6e03c24d0ab7112dce75cdba35
- name: cookieParam
in: cookie
required: true
schema:
type: string
minLength: 10
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ValidatedObjectIssue976'
responses:
"200":
description: OK
content:
text/plain:
schema:
type: string
components:
schemas:
ValidatedObjectIssue976:
type: object
description: Some object to be validated
required:
- id
- name
- secondName
- size
properties:
id:
type: integer
minimum: 1
maximum: 100
name:
type: string
pattern: "[a-zA-Z]*"
minLength: 1
maxLength: 10
secondName:
type: string
size:
type: number
minimum: 1.0
maximum: 10.0
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
quarkus.openapi-generator.codegen.spec.bean_validation_true_yaml.use-bean-validation = true
quarkus.openapi-generator.codegen.spec.issue_976_yaml.use-bean-validation = true
quarkus.openapi-generator.codegen.spec.bean_validation_false_yaml.use-bean-validation = false
quarkus.keycloak.devservices.enabled=false
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.stream.Stream;

Expand All @@ -16,12 +17,15 @@
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import jakarta.ws.rs.HeaderParam;
import jakarta.ws.rs.PathParam;

import org.junit.jupiter.api.Test;
import org.openapi.quarkus.bean_validation_false_yaml.api.UnvalidatedEndpointApi;
import org.openapi.quarkus.bean_validation_false_yaml.model.UnvalidatedObject;
import org.openapi.quarkus.bean_validation_true_yaml.api.ValidatedEndpointApi;
import org.openapi.quarkus.bean_validation_true_yaml.model.ValidatedObject;
import org.openapi.quarkus.issue_976_yaml.api.ValidatedEndpointIssue976Api;

import io.quarkus.test.junit.QuarkusTest;

Expand Down Expand Up @@ -99,4 +103,37 @@ void testValidationAnnotationsAreSkippedModel() throws Exception {
assertThat(size.isAnnotationPresent(DecimalMin.class)).isFalse();
assertThat(size.isAnnotationPresent(DecimalMax.class)).isFalse();
}

@Test
void testValidationAnnotationsAreInPlaceApiIssue976() {
Method method = ValidatedEndpointIssue976Api.class.getMethods()[0];
Annotation[][] annotationsPerParameter = method.getParameterAnnotations();

Parameter pathParam = Arrays.stream(method.getParameters())
.filter(p -> p.getName().equals("pathParam"))
.findFirst().get();

Parameter headerParam = Arrays.stream(method.getParameters())
.filter(p -> p.getName().equals("headerParam"))
.findFirst().get();

Boolean validationAnnotationExists = Arrays.stream(annotationsPerParameter)
.allMatch(annotations -> Arrays.stream(annotations)
.filter(a -> a.annotationType().equals(Valid.class)).toList()
.size() == 1);

assertThat(validationAnnotationExists).isTrue();

assertThat(pathParam.isAnnotationPresent(Valid.class)).isTrue();
assertThat(pathParam.isAnnotationPresent(NotNull.class)).isTrue();
assertThat(pathParam.isAnnotationPresent(Pattern.class)).isTrue();
assertThat(pathParam.isAnnotationPresent(Size.List.class)).isTrue();
assertThat(pathParam.isAnnotationPresent(PathParam.class)).isTrue();

assertThat(headerParam.isAnnotationPresent(Valid.class)).isTrue();
assertThat(headerParam.isAnnotationPresent(NotNull.class)).isFalse();
assertThat(headerParam.isAnnotationPresent(Size.List.class)).isTrue();
assertThat(headerParam.isAnnotationPresent(Pattern.class)).isTrue();
assertThat(headerParam.isAnnotationPresent(HeaderParam.class)).isTrue();
}
}

0 comments on commit 2eabcb2

Please sign in to comment.