-
Notifications
You must be signed in to change notification settings - Fork 6k
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
Comments
Swagger doesn't support |
Thank you, I've posted it there (springfox/springfox#659). 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? |
That looks like a problem with the Swagger definition as well. They all have the same |
We should handle duplicate nicknames in the codegen... maybe a new issue |
Maybe there should be an Exception (when duplicates are not allowed) or they could be handled somehow (by adding suffixes). |
The same error occurs with a Swagger 2.0 api-doc (generated also using Spring-Mvc-Swagger):
/**
* 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); |
The same error also occurs in PHP code generation: |
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 |
Actually, I don't think it would look that weird :) That's the whole idea being |
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 |
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). |
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 |
how can I verify this (cannot see related commits on branches master / develop-2.0). Or did you commit to another branch? |
Added OAI/OpenAPI-Specification#325 for TRACE support. |
@jfiala - it's in develop_2.0 |
I cannot verify this using develop_2.0: the api-docs supply: the generated code
the logfile:
the supplied api-docs (Swagger 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;
}
}
} |
That means that the only current problem is the lack of HEAD implementation. |
Was the HEAD issue ever addressed? My project's HEAD endpoints aren't showing up in springfox swagger. |
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:
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:
The text was updated successfully, but these errors were encountered: