Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tags in swagger yaml breaks nodejs generated server #2423

Open
djskinner opened this issue Mar 21, 2016 · 17 comments
Open

Tags in swagger yaml breaks nodejs generated server #2423

djskinner opened this issue Mar 21, 2016 · 17 comments

Comments

@djskinner
Copy link

I have been having a hard time using the generated nodejs server to build a mock API based on my swagger yaml file. It turns out that my use of tags in the yaml causes the generated server to have multiples of the controllers I am expecting.

If I add a single tag as follows:

      tags:
        - HTTP Request

Then when making an API request with the generated server I get the following error

Error: Cannot resolve the configured swagger-router handler: HTTP Request_shopsShopIdTransactionsGET

Removing the tag will allow the server to identify the correct controller and respond.

@wing328
Copy link
Contributor

wing328 commented Mar 21, 2016

Currently, the Tag is split based on " " (space): https://github.com/meshkorea/swagger-codegen/blob/master/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java#L689

If you change "HTTP Request" to "HttpRequest", would that work for you?

@djskinner
Copy link
Author

If you change "HTTP Request" to "HttpRequest", would that work for you?

Yes, this solved it. As long as there are no spaces in tags it will work, even for multiple tags.

Why does the codegen create duplicate controllers for each tab?

@wing328
Copy link
Contributor

wing328 commented Mar 21, 2016

Sorry I don't have an answer for that as I'm not the one who created the NodeJS server stub generator.

For multiple tags, what's your expected output? Only using the first tag to generate the controller?

@djskinner
Copy link
Author

I guess so, I'm not entirely sure why tags ought to affect the output. I'll do a little more research and get back to you if there is anything of use.

It would definitely be worth validating/warning on the space in a tag issue as it might save someone else some head scratching.

@wing328
Copy link
Contributor

wing328 commented Mar 21, 2016

Agree with you that a warning about multiple tags due to space would be helpful to nodejs users.

@wing328 wing328 added this to the v2.2.0 milestone May 21, 2016
@Lotti
Copy link

Lotti commented May 31, 2016

It creates multiple controllers where multiple tags are present...
I thought controllers were made by using the x-swagger-router-controller specific parameter!!

swagger: "2.0"
info:
  description: |
    This is a sample server Petstore server.

    [Learn about Swagger](http://swagger.io) or join the IRC channel `#swagger` on irc.freenode.net.

    For this sample, you can use the api key `special-key` to test the authorization filters
  version: "1.0.0"
  title: Swagger Petstore
  termsOfService: http://helloreverb.com/terms/
  contact:
    name: apiteam@swagger.io
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
host: petstore.swagger.io
basePath: /v2
schemes:
  - http
paths:
  /pets:
    post:
      tags:
        - pet
        - petAAAA
        - petBBBB
        - petCCCC
        - petDDDD
      summary: Add a new pet to the store
      description: ""
      operationId: addPet
      consumes:
        - application/json
        - application/xml
      produces:
        - application/json
        - application/xml
      parameters:
        - in: body
          name: body
          description: Pet object that needs to be added to the store
          required: false
          schema:
            $ref: "#/definitions/Pet"
      responses:
        "405":
          description: Invalid input
      security:
        - petstore_auth:
          - write_pets
          - read_pets
    put:
      tags:
        - pet
      summary: Update an existing pet
      description: ""
      operationId: updatePet
      consumes:
        - application/json
        - application/xml
      produces:
        - application/json
        - application/xml
      parameters:
        - in: body
          name: body
          description: Pet object that needs to be added to the store
          required: false
          schema:
            $ref: "#/definitions/Pet"
      responses:
        "405":
          description: Validation exception
        "404":
          description: Pet not found
        "400":
          description: Invalid ID supplied
      security:
        - petstore_auth:
          - write_pets
          - read_pets
  /pets/findByStatus:
    get:
      tags:
        - pet
      summary: Finds Pets by status
      description: Multiple status values can be provided with comma seperated strings
      operationId: findPetsByStatus
      produces:
        - application/json
        - application/xml
      parameters:
        - in: query
          name: status
          description: Status values that need to be considered for filter
          required: false
          type: array
          items:
            type: string
          collectionFormat: multi
      responses:
        "200":
          description: successful operation
          schema:
            type: array
            items:
              $ref: "#/definitions/Pet"
        "400":
          description: Invalid status value
      security:
        - petstore_auth:
          - write_pets
          - read_pets
  /pets/findByTags:
    get:
      tags:
        - pet
      summary: Finds Pets by tags
      description: Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.
      operationId: findPetsByTags
      produces:
        - application/json
        - application/xml
      parameters:
        - in: query
          name: tags
          description: Tags to filter by
          required: false
          type: array
          items:
            type: string
          collectionFormat: multi
      responses:
        "200":
          description: successful operation
          schema:
            type: array
            items:
              $ref: "#/definitions/Pet"
        "400":
          description: Invalid tag value
      security:
        - petstore_auth:
          - write_pets
          - read_pets
  /pets/{petId}:
    get:
      tags:
        - pet
      summary: Find pet by ID
      description: Returns a pet when ID < 10.  ID > 10 or nonintegers will simulate API error conditions
      operationId: getPetById
      produces:
        - application/json
        - application/xml
      parameters:
        - in: path
          name: petId
          description: ID of pet that needs to be fetched
          required: true
          type: integer
          format: int64
      responses:
        "404":
          description: Pet not found
        "200":
          description: successful operation
          schema:
            $ref: "#/definitions/Pet"
        "400":
          description: Invalid ID supplied
      security:
        - api_key: []
        - petstore_auth:
          - write_pets
          - read_pets
    post:
      tags:
        - pet
      summary: Updates a pet in the store with form data
      description: ""
      operationId: updatePetWithForm
      consumes:
        - application/x-www-form-urlencoded
      produces:
        - application/json
        - application/xml
      parameters:
        - in: path
          name: petId
          description: ID of pet that needs to be updated
          required: true
          type: string
        - in: formData
          name: name
          description: Updated name of the pet
          required: true
          type: string
        - in: formData
          name: status
          description: Updated status of the pet
          required: true
          type: string
      responses:
        "405":
          description: Invalid input
      security:
        - petstore_auth:
          - write_pets
          - read_pets
    delete:
      tags:
        - pet
      summary: Deletes a pet
      description: ""
      operationId: deletePet
      produces:
        - application/json
        - application/xml
      parameters:
        - in: header
          name: api_key
          description: ""
          required: true
          type: string
        - in: path
          name: petId
          description: Pet id to delete
          required: true
          type: integer
          format: int64
      responses:
        "400":
          description: Invalid pet value
      security:
        - petstore_auth:
          - write_pets
          - read_pets
  /stores/order:
    post:
      tags:
        - store
      summary: Place an order for a pet
      description: ""
      operationId: placeOrder
      produces:
        - application/json
        - application/xml
      parameters:
        - in: body
          name: body
          description: order placed for purchasing the pet
          required: false
          schema:
            $ref: "#/definitions/Order"
      responses:
        "200":
          description: successful operation
          schema:
            $ref: "#/definitions/Order"
        "400":
          description: Invalid Order
  /stores/order/{orderId}:
    get:
      tags:
        - store
      summary: Find purchase order by ID
      description: For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions
      operationId: getOrderById
      produces:
        - application/json
        - application/xml
      parameters:
        - in: path
          name: orderId
          description: ID of pet that needs to be fetched
          required: true
          type: string
      responses:
        "404":
          description: Order not found
        "200":
          description: successful operation
          schema:
            $ref: "#/definitions/Order"
        "400":
          description: Invalid ID supplied
    delete:
      tags:
        - store
      summary: Delete purchase order by ID
      description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
      operationId: deleteOrder
      produces:
        - application/json
        - application/xml
      parameters:
        - in: path
          name: orderId
          description: ID of the order that needs to be deleted
          required: true
          type: string
      responses:
        "404":
          description: Order not found
        "400":
          description: Invalid ID supplied
  /users:
    post:
      tags:
        - user
      summary: Create user
      description: This can only be done by the logged in user.
      operationId: createUser
      produces:
        - application/json
        - application/xml
      parameters:
        - in: body
          name: body
          description: Created user object
          required: false
          schema:
            $ref: "#/definitions/User"
      responses:
        default:
          description: successful operation
  /users/createWithArray:
    post:
      tags:
        - user
      summary: Creates list of users with given input array
      description: ""
      operationId: createUsersWithArrayInput
      produces:
        - application/json
        - application/xml
      parameters:
        - in: body
          name: body
          description: List of user object
          required: false
          schema:
            type: array
            items:
              $ref: "#/definitions/User"
      responses:
        default:
          description: successful operation
  /users/createWithList:
    post:
      tags:
        - user
      summary: Creates list of users with given input array
      description: ""
      operationId: createUsersWithListInput
      produces:
        - application/json
        - application/xml
      parameters:
        - in: body
          name: body
          description: List of user object
          required: false
          schema:
            type: array
            items:
              $ref: "#/definitions/User"
      responses:
        default:
          description: successful operation
  /users/login:
    get:
      tags:
        - user
      summary: Logs user into the system
      description: ""
      operationId: loginUser
      produces:
        - application/json
        - application/xml
      parameters:
        - in: query
          name: username
          description: The user name for login
          required: false
          type: string
        - in: query
          name: password
          description: The password for login in clear text
          required: false
          type: string
      responses:
        "200":
          description: successful operation
          schema:
            type: string
        "400":
          description: Invalid username/password supplied
  /users/logout:
    get:
      tags:
        - user
      summary: Logs out current logged in user session
      description: ""
      operationId: logoutUser
      produces:
        - application/json
        - application/xml
      responses:
        default:
          description: successful operation
  /users/{username}:
    get:
      tags:
        - user
      summary: Get user by user name
      description: ""
      operationId: getUserByName
      produces:
        - application/json
        - application/xml
      parameters:
        - in: path
          name: username
          description: The name that needs to be fetched. Use user1 for testing.
          required: true
          type: string
      responses:
        "404":
          description: User not found
        "200":
          description: successful operation
          schema:
            $ref: "#/definitions/User"
        "400":
          description: Invalid username supplied
    put:
      tags:
        - user
      summary: Updated user
      description: This can only be done by the logged in user.
      operationId: updateUser
      produces:
        - application/json
        - application/xml
      parameters:
        - in: path
          name: username
          description: name that need to be deleted
          required: true
          type: string
        - in: body
          name: body
          description: Updated user object
          required: false
          schema:
            $ref: "#/definitions/User"
      responses:
        "404":
          description: User not found
        "400":
          description: Invalid user supplied
    delete:
      tags:
        - user
      summary: Delete user
      description: This can only be done by the logged in user.
      operationId: deleteUser
      produces:
        - application/json
        - application/xml
      parameters:
        - in: path
          name: username
          description: The name that needs to be deleted
          required: true
          type: string
      responses:
        "404":
          description: User not found
        "400":
          description: Invalid username supplied
securityDefinitions:
  api_key:
    type: apiKey
    name: api_key
    in: header
  petstore_auth:
    type: oauth2
    authorizationUrl: http://petstore.swagger.io/api/oauth/dialog
    flow: implicit
    scopes:
      write_pets: modify pets in your account
      read_pets: read your pets
definitions:
  User:
    type: object
    properties:
      id:
        type: integer
        format: int64
      username:
        type: string
      firstName:
        type: string
      lastName:
        type: string
      email:
        type: string
      password:
        type: string
      phone:
        type: string
      userStatus:
        type: integer
        format: int32
        description: User Status
  Category:
    type: object
    properties:
      id:
        type: integer
        format: int64
      name:
        type: string
  Pet:
    type: object
    required:
      - name
      - photoUrls
    properties:
      id:
        type: integer
        format: int64
      category:
        $ref: "#/definitions/Category"
      name:
        type: string
        example: doggie
      photoUrls:
        type: array
        items:
          type: string
      tags:
        type: array
        items:
          $ref: "#/definitions/Tag"
      status:
        type: string
        description: pet status in the store
  Tag:
    type: object
    properties:
      id:
        type: integer
        format: int64
      name:
        type: string
  Order:
    type: object
    properties:
      id:
        type: integer
        format: int64
      petId:
        type: integer
        format: int64
      quantity:
        type: integer
        format: int32
      shipDate:
        type: string
        format: date-time
      status:
        type: string
        description: Order Status
      complete:
        type: boolean

@fehguy
Copy link
Contributor

fehguy commented May 31, 2016

We should follow the Java pattern where the first tag is used for routing. The controller extension should win, though, and avoid that logic altogether

@Lotti
Copy link

Lotti commented May 31, 2016

If not tag is specified and x-swagger-router-controller is available, the generator keeps acting in a very strange way... every api is bundled in just one controller named "default"...

@wing328
Copy link
Contributor

wing328 commented Jun 1, 2016

@Lotti Here is the logic related to x-swagger-router-controller in NodeJS generator.

// need vendor extensions for x-swagger-router-controller
Map<String, Path> paths = swagger.getPaths();
if(paths != null) {
for(String pathname : paths.keySet()) {
Path path = paths.get(pathname);
Map<HttpMethod, Operation> operationMap = path.getOperationMap();
if(operationMap != null) {
for(HttpMethod method : operationMap.keySet()) {
Operation operation = operationMap.get(method);
String tag = "default";
if(operation.getTags() != null && operation.getTags().size() > 0) {
tag = toApiName(operation.getTags().get(0));
}
if(operation.getOperationId() == null) {
operation.setOperationId(getOrGenerateOperationId(operation, pathname, method.toString()));
}
if(operation.getVendorExtensions().get("x-swagger-router-controller") == null) {
operation.getVendorExtensions().put("x-swagger-router-controller", sanitizeTag(tag));
}
}
}
}
}
}

Would you have cycle to contribute a fix?

@Lotti
Copy link

Lotti commented Jun 1, 2016

I have to setup all the environment for develop with java... probably later in the week. Is there a favourite ide?

@wing328
Copy link
Contributor

wing328 commented Jun 1, 2016

Eclipse works for me

@wing328
Copy link
Contributor

wing328 commented Jun 20, 2016

@Lotti do you need help filing a fix/PR?

@wing328 wing328 modified the milestones: v2.2.0, v2.3.0 Jul 7, 2016
@wing328 wing328 modified the milestones: v2.2.1, v2.2.2 Aug 8, 2016
@wing328 wing328 modified the milestones: v2.2.2, Future Feb 15, 2017
@wing328 wing328 modified the milestones: Future, v2.2.2 Feb 15, 2017
@YathendraPrasad
Copy link

Hi @wing328 ,

i have

"tags":[ "Add Documents" ],

in my JSON file and the customized JavaJaxRS code for this is in api.mustache file is

com.ibm.mfp.adapters.sample.api.{{#vendorExtensions.x-tags}}{{tag}}{{#hasMore}}{{/hasMore}}{{/vendorExtensions.x-tags}}Api apiInstance = new com.ibm.mfp.adapters.sample.api.{{#vendorExtensions.x-tags}}{{tag}}{{#hasMore}}{{/hasMore}}{{/vendorExtensions.x-tags}}Api(apiAuthInstance);

and the generated code is

com.ibm.mfp.adapters.sample.api.Documents spaceApi apiInstance = new com.ibm.mfp.adapters.sample.api.Add DocumentsApi(apiAuthInstance);

can you please let me know how to remove the space between the string given in the "tags" . i mean the modification that i have to do in api.mustache file

Hoping for early reply as i am stuck with this and could not proceed further
Thanks in advance

@YathendraPrasad
Copy link

Hi ,

Any update on this will be helpful

Thanks

@YathendraPrasad
Copy link

Hi @webron ,

can you please comment on this , really helpful

Thanks

@YathendraPrasad
Copy link

Adding @fehguy

@NathanHazout
Copy link

Old thread.

Using multiple tags generates multiple controllers/services with the exact same API. Is this the correct issue or should I create a new one?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants