Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • O openapi-generator
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 3,476
    • Issues 3,476
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 402
    • Merge requests 402
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • OpenAPI Tools
  • openapi-generator
  • Issues
  • #13938
Closed
Open
Issue created Nov 07, 2022 by Administrator@rootContributor

[FEATURE] [SPRING] Add support for custom beanValidation annotations

Created by: Mintas

Description

The feature is mostly inspired by https://bartko-mat.medium.com/openapi-generator-to-spring-boot-with-custom-java-validations-623381df9215

We want to be able to add our custom validation constraint annotations for java spring-based modules. Provide new vendor extension aka 'x-spring-constraint' and allow user-defined annotation class or package to be imported gracefully using configuration parameters (without any template customization).

This is extremely useful in combination with javax.validation.valueextraction.ValueExctractor , see https://javaee.github.io/javaee-spec/javadocs/javax/validation/valueextraction/package-summary.html

openapi-generator version

6.2.1 , current master

OpenAPI declaration file content or url
openapi: 3.0.3
info:
  version: 1.0.0
  description: Specification to show applicability of x-spring-constraint vendor extension
  title: XSpringConstraintTest Api
paths:
  /smth/add:
    get:
      parameters:
        - in: query
          name: quantity
          schema:
            type: integer
          x-spring-constraint: "@Positive"
          required: true
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: boolean
  /smth/remove:
    get:
      parameters:
        - in: query
          name: quantity
          schema:
            type: integer
          x-spring-constraint: "@NotZero(message = \"custom\")"
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: boolean

Plugin configuration:

generatorName = 'spring'
configOptions = [
    dateLibrary: 'java8',
    interfaceOnly: 'true',
    openApiNullable: 'false',
    java8: 'false',
    customValidationAnnotationsPackage: 'org.custom.validation.annotations.*'
]

as alternative we can set this property to contains class name to be imported:
customValidationAnnotationsPackage: 'org.custom.validation.annotations.NotZero'

Generates:

package xyz.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.Valid;
import javax.validation.constraints.*;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Generated;
import org.custom.validations.*;

@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2022-11-07T14:52:46.573574+03:00[Europe/Moscow]")
@Validated
@Tag(name = "smth", description = "the smth API")
public interface SmthApi {

    default Optional<NativeWebRequest> getRequest() {
        return Optional.empty();
    }

    /**
     * GET /smth/add
     *
     * @param quantity  (required)
     * @return OK (status code 200)
     */
    @Operation(operationId = "smthAddGet", responses = { @ApiResponse(responseCode = "200", description = "OK", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Boolean.class)) }) })
    @RequestMapping(method = RequestMethod.GET, value = "/smth/add", produces = { "application/json" })
    default ResponseEntity<Boolean> smthAddGet(@NotNull @Positive @Parameter(name = "quantity", description = "", required = true) @Valid @RequestParam(value = "quantity", required = true) Integer quantity) {
        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
    }

    /**
     * GET /smth/remove
     *
     * @param quantity  (optional)
     * @return OK (status code 200)
     */
    @Operation(operationId = "smthRemoveGet", responses = { @ApiResponse(responseCode = "200", description = "OK", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Boolean.class)) }) })
    @RequestMapping(method = RequestMethod.GET, value = "/smth/remove", produces = { "application/json" })
    default ResponseEntity<Boolean> smthRemoveGet(@NotZero(message = "custom") @Parameter(name = "quantity", description = "") @Valid @RequestParam(value = "quantity", required = false) Integer quantity) {
        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
    }
}

Added with proposed feature:

//lines omitted
import org.custom.validations.*;

//lines omitted
    default ResponseEntity<Boolean> smthAddGet(@NotNull @Positive/* other content omitted*/  Integer quantity) {
        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
    }
//lines omitted
    default ResponseEntity<Boolean> smthRemoveGet(@NotZero(message = "custom") /* other content omitted*/ Integer quantity) {
        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
    }
}
Command line used for generation
Steps to reproduce
Related issues/PRs
Suggest a fix/enhancement

will propose a solution as PR from fork repository https://github.com/Mintas/openapi-generator

Assignee
Assign to
Time tracking