Forum Discussion

doncarlito87's avatar
doncarlito87
New Contributor
4 years ago

Why does multi openAPI yaml not work? Spring Boot, Maven, OpenApi

I have the following problem. I want to create several smaller interfaces from an OpenAPI.yaml. The OpenAPI.yaml serves as the top-level yaml file and this should contain all the necessary references to point to the other interfaces. But now I get the error shown below. Does anyone have a solution for this problem?

My top-level openAPI.yaml

 

openapi: 3.0.1
info:
  description: "REST resources for Test"
  version: "1.0.0"
  title: "Test"
servers:
  - url: 'http://localhost:8080'
    description: local dev environment
tags:
  - name: openApi Top-Level
    description: Top-Level OpenApi.yaml
paths:
  /:
    get:
      tags:
        - home
      summary: loads the homepage
      description: loads the homepage
      operationId: loadIndex
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: string
        '400':
          description: Invalid status value
          content: {}
  /user:
    $ref: 'user.yaml#/user'
  /user/createWithArray:
    $ref: 'user.yaml#/user-createWithArray'
  /user/createWithList:
    $ref: 'user.yaml#/user-createWithList'
  /user/login:
    $ref: 'user.yaml#/user-login'
  /user/logout:
    $ref: 'user.yaml#/user-logout'
  /version:
    $ref: 'pet.api.yaml#/version'
  /version/findAllByOrderByReleasedateAsc:
    $ref: 'version.yaml#/version-findAllByOrderByReleasedateAsc'
  /version/findAllByOrderByReleasedateDesc:
    $ref: 'version.yaml#/version-findAllByOrderByReleasedateDesc'
  /version/currentVersion:
    $ref: 'version.yaml#/version-currentVersion'
  /version/{versionId}:
    $ref: 'version.yaml#/version-versionId'
components:
  schemas:
    StructureProperty:
      $ref: 'structureGroup.yaml#/StructureProperty'
    Structure:
      $ref: 'structureGroup.yaml#/Structure'
    StructureGroup:
      $ref: 'structureGroup.yaml#/StructureGroup'
    StructureGroupLocation:
      $ref: 'structureGroupLocation.yaml#/StructureGroupLocation'
    User:
      $ref: 'user.yaml#/User'
    Version:  
      $ref: 'version.yaml#/Version'
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic

 

My user.yaml file

 

openapi: 3.0.1
info:
  description: "REST resources for Test2"
  version: "1.0.0"
  title: "Test2"
servers:
  - url: 'http://localhost:8080'
    description: local dev environment
tags:
  - name: user
    description: Everything about the users

paths:
  /user:
    get:
      tags:
      - "user"
      operationId: "getUsers"
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'
      security:
        - basicAuth: []
    post:
      tags:
        - user
      summary: Create user
      description: This can only be done by the logged in user.
      operationId: createUser
      requestBody:
        description: Created user object
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
        required: true
      responses:
        '405':
          description: Invalid input
          content: {}
      security:
        - basicAuth: []
      x-codegen-request-body-name: body
  /user/createWithArray:
    post:
      tags:
        - user
      summary: Creates list of users with given input array
      operationId: createUsersWithArrayInput
      requestBody:
        description: List of user object
        content:
          '*/*':
            schema:
              type: array
              items:
                $ref: '#/components/schemas/User'
        required: true
      responses:
        default:
          description: successful operation
          content: {}
      x-codegen-request-body-name: body
  /user/createWithList:
    post:
      tags:
        - user
      summary: Creates list of users with given input array
      operationId: createUsersWithListInput
      requestBody:
        description: List of user object
        content:
          '*/*':
            schema:
              type: array
              items:
                $ref: '#/components/schemas/User'
        required: true
      responses:
        default:
          description: successful operation
          content: {}
      x-codegen-request-body-name: body
  /user/login:
    get:
      tags:
        - user
      summary: Logs user into the system
      operationId: loginUser
      parameters:
        - name: username
          in: query
          description: The user name for login
          required: true
          schema:
            type: string
        - name: password
          in: query
          description: The password for login in clear text
          required: true
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          headers:
            X-Rate-Limit:
              description: calls per hour allowed by the user
              schema:
                type: integer
                format: int32
            X-Expires-After:
              description: date in UTC when token expires
              schema:
                type: string
                format: date-time
          content:
            application/json:
              schema:
                type: string
        '400':
          description: Invalid username/password supplied
          content: {}
  /user/logout:
    get:
      tags:
        - user
      summary: Logs out current logged in user session
      operationId: logoutUser
      responses:
        default:
          description: successful operation
          content: {}
  '/user/{id}':
    get:
      tags:
        - user
      summary: Get user by user id
      operationId: getUserById
      parameters:
        - name: id
          in: path
          description: 'The id that needs to be fetched. '
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: successful operation
          content: 
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '400':
          description: Invalid user id supplied
          content: {}
        '404':
          description: User not found
          content: {}
    put:
      tags:
        - user
      summary: Updated user
      description: This can only be done by the logged in user.
      operationId: updateUserById
      parameters:
        - name: id
          in: path
          description: id that need to be updated
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        description: Updated user object
        content:
          '*/*':
            schema:
              $ref: '#/components/schemas/User'
        required: true
      responses:
        '400':
          description: Invalid user id supplied
          content: {}
        '404':
          description: User not found
          content: {}
      x-codegen-request-body-name: body
    delete:
      tags:
        - user
      summary: Delete user
      description: This can only be done by the logged in user.
      operationId: deleteUserById
      parameters:
        - name: id
          in: path
          description: The id of the user that needs to be deleted
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '400':
          description: Invalid user id supplied
          content: {}
        '404':
          description: User not found
          content: {}
      security:
        - basicAuth: []
components:
  schemas:
    User:
      required:
        - id
        - username
        - email
        - password
        - role
      type: object
      properties:
        id:
          type: integer
          format: int64
        username:
          type: string
          example: "toencript"
        firstName:
          type: string
          example: "to"
        lastName:
          type: string
          example: "encript"
        email:
          type: string
          example: "toencript@toencript.com"
        password:
          type: string
          example: "toencript"
        role:  
          type: string 
          example: "ADMIN"
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic

 

 My Plugin:

 

<plugin>
                <!-- Generate the classes from open api -->
                <groupId>org.openapitools</groupId>
                <artifactId>openapi-generator-maven-plugin</artifactId>
                <version>5.1.1</version>
                <executions>
                    <execution>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <inputSpec>${project.basedir}/src/main/resources/openapi.yaml</inputSpec>
                            <generatorName>spring</generatorName>
                            <supportingFilesToGenerate>
                                ApiUtil.java
                            </supportingFilesToGenerate>
                            <configOptions>
                                <delegatePattern>true</delegatePattern>
                                <interfaceOnly>true</interfaceOnly>
                            </configOptions>
                            <modelPackage>${project.groupId}.openapi.DTO</modelPackage>
                            <apiPackage>${project.groupId}.openapi.api</apiPackage>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

 

 My Error Message:

 

[ERROR] Failed to execute goal org.openapitools:openapi-generator-maven-plugin:5.1.1:generate (default) on project service: Code generation failed. See
 above for the full exception. -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

[WARNING] Exception while resolving:
java.lang.RuntimeException: Unable to load RELATIVE ref: user path: D:\Repositories\service\src\main\resources
    at io.swagger.v3.parser.util.RefUtils.readExternalRef (RefUtils.java:239)
    at io.swagger.v3.parser.ResolverCache.loadRef (ResolverCache.java:119)
    at io.swagger.v3.parser.processors.ExternalRefProcessor.processRefToExternalPathItem (ExternalRefProcessor.java:237)
    at io.swagger.v3.parser.processors.PathsProcessor.processReferencePath (PathsProcessor.java:299)
    at io.swagger.v3.parser.processors.PathsProcessor.processPaths (PathsProcessor.java:63)
    at io.swagger.v3.parser.OpenAPIResolver.resolve (OpenAPIResolver.java:49)
    at io.swagger.v3.parser.OpenAPIV3Parser.resolve (OpenAPIV3Parser.java:175)
    at io.swagger.v3.parser.OpenAPIV3Parser.readContents (OpenAPIV3Parser.java:154)
    at io.swagger.v3.parser.OpenAPIV3Parser.readLocation (OpenAPIV3Parser.java:89)
    at io.swagger.parser.OpenAPIParser.readLocation (OpenAPIParser.java:16)
    at org.openapitools.codegen.config.CodegenConfigurator.toContext (CodegenConfigurator.java:523)
    at org.openapitools.codegen.config.CodegenConfigurator.toClientOptInput (CodegenConfigurator.java:573)
    at org.openapitools.codegen.plugin.CodeGenMojo.execute (CodeGenMojo.java:731)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:972)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:293)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:196)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: java.lang.RuntimeException: Could not find structureGroupLocation on the classpath
    at io.swagger.v3.parser.util.ClasspathHelper.loadFileFromClasspath (ClasspathHelper.java:31)
    at io.swagger.v3.parser.util.RefUtils.readExternalRef (RefUtils.java:233)
    at io.swagger.v3.parser.ResolverCache.loadRef (ResolverCache.java:119)
    at io.swagger.v3.parser.processors.ExternalRefProcessor.processRefToExternalPathItem (ExternalRefProcessor.java:237)
    at io.swagger.v3.parser.processors.PathsProcessor.processReferencePath (PathsProcessor.java:299)
    at io.swagger.v3.parser.processors.PathsProcessor.processPaths (PathsProcessor.java:63)
    at io.swagger.v3.parser.OpenAPIResolver.resolve (OpenAPIResolver.java:49)
    at io.swagger.v3.parser.OpenAPIV3Parser.resolve (OpenAPIV3Parser.java:175)
    at io.swagger.v3.parser.OpenAPIV3Parser.readContents (OpenAPIV3Parser.java:154)
    at io.swagger.v3.parser.OpenAPIV3Parser.readLocation (OpenAPIV3Parser.java:89)
    at io.swagger.parser.OpenAPIParser.readLocation (OpenAPIParser.java:16)
    at org.openapitools.codegen.config.CodegenConfigurator.toContext (CodegenConfigurator.java:523)
    at org.openapitools.codegen.config.CodegenConfigurator.toClientOptInput (CodegenConfigurator.java:573)
    at org.openapitools.codegen.plugin.CodeGenMojo.execute (CodeGenMojo.java:731)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:972)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:293)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:196)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
[WARNING] D:\Repositories\service\src\main\resources\openapi.yaml [0:0]: unexpected error in Open-API generation
org.openapitools.codegen.SpecValidationException: There were issues with the specification. The option can be disabled via validateSpec (Maven/Gradle) or --skip-valid
ate-spec (CLI).
 | Error count: 1, Warning count: 6
Errors:
        -Unable to load RELATIVE ref: user path: D:\Repositories\service\src\main\resources
Warnings:
        -Unable to load RELATIVE ref: user path: D:\Repositories\service\src\main\resources

 

 

  • HKosova's avatar
    HKosova
    SmartBear Alumni (Retired)

    Try this:

    paths:
      ...
    
      /user:
        $ref: 'user.yaml#/paths/~1user'
      /user/createWithArray:
        $ref: 'user.yaml#/paths/~1user~1createWithArray'
      /user/createWithList:
        $ref: 'user.yaml#/paths/~1user~1createWithList'
      /user/login:
        $ref: 'user.yaml#/paths/~1user~1login'
      /user/logout:
        $ref: 'user.yaml#/paths/~1user~1logout'
    
      # etc.
    
    
    components:
      schemas:
        ...
    
        User:
          $ref: 'user.yaml#/components/schemas/User'
        
        # etc.

     

    Note that path references look like

    $ref: 'user.yaml#/paths/~1user~1createWithArray'

    The part after #/ must specify the full "path" to the referenced node from the root of the file, hence the #/paths/... part. Endpoint names such as /user/createWithArray are written as ~1user~1createWithArray because the literal / characters in node names must be escaped as ~1 (see "Encoding $ref values" in this post).

     
    • doncarlito87's avatar
      doncarlito87
      New Contributor

      Hey thanks for your answer. I have modified my OpenApi yaml file as you described.

      /structure/{structureId}:
          $ref: 'structureGroup.yaml#/paths/~1structure~1structureId'
        /structureGroup/listAllNames:
          $ref: 'structureGroup.yaml#/paths/~1structureGroup~1listAllNames'
        /structureGroup/{structureGroupId}:
          $ref: 'structureGroup.yaml#/paths/~1structureGroup~1structureGroupId'
        /structureGroup/location/{structureGroupId}:
          $ref: 'structureGroupLocation#/paths/~1structureGroup~1location~1structureGroupId'
        /structureGroup/allLocation:
          $ref: 'structureGroupLocation#/paths/~1structureGroup~1allLocation'
        /user:
          $ref: 'user.yaml#/paths~1user'
        /user/createWithArray:
          $ref: 'user.yaml#/paths~1user/~1createWithArray'
        /user/createWithList:
          $ref: 'user.yaml#/paths~1user/~1createWithList'
        /user/login:
          $ref: 'user.yaml#/paths~1user/~1login'
        /user/logout:
          $ref: 'user.yaml#/paths~1user/~1logout'
        /version:
          $ref: 'version.yaml#/paths~1version'
        /version/findAllByOrderByReleasedateAsc:
          $ref: 'version.yaml#/paths/~1version~1findAllByOrderByReleasedateAsc'
        /version/findAllByOrderByReleasedateDesc:
          $ref: 'version.yaml#/paths/~1version~1findAllByOrderByReleasedateDesc'
        /version/currentVersion:
          $ref: 'version.yaml#/paths/~1version~1currentVersion'
        /version/{versionId}:
          $ref: 'version.yaml#/paths/~1version~1versionId'

       

      components:
        schemas:
          StructureProperty:
            $ref: 'structureGroup.yaml#/components/schemas/StructureProperty'
          Structure:
            $ref: 'structureGroup.yaml#/components/schemas/Structure'
          StructureGroup:
            $ref: 'structureGroup.yaml#/components/schemas/StructureGroup'
          StructureGroupLocation:
            $ref: 'structureGroupLocation.yaml#/components/schemas/StructureGroupLocation'
          User:
            $ref: 'user.yaml#/components/schemas/User'
          Version:  
            $ref: 'version.yaml#/components/schemas/Version'

       

      But i am still getting the following error

       

      [ERROR] Failed to execute goal org.openapitools:openapi-generator-maven-plugin:5.1.1:generate (default) on project proinfra-basis-service: Code generation failed. See
       above for the full exception. -> [Help 1]
      [ERROR]
      [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
      [ERROR] Re-run Maven using the -X switch to enable full debug logging.
      [ERROR]
      [ERROR] For more information about the errors and possible solutions, please read the following articles:
      [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

       

      The errors concerning the paths have already disappeared.
      What surprises me is that in paths of the top-level yaml file everything is written in the same color. Normally it is the path has one color and the reference another or (see image)?