[java][microprofile] Extend support for useOneOfInterfaces to the microprofile library when Jackson serialisation is enabled

Merged
IG
4mo ago
+1687-0

[java][microprofile] Support useOneOfInterfaces

The java client generator already supports oneOfInterface templating and it's currently used by the Spring library variants. This PR extends this to the Microprofile library when Jackson is selected for serialisation.

It renders a oneOf schema as a Java interface (implemented by its subtypes) for the microprofile library, instead of an unrelated pojo.

The microprofile library ships its own model.mustache and supports serializationLibrary=jackson and serialisationLibrary=jsonB. This PR guarantees support Jackson and JsonB will be verified in a follow up PR.

Add support for OneOfInterfaces to avoid having circular dependencies because the child schemas components extend a parent class that also has oneOf and mapping pointing to the children. Example:

   # -----------------------------------------------
   # Base schema in component that contains oneOf and mapping
   # Discriminator also lives here on the parent
   # Child classes have a circular dependency because allOf to the parent with the oneOf & mapping
   # PetRequest (mapping) -> CatRequest (allOf) -> PetRequest
   # -----------------------------------------------

   PetRequest:
     type: object
     required:
       - petType
       - name
     properties:
       petType:
         type: string
         enum:
           - CAT
           - DOG
       name:
         type: string
     discriminator:
       propertyName: petType
       mapping:
         CAT: '#/components/schemas/CatRequest'
         DOG: '#/components/schemas/DogRequest'

   CatRequest:
     type: object
     allOf:
       - $ref: '#/components/schemas/PetRequest'
       - type: object
         required:
           - breedType
           - petType
         properties:
           breedType:
             $ref: '#/components/schemas/CatBreedType'
   DogRequest:
     type: object
     allOf:
       - $ref: '#/components/schemas/PetRequest'
       - type: object
         properties:
           breedType:
             $ref: '#/components/schemas/DogBreedType'


   # -----------------------------------------------
   # Base schema a separate component
   # Discriminator lives in parent and base object until #24156 is merged
   # -----------------------------------------------

   PetRequestV2:
     type: object
     properties:
       petType:
         $ref: '#/components/schemas/PetType'      # --> This will removed once #24156 is merged
     oneOf:
       - $ref: '#/components/schemas/CatRequestV2'
       - $ref: '#/components/schemas/DogRequestV2'
     discriminator:
       propertyName: petType
       mapping:
         CAT: '#/components/schemas/CatRequestV2'
         DOG: '#/components/schemas/DogRequestV2'

   PetRequestV2Base:
       type: object
       required:
         - petType
         - name
       properties:
         petType:
           $ref: '#/components/schemas/PetType'
         name:
           type: string
   
   CatRequestV2:
     type: object
     allOf:
       - $ref: '#/components/schemas/PetRequestV2Base'
       - type: object
         properties:
           breedType:
             $ref: '#/components/schemas/CatBreedType'
          

   DogRequestV2:
     type: object
     allOf:
       - $ref: '#/components/schemas/PetRequestV2Base'
       - type: object
         properties:
           breedType:
             $ref: '#/components/schemas/DogBreedType'

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Extends useOneOfInterfaces to the Java MicroProfile client when serializationLibrary=jackson, rendering oneOf schemas as interfaces implemented by subtypes. Adds a MicroProfile sample and CI coverage.

  • New Features
    • Route MicroProfile model.mustache to the shared oneof_interface template via vendorExtensions.x-is-one-of-interface when useOneOfInterfaces=true and serializationLibrary=jackson; fall back to pojo otherwise.
    • Added a minimal fixture (modules/openapi-generator/src/test/resources/3_0/java/oneof_interface_petstore.yaml), generator config (bin/configs/java-microprofile-oneof-interface.yaml, MicroProfile Rest Client 3.0), a JavaClientCodegenTest, and a sample at samples/client/petstore/java/microprofile-oneof-interface.
    • The test verifies the oneOf container is an interface, children implement it, the discriminator getter returns the enum type, and interfaces are non-sealed by default.
    • Added the sample to the Java client JDK 11 samples workflow.
    • useSealedOneOfInterfaces is not enabled; jsonb is not supported yet.