Skip to content

swagger-codegen: SwaggerCompatConverter throws NPE due to TRACE HTTP // no handling of duplicate nicknames #612

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

Closed
jfiala opened this issue Apr 9, 2015 · 18 comments

Comments

@jfiala
Copy link
Contributor

jfiala commented Apr 9, 2015

With this api-doc (generated using the Basic Error Controller of the Swagger Spring-MVC project at https://github.com/springfox/springfox with com.mangofactory:swagger-springmvc-1.0.2)
SwaggerCompatConverter (Swagger-Codegen 2.1.2-M1) will throw an NPE:

com.wordnik.swagger.codegen.Codegen -i http://localhost:8080/api-docs -l java

java.lang.NullPointerException
at io.swagger.parser.SwaggerCompatConverter.convert(SwaggerCompatConverter.java:455)
at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:111)
at io.swagger.parser.SwaggerParser.read(SwaggerParser.java:34)
at com.wordnik.swagger.codegen.Codegen.main(Codegen.java:93)

Full API-doc:

{
    "apiVersion": "1.0",
    "apis": [
        {
            "description": "error",
            "operations": [
                {
                    "method": "GET",
                    "summary": "error",
                    "notes": "error",
                    "nickname": "error",
                    "produces": ["*/*"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "Map«string,object»"
                        }
                    ],
                    "deprecated": "false",
                    "type": "Map«string,object»"
                }, {
                    "method": "HEAD",
                    "summary": "error",
                    "notes": "error",
                    "nickname": "error",
                    "produces": ["*/*"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "Map«string,object»"
                        }
                    ],
                    "deprecated": "false",
                    "type": "Map«string,object»"
                }, {
                    "method": "POST",
                    "summary": "error",
                    "notes": "error",
                    "nickname": "error",
                    "produces": ["*/*"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "Map«string,object»"
                        }
                    ],
                    "deprecated": "false",
                    "type": "Map«string,object»"
                }, {
                    "method": "PUT",
                    "summary": "error",
                    "notes": "error",
                    "nickname": "error",
                    "produces": ["*/*"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "Map«string,object»"
                        }
                    ],
                    "deprecated": "false",
                    "type": "Map«string,object»"
                }, {
                    "method": "PATCH",
                    "summary": "error",
                    "notes": "error",
                    "nickname": "error",
                    "produces": ["*/*"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "Map«string,object»"
                        }
                    ],
                    "deprecated": "false",
                    "type": "Map«string,object»"
                }, {
                    "method": "DELETE",
                    "summary": "error",
                    "notes": "error",
                    "nickname": "error",
                    "produces": ["*/*"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "Map«string,object»"
                        }
                    ],
                    "deprecated": "false",
                    "type": "Map«string,object»"
                }, {
                    "method": "OPTIONS",
                    "summary": "error",
                    "notes": "error",
                    "nickname": "error",
                    "produces": ["*/*"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "Map«string,object»"
                        }
                    ],
                    "deprecated": "false",
                    "type": "Map«string,object»"
                }, {
                    "method": "TRACE",
                    "summary": "error",
                    "notes": "error",
                    "nickname": "error",
                    "produces": ["*/*"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "Map«string,object»"
                        }
                    ],
                    "deprecated": "false",
                    "type": "Map«string,object»"
                }
            ],
            "path": "/error"
        }, {
            "description": "errorHtml",
            "operations": [
                {
                    "method": "GET",
                    "summary": "errorHtml",
                    "notes": "errorHtml",
                    "nickname": "errorHtml",
                    "produces": ["text/html"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "ModelAndView"
                        }
                    ],
                    "deprecated": "false",
                    "type": "ModelAndView"
                }, {
                    "method": "HEAD",
                    "summary": "errorHtml",
                    "notes": "errorHtml",
                    "nickname": "errorHtml",
                    "produces": ["text/html"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "ModelAndView"
                        }
                    ],
                    "deprecated": "false",
                    "type": "ModelAndView"
                }, {
                    "method": "POST",
                    "summary": "errorHtml",
                    "notes": "errorHtml",
                    "nickname": "errorHtml",
                    "produces": ["text/html"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "ModelAndView"
                        }
                    ],
                    "deprecated": "false",
                    "type": "ModelAndView"
                }, {
                    "method": "PUT",
                    "summary": "errorHtml",
                    "notes": "errorHtml",
                    "nickname": "errorHtml",
                    "produces": ["text/html"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "ModelAndView"
                        }
                    ],
                    "deprecated": "false",
                    "type": "ModelAndView"
                }, {
                    "method": "PATCH",
                    "summary": "errorHtml",
                    "notes": "errorHtml",
                    "nickname": "errorHtml",
                    "produces": ["text/html"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "ModelAndView"
                        }
                    ],
                    "deprecated": "false",
                    "type": "ModelAndView"
                }, {
                    "method": "DELETE",
                    "summary": "errorHtml",
                    "notes": "errorHtml",
                    "nickname": "errorHtml",
                    "produces": ["text/html"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "ModelAndView"
                        }
                    ],
                    "deprecated": "false",
                    "type": "ModelAndView"
                }, {
                    "method": "OPTIONS",
                    "summary": "errorHtml",
                    "notes": "errorHtml",
                    "nickname": "errorHtml",
                    "produces": ["text/html"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "ModelAndView"
                        }
                    ],
                    "deprecated": "false",
                    "type": "ModelAndView"
                }, {
                    "method": "TRACE",
                    "summary": "errorHtml",
                    "notes": "errorHtml",
                    "nickname": "errorHtml",
                    "produces": ["text/html"],
                    "consumes": ["application/json"],
                    "parameters": [],
                    "responseMessages": [
                        {
                            "code": 200,
                            "message": null,
                            "responseModel": "ModelAndView"
                        }
                    ],
                    "deprecated": "false",
                    "type": "ModelAndView"
                }
            ],
            "path": "/error"
        }
    ],
    "basePath": "/",
    "consumes": ["application/json"],
    "models": {
        "View": {
            "description": "",
            "id": "View",
            "properties": {
                "contentType": {
                    "required": false,
                    "type": "string"
                }
            }
        },
        "ModelAndView": {
            "description": "",
            "id": "ModelAndView",
            "properties": {
                "view": {
                    "required": false,
                    "type": "View"
                },
                "model": {
                    "required": false,
                    "type": "object"
                },
                "empty": {
                    "required": false,
                    "type": "boolean"
                },
                "modelMap": {
                    "required": false,
                    "type": "ModelMap"
                },
                "viewName": {
                    "required": false,
                    "type": "string"
                },
                "reference": {
                    "required": false,
                    "type": "boolean"
                }
            }
        },
        "ModelMap": {
            "description": "",
            "id": "ModelMap",
            "properties": {
                "empty": {
                    "required": false,
                    "type": "boolean"
                }
            }
        }
    },
    "produces": ["*/*", "text/html"],
    "resourcePath": "/error",
    "swaggerVersion": "1.2"
}

I tried to replace SwaggerCompatConverter, but right now it doesn't seem to be intended to replace the SwaggerCompatConverter easily, as it is parsed via "SwaggerParserExtension" and there is no reference to the class SwaggerCompatConverter in the whole swagger-codegen-project-2.1.2-M1 (to allow it to be edited):

SwaggerParser:

for(SwaggerParserExtension extension : parserExtensions) {
      try{
        output = extension.read(location, auths);
        if(output != null) {
          return output;
        }
      }
@jfiala jfiala changed the title swagger-codegen: SwaggerCompatConverter throws NPE due to TRACE HTTP verb swagger-codegen: SwaggerCompatConverter throws NPE due to TRACE HTTP verb using Basic Error Controller of Spring-MVC-Swagger Apr 9, 2015
@webron
Copy link
Contributor

webron commented Apr 9, 2015

Swagger doesn't support TRACE for REST calls in general. Other than that, that definition is malformed for using Maps with Swagger 1.2 (which is only supported in 2.0 and is represented differently) and it looks like none of the operations have any parameters which is especially odd for PUT, POST and PATCH requests.

@jfiala
Copy link
Contributor Author

jfiala commented Apr 9, 2015

Thank you, I've posted it there (springfox/springfox#659).
There is a second issue with that API-doc:
After removing trace, the errorHtml()-method is duplicated within the ErrorApi itself, so it causes a compile error on ErrorApi.java:

  public ModelAndView errorHtml () throws ApiException {
   ...

    try {
      String response = apiInvoker.invokeAPI(basePath, path, "GET", queryParams, postBody, headerParams, formParams, contentType);
     ...
    }
  }


  public ModelAndView errorHtml () throws ApiException {
    Object postBody = null;

Is this behaviour erroneous due to Spring-MVC-Swagger or of Swagger-Codegen?

@webron
Copy link
Contributor

webron commented Apr 9, 2015

That looks like a problem with the Swagger definition as well. They all have the same nickname value, and those have to be unique.

@fehguy
Copy link
Contributor

fehguy commented Apr 9, 2015

We should handle duplicate nicknames in the codegen... maybe a new issue

@jfiala
Copy link
Contributor Author

jfiala commented Apr 9, 2015

Maybe there should be an Exception (when duplicates are not allowed) or they could be handled somehow (by adding suffixes).

@jfiala
Copy link
Contributor Author

jfiala commented Apr 9, 2015

The same error occurs with a Swagger 2.0 api-doc (generated also using Spring-Mvc-Swagger):

{
  "swagger": "2.0",
  "info": {
    "description": "Api Documentation",
    "version": "1.0",
    "title": "Api Documentation",
    "termsOfService": "urn:tos",
    "contact": {
      "name": "Contact Email"
    },
    "license": {
      "name": "Apache 2.0",
      "url": "http://www.apache.org/licenses/LICENSE-2.0"
    }
  },
  "host": "localhost:8080",
  "basePath": "/",
  "tags": [
    {
      "name": "search-services"
    },
    {
      "name": "user-crud-responseentity"
    },
    {
      "name": "user-crud"
    },
    {
      "name": "basic-error-controller"
    }
  ],
  "paths": {
    "/error": {
      "get": {
        "tags": [
          "basic-error-controller"
        ],
        "summary": "error",
        "description": "error",
        "operationId": "error",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "responses": {
          "404": {
            "description": "Not Found"
          },
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "object"
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "basic-error-controller"
        ],
        "summary": "error",
        "description": "error",
        "operationId": "error",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "responses": {
          "404": {
            "description": "Not Found"
          },
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "object"
              }
            }
          },
          "201": {
            "description": "Created"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        }
      },
      "put": {
        "tags": [
          "basic-error-controller"
        ],
        "summary": "error",
        "description": "error",
        "operationId": "error",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "responses": {
          "404": {
            "description": "Not Found"
          },
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "object"
              }
            }
          },
          "201": {
            "description": "Created"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        }
      },
      "delete": {
        "tags": [
          "basic-error-controller"
        ],
        "summary": "error",
        "description": "error",
        "operationId": "error",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "object"
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        }
      },
      "options": {
        "tags": [
          "basic-error-controller"
        ],
        "summary": "error",
        "description": "error",
        "operationId": "error",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "object"
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        }
      },
      "patch": {
        "tags": [
          "basic-error-controller"
        ],
        "summary": "error",
        "description": "error",
        "operationId": "error",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "object"
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        }
      }
    },
    "/search": {
      "get": {
        "tags": [
          "search-services"
        ],
        "summary": "search for users by name-part",
        "description": "search for users",
        "operationId": "searchUsers",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "description": "query",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "404": {
            "description": "Not Found"
          },
          "200": {
            "description": "OK",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/User"
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        }
      }
    },
    "/user": {
      "get": {
        "tags": [
          "user-crud"
        ],
        "summary": "read User by ID",
        "description": "pass ID to read user",
        "operationId": "getUser",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "description": "id",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "404": {
            "description": "Not Found"
          },
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/User"
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "user-crud"
        ],
        "summary": "create or update a user name by id",
        "description": "saveUser",
        "operationId": "saveUser",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "description": "id",
            "required": true,
            "type": "integer",
            "format": "int64"
          },
          {
            "name": "name",
            "in": "query",
            "description": "name",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "404": {
            "description": "Not Found"
          },
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/User"
            }
          },
          "201": {
            "description": "Created"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        }
      }
    },
    "/user_with_responseentity": {
      "get": {
        "tags": [
          "user-crud-responseentity"
        ],
        "summary": "getUserResponseEntity",
        "description": "getUserResponseEntity",
        "operationId": "getUserResponseEntity",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "description": "id",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "404": {
            "description": "Not Found"
          },
          "200": {
            "description": "OK",
            "schema": {
              "type": "object"
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "500": {
            "description": "Unexpected Error"
          }
        }
      }
    }
  },
  "definitions": {
    "User": {
      "required": [
        "id",
        "name"
      ],
      "properties": {
        "bytes": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "byte"
          }
        },
        "id": {
          "type": "integer",
          "format": "int64",
          "description": "ID of the user"
        },
        "name": {
          "type": "string",
          "description": "Name of the user"
        },
        "state": {
          "type": "string",
          "enum": [
            "ACTIVE",
            "DISABLED"
          ]
        }
      },
      "description": "User object"
    },
    "View": {
      "properties": {
        "contentType": {
          "type": "string"
        }
      }
    },
    "ModelAndView": {
      "properties": {
        "empty": {
          "type": "boolean"
        },
        "model": {
          "type": "object"
        },
        "modelMap": {
          "type": "object",
          "additionalProperties": {
            "type": "object"
          }
        },
        "reference": {
          "type": "boolean"
        },
        "view": {
          "$ref": "#/definitions/View"
        },
        "viewName": {
          "type": "string"
        }
      }
    }
  }
}
 /**
   * error
   * error
   * @return Map<String, Object>
   */
  public Map<String, Object> error () throws ApiException {
...
 String response = apiInvoker.invokeAPI(basePath, path, "GET", queryParams, postBody, headerParams, formParams, contentType);
....

 /**
   * error
   * error
   * @return Map<String, Object>
   */
  public Map<String, Object> error () throws ApiException {
    String response = apiInvoker.invokeAPI(basePath, path, "PUT", queryParams, postBody, headerParams, formParams, contentType);

@jfiala
Copy link
Contributor Author

jfiala commented Apr 9, 2015

The same error also occurs in PHP code generation:
PHP Fatal error: Cannot redeclare SwaggerPetstore\BasicerrorcontrollerApi::error() in J:\dev_php_new\confess-demo-client-codegen-2.1.2-M2\lib\BasicerrorcontrollerApi.php on line 89
PHP Stack trace:
PHP 1. {main}() J:\dev_php_new\confess-demo-client-codegen-2.1.2-M2\SwaggerPetstore.php:0

@jfiala jfiala changed the title swagger-codegen: SwaggerCompatConverter throws NPE due to TRACE HTTP verb using Basic Error Controller of Spring-MVC-Swagger swagger-codegen: SwaggerCompatConverter throws NPE due to TRACE HTTP // no handling of duplicate nicknames Apr 10, 2015
@dilipkrish
Copy link
Contributor

Might not be a problem with Jax-RS services, but in spring a request mapping could represent more than one http method. For e.g. if the method doesnt specify a http method, any of the http verbs could be routed to this method.

This is a little different than how Jax-RS works. Now really from a swagger definition I know it is supposed to be unique, however, from a codegen perspective it will look weird if we manufacture unique nicknames like errorUsingPOST errorUsingGET etc. Thoughts?

@webron
Copy link
Contributor

webron commented Apr 10, 2015

Actually, I don't think it would look that weird :) That's the whole idea being operationId in 2.0 - the consumer (in this case, codegen) need to work out the uniqueness of the given operation.

@dilipkrish
Copy link
Contributor

Cant remember which property is visible to the end-user in the swagger UI. If I remember correctly it shows the summary on the far left of the operation. In which case generating that name should be fine. As long as we dont surface the unique identifier in the ui I'm 👍 with changing that behavior. Let me know

@webron
Copy link
Contributor

webron commented Apr 10, 2015

The unique identifier is not visible to the user in the UI, it is used behind the scenes to control some mechanics (such as operation collapsing and so on).

fehguy added a commit to swagger-api/swagger-parser that referenced this issue Apr 11, 2015
fehguy added a commit that referenced this issue Apr 11, 2015
fehguy added a commit that referenced this issue Apr 11, 2015
@fehguy
Copy link
Contributor

fehguy commented Apr 11, 2015

OK, two fixes. First, the NPE is addressed with a simple null check in swagger parser and a nasty warning. As @webron stated, TRACE is not supported in the spec (should it be???).

Next, when processing operations, we will now append a _X suffix to the nickname if it's duplicated across a single file.

@fehguy fehguy closed this as completed Apr 11, 2015
@jfiala
Copy link
Contributor Author

jfiala commented Apr 11, 2015

how can I verify this (cannot see related commits on branches master / develop-2.0). Or did you commit to another branch?

@webron
Copy link
Contributor

webron commented Apr 11, 2015

Added OAI/OpenAPI-Specification#325 for TRACE support.

@webron
Copy link
Contributor

webron commented Apr 11, 2015

@jfiala - it's in develop_2.0

@jfiala
Copy link
Contributor Author

jfiala commented Apr 11, 2015

I cannot verify this using develop_2.0:

the api-docs supply:
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE

the generated code

  • correctly adds suffixes to the operations (errorHtml_)
  • still has troubles dealing with the incorrect data type Map«string,object» (but that's an springfox-issue)
  • is missing the http verbs: HEAD, TRACE

the logfile:

reading from http://localhost:8080/api-docs
reading from http://localhost:8080/api-docs
skipping operation with missing method:
{
  "tags" : [ "error" ],
  "summary" : "errorHtml",
  "description" : "errorHtml",
  "operationId" : "errorHtml",
  "consumes" : [ "application/json" ],
  "produces" : [ "text/html" ],
  "parameters" : [ ],
  "responses" : {
    "200" : {
      "description" : "success",
      "schema" : {
        "$ref" : "#/definitions/ModelAndView"
      }
    }
  }
}
skipping operation with missing method:
{
  "tags" : [ "error" ],
  "summary" : "error",
  "description" : "error",
  "operationId" : "error",
  "consumes" : [ "application/json" ],
  "produces" : [ "*/*" ],
  "parameters" : [ ],
  "responses" : {
    "200" : {
      "description" : "success",
      "schema" : {
        "$ref" : "#/definitions/Map«string,object»"
      }
    }
  }
}
writing file ../../../swagger-spring-demo/user-rest-service-swagger-codegen-client-1.0.2-codegen-2.0/src/main/java/io\swagger\client\model\User.java
writing file ../../../swagger-spring-demo/user-rest-service-swagger-codegen-client-1.0.2-codegen-2.0/src/main/java/io\swagger\client\model\View.java
writing file ../../../swagger-spring-demo/user-rest-service-swagger-codegen-client-1.0.2-codegen-2.0/src/main/java/io\swagger\client\model\ModelAndView.java
writing file ../../../swagger-spring-demo/user-rest-service-swagger-codegen-client-1.0.2-codegen-2.0/src/main/java/io\swagger\client\model\ModelMap.java
writing file ../../../swagger-spring-demo/user-rest-service-swagger-codegen-client-1.0.2-codegen-2.0/src/main/java/io\swagger\client\api\DefaultApi.java
writing file ../../../swagger-spring-demo/user-rest-service-swagger-codegen-client-1.0.2-codegen-2.0/src/main/java/io\swagger\client\api\UserApi.java
writing file ../../../swagger-spring-demo/user-rest-service-swagger-codegen-client-1.0.2-codegen-2.0/src/main/java/io\swagger\client\api\UsergetreadApi.java
writing file ../../../swagger-spring-demo/user-rest-service-swagger-codegen-client-1.0.2-codegen-2.0/src/main/java/io\swagger\client\api\SearchApi.java
writing file ../../../swagger-spring-demo/user-rest-service-swagger-codegen-client-1.0.2-codegen-2.0/src/main/java/io\swagger\client\api\UserwithresponseentityApi.java
writing file ../../../swagger-spring-demo/user-rest-service-swagger-codegen-client-1.0.2-codegen-2.0/src/main/java/io\swagger\client\api\ErrorApi.java
writing file ../../../swagger-spring-demo/user-rest-service-swagger-codegen-client-1.0.2-codegen-2.0\pom.xml
writing file ../../../swagger-spring-demo/user-rest-service-swagger-codegen-client-1.0.2-codegen-2.0\src/main/java\io\swagger\client\ApiInvoker.java
writing file ../../../swagger-spring-demo/user-rest-service-swagger-codegen-client-1.0.2-codegen-2.0\src/main/java\io\swagger\client\JsonUtil.java
writing file ../../../swagger-spring-demo/user-rest-service-swagger-codegen-client-1.0.2-codegen-2.0\src/main/java\io\swagger\client\ApiException.java

the supplied api-docs (Swagger 1.2):

{"apiVersion":"1.0","apis":[{"description":"errorHtml","operations":[{"method":"GET","summary":"errorHtml","notes":"errorHtml","nickname":"errorHtml","produces":["text/html"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"ModelAndView"}],"deprecated":"false","type":"ModelAndView"},{"method":"HEAD","summary":"errorHtml","notes":"errorHtml","nickname":"errorHtml","produces":["text/html"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"ModelAndView"}],"deprecated":"false","type":"ModelAndView"},{"method":"POST","summary":"errorHtml","notes":"errorHtml","nickname":"errorHtml","produces":["text/html"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"ModelAndView"}],"deprecated":"false","type":"ModelAndView"},{"method":"PUT","summary":"errorHtml","notes":"errorHtml","nickname":"errorHtml","produces":["text/html"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"ModelAndView"}],"deprecated":"false","type":"ModelAndView"},{"method":"PATCH","summary":"errorHtml","notes":"errorHtml","nickname":"errorHtml","produces":["text/html"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"ModelAndView"}],"deprecated":"false","type":"ModelAndView"},{"method":"DELETE","summary":"errorHtml","notes":"errorHtml","nickname":"errorHtml","produces":["text/html"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"ModelAndView"}],"deprecated":"false","type":"ModelAndView"},{"method":"OPTIONS","summary":"errorHtml","notes":"errorHtml","nickname":"errorHtml","produces":["text/html"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"ModelAndView"}],"deprecated":"false","type":"ModelAndView"},{"method":"TRACE","summary":"errorHtml","notes":"errorHtml","nickname":"errorHtml","produces":["text/html"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"ModelAndView"}],"deprecated":"false","type":"ModelAndView"}],"path":"/error"},{"description":"error","operations":[{"method":"GET","summary":"error","notes":"error","nickname":"error","produces":["*/*"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"Map«string,object»"}],"deprecated":"false","type":"Map«string,object»"},{"method":"HEAD","summary":"error","notes":"error","nickname":"error","produces":["*/*"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"Map«string,object»"}],"deprecated":"false","type":"Map«string,object»"},{"method":"POST","summary":"error","notes":"error","nickname":"error","produces":["*/*"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"Map«string,object»"}],"deprecated":"false","type":"Map«string,object»"},{"method":"PUT","summary":"error","notes":"error","nickname":"error","produces":["*/*"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"Map«string,object»"}],"deprecated":"false","type":"Map«string,object»"},{"method":"PATCH","summary":"error","notes":"error","nickname":"error","produces":["*/*"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"Map«string,object»"}],"deprecated":"false","type":"Map«string,object»"},{"method":"DELETE","summary":"error","notes":"error","nickname":"error","produces":["*/*"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"Map«string,object»"}],"deprecated":"false","type":"Map«string,object»"},{"method":"OPTIONS","summary":"error","notes":"error","nickname":"error","produces":["*/*"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"Map«string,object»"}],"deprecated":"false","type":"Map«string,object»"},{"method":"TRACE","summary":"error","notes":"error","nickname":"error","produces":["*/*"],"consumes":["application/json"],"parameters":[],"responseMessages":[{"code":200,"message":null,"responseModel":"Map«string,object»"}],"deprecated":"false","type":"Map«string,object»"}],"path":"/error"}],"basePath":"/","consumes":["application/json"],"models":{"View":{"description":"","id":"View","properties":{"contentType":{"required":false,"type":"string"}}},"ModelAndView":{"description":"","id":"ModelAndView","properties":{"view":{"required":false,"type":"View"},"model":{"required":false,"type":"object"},"empty":{"required":false,"type":"boolean"},"viewName":{"required":false,"type":"string"},"reference":{"required":false,"type":"boolean"},"modelMap":{"required":false,"type":"ModelMap"}}},"ModelMap":{"description":"","id":"ModelMap","properties":{"empty":{"required":false,"type":"boolean"}}}},"produces":["*/*","text/html"],"resourcePath":"/error","swaggerVersion":"1.2"}

the generated code:

package io.swagger.client.api;

import io.swagger.client.ApiException;
import io.swagger.client.ApiInvoker;

import io.swagger.client.model.*;

import java.util.*;

import io.swagger.client.model.Map«string,object»;


import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.file.FileDataBodyPart;

import javax.ws.rs.core.MediaType;

import java.io.File;
import java.util.Map;
import java.util.HashMap;


public class ErrorApi {
  String basePath = "http://localhost/";
  ApiInvoker apiInvoker = ApiInvoker.getInstance();

  public ApiInvoker getInvoker() {
    return apiInvoker;
  }

  public void setBasePath(String basePath) {
    this.basePath = basePath;
  }

  public String getBasePath() {
    return basePath;
  }


  /**
   * error
   * error
   * @return Map«string,object»
   */
  public Map«string,object» error () throws ApiException {
    Object postBody = null;


    // create path and map variables
    String path = "/error".replaceAll("\\{format\\}","json");

    // query params
    Map<String, String> queryParams = new HashMap<String, String>();
    Map<String, String> headerParams = new HashMap<String, String>();
    Map<String, String> formParams = new HashMap<String, String>();



    String[] contentTypes = {
      "application/json",
    };

    String contentType = contentTypes.length > 0 ? contentTypes[0] : "application/json";

    if(contentType.startsWith("multipart/form-data")) {
      boolean hasFields = false;
      FormDataMultiPart mp = new FormDataMultiPart();

      if(hasFields)
        postBody = mp;
    }
    else {

    }

    try {
      String response = apiInvoker.invokeAPI(basePath, path, "GET", queryParams, postBody, headerParams, formParams, contentType);
      if(response != null){
        return (Map«string,object») ApiInvoker.deserialize(response, "", Map«string,object».class);
      }
      else {
        return null;
      }
    } catch (ApiException ex) {
      throw ex;
    }
  }

  /**
   * error
   * error
   * @return Map«string,object»
   */
  public Map«string,object» error_1 () throws ApiException {
    Object postBody = null;


    // create path and map variables
    String path = "/error".replaceAll("\\{format\\}","json");

    // query params
    Map<String, String> queryParams = new HashMap<String, String>();
    Map<String, String> headerParams = new HashMap<String, String>();
    Map<String, String> formParams = new HashMap<String, String>();



    String[] contentTypes = {
      "application/json",
    };

    String contentType = contentTypes.length > 0 ? contentTypes[0] : "application/json";

    if(contentType.startsWith("multipart/form-data")) {
      boolean hasFields = false;
      FormDataMultiPart mp = new FormDataMultiPart();

      if(hasFields)
        postBody = mp;
    }
    else {

    }

    try {
      String response = apiInvoker.invokeAPI(basePath, path, "PUT", queryParams, postBody, headerParams, formParams, contentType);
      if(response != null){
        return (Map«string,object») ApiInvoker.deserialize(response, "", Map«string,object».class);
      }
      else {
        return null;
      }
    } catch (ApiException ex) {
      throw ex;
    }
  }

  /**
   * error
   * error
   * @return Map«string,object»
   */
  public Map«string,object» error_2 () throws ApiException {
    Object postBody = null;


    // create path and map variables
    String path = "/error".replaceAll("\\{format\\}","json");

    // query params
    Map<String, String> queryParams = new HashMap<String, String>();
    Map<String, String> headerParams = new HashMap<String, String>();
    Map<String, String> formParams = new HashMap<String, String>();



    String[] contentTypes = {
      "application/json",
    };

    String contentType = contentTypes.length > 0 ? contentTypes[0] : "application/json";

    if(contentType.startsWith("multipart/form-data")) {
      boolean hasFields = false;
      FormDataMultiPart mp = new FormDataMultiPart();

      if(hasFields)
        postBody = mp;
    }
    else {

    }

    try {
      String response = apiInvoker.invokeAPI(basePath, path, "POST", queryParams, postBody, headerParams, formParams, contentType);
      if(response != null){
        return (Map«string,object») ApiInvoker.deserialize(response, "", Map«string,object».class);
      }
      else {
        return null;
      }
    } catch (ApiException ex) {
      throw ex;
    }
  }

  /**
   * error
   * error
   * @return Map«string,object»
   */
  public Map«string,object» error_3 () throws ApiException {
    Object postBody = null;


    // create path and map variables
    String path = "/error".replaceAll("\\{format\\}","json");

    // query params
    Map<String, String> queryParams = new HashMap<String, String>();
    Map<String, String> headerParams = new HashMap<String, String>();
    Map<String, String> formParams = new HashMap<String, String>();



    String[] contentTypes = {
      "application/json",
    };

    String contentType = contentTypes.length > 0 ? contentTypes[0] : "application/json";

    if(contentType.startsWith("multipart/form-data")) {
      boolean hasFields = false;
      FormDataMultiPart mp = new FormDataMultiPart();

      if(hasFields)
        postBody = mp;
    }
    else {

    }

    try {
      String response = apiInvoker.invokeAPI(basePath, path, "DELETE", queryParams, postBody, headerParams, formParams, contentType);
      if(response != null){
        return (Map«string,object») ApiInvoker.deserialize(response, "", Map«string,object».class);
      }
      else {
        return null;
      }
    } catch (ApiException ex) {
      throw ex;
    }
  }

  /**
   * error
   * error
   * @return Map«string,object»
   */
  public Map«string,object» error_4 () throws ApiException {
    Object postBody = null;


    // create path and map variables
    String path = "/error".replaceAll("\\{format\\}","json");

    // query params
    Map<String, String> queryParams = new HashMap<String, String>();
    Map<String, String> headerParams = new HashMap<String, String>();
    Map<String, String> formParams = new HashMap<String, String>();



    String[] contentTypes = {
      "application/json",
    };

    String contentType = contentTypes.length > 0 ? contentTypes[0] : "application/json";

    if(contentType.startsWith("multipart/form-data")) {
      boolean hasFields = false;
      FormDataMultiPart mp = new FormDataMultiPart();

      if(hasFields)
        postBody = mp;
    }
    else {

    }

    try {
      String response = apiInvoker.invokeAPI(basePath, path, "PATCH", queryParams, postBody, headerParams, formParams, contentType);
      if(response != null){
        return (Map«string,object») ApiInvoker.deserialize(response, "", Map«string,object».class);
      }
      else {
        return null;
      }
    } catch (ApiException ex) {
      throw ex;
    }
  }

  /**
   * error
   * error
   * @return Map«string,object»
   */
  public Map«string,object» error_5 () throws ApiException {
    Object postBody = null;


    // create path and map variables
    String path = "/error".replaceAll("\\{format\\}","json");

    // query params
    Map<String, String> queryParams = new HashMap<String, String>();
    Map<String, String> headerParams = new HashMap<String, String>();
    Map<String, String> formParams = new HashMap<String, String>();



    String[] contentTypes = {
      "application/json",
    };

    String contentType = contentTypes.length > 0 ? contentTypes[0] : "application/json";

    if(contentType.startsWith("multipart/form-data")) {
      boolean hasFields = false;
      FormDataMultiPart mp = new FormDataMultiPart();

      if(hasFields)
        postBody = mp;
    }
    else {

    }

    try {
      String response = apiInvoker.invokeAPI(basePath, path, "OPTIONS", queryParams, postBody, headerParams, formParams, contentType);
      if(response != null){
        return (Map«string,object») ApiInvoker.deserialize(response, "", Map«string,object».class);
      }
      else {
        return null;
      }
    } catch (ApiException ex) {
      throw ex;
    }
  }

}

@webron
Copy link
Contributor

webron commented Apr 11, 2015

That means that the only current problem is the lack of HEAD implementation.

@wakingrufus
Copy link

Was the HEAD issue ever addressed? My project's HEAD endpoints aren't showing up in springfox swagger.

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

No branches or pull requests

5 participants