From 85aabbe8102847939948c995318eae4a7301f01b Mon Sep 17 00:00:00 2001 From: Robin Eggenkamp Date: Fri, 21 Aug 2015 12:24:37 +0200 Subject: [PATCH 1/5] Fix possible NullPointerException getWrapped() returns a Boolean which can be null --- .../java/io/swagger/codegen/examples/XmlExampleGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/examples/XmlExampleGenerator.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/examples/XmlExampleGenerator.java index 73294268f39..a6bfc7d5ddd 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/examples/XmlExampleGenerator.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/examples/XmlExampleGenerator.java @@ -128,7 +128,7 @@ public class XmlExampleGenerator { ArrayProperty p = (ArrayProperty) property; Property inner = p.getItems(); boolean wrapped = false; - if (property.getXml() != null && property.getXml().getWrapped()) { + if (property.getXml() != null && property.getXml().getWrapped() != null && property.getXml().getWrapped()) { wrapped = true; } if (wrapped) { From 0261121d780efff40de24d18c0f7630825b581fd Mon Sep 17 00:00:00 2001 From: F481 Date: Mon, 24 Aug 2015 14:04:50 +0200 Subject: [PATCH 2/5] added some useful log/output messages and exception handling --- .../java/io/swagger/codegen/cmd/Generate.java | 4 +- .../io/swagger/codegen/DefaultCodegen.java | 33 +++++-- .../io/swagger/codegen/DefaultGenerator.java | 88 ++++++++++++------- .../codegen/languages/JavaClientCodegen.java | 11 +++ 4 files changed, 94 insertions(+), 42 deletions(-) diff --git a/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Generate.java b/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Generate.java index cf22ae91b62..74b445c57ff 100644 --- a/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Generate.java +++ b/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Generate.java @@ -78,17 +78,19 @@ public class Generate implements Runnable { */ private static CodegenConfig forName(String name) { ServiceLoader loader = load(CodegenConfig.class); + String available = ""; for (CodegenConfig config : loader) { if (config.getName().equals(name)) { return config; } + available = available + config.getName() + "\n"; } // else try to load directly try { return (CodegenConfig) Class.forName(name).newInstance(); } catch (Exception e) { - throw new RuntimeException("Can't load config class with name ".concat(name), e); + throw new RuntimeException("Can't load config class with name ".concat(name) + "Available: "+available, e); } } diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java index 8a75eac30d6..298d57ff177 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java @@ -391,7 +391,13 @@ public class DefaultCodegen { public String toInstantiationType(Property p) { if (p instanceof MapProperty) { MapProperty ap = (MapProperty) p; - String inner = getSwaggerType(ap.getAdditionalProperties()); + Property additionalProperties2 = ap.getAdditionalProperties(); + String type = additionalProperties2.getType(); + if (null == type) { + LOGGER.error("No Type defined for Additional Property " + additionalProperties2 + "\n" // + + "\tIn Property: " + p); + } + String inner = getSwaggerType(additionalProperties2); return instantiationTypes.get("map") + ""; } else if (p instanceof ArrayProperty) { ArrayProperty ap = (ArrayProperty) p; @@ -763,7 +769,7 @@ public class DefaultCodegen { } } operationId = builder.toString(); - LOGGER.warn("generated operationId " + operationId); + LOGGER.info("generated operationId " + operationId + "\tfor Path: " + httpMethod + " " + path); } operationId = removeNonNameElementToCamelCase(operationId); op.path = path; @@ -1002,6 +1008,10 @@ public class DefaultCodegen { } p.jsonSchema = Json.pretty(param); + if (System.getProperty("debugParser") != null) { + LOGGER.info("working on Parameter " + param); + } + // move the defaultValue for headers, forms and params if (param instanceof QueryParameter) { p.defaultValue = ((QueryParameter) param).getDefaultValue(); @@ -1015,7 +1025,11 @@ public class DefaultCodegen { SerializableParameter qp = (SerializableParameter) param; Property property = null; String collectionFormat = null; - if ("array".equals(qp.getType())) { + String type = qp.getType(); + if (null == type) { + LOGGER.warn("Type is NULL for Serializable Parameter: " + param); + } + if ("array".equals(type)) { Property inner = qp.getItems(); if (inner == null) { LOGGER.warn("warning! No inner type supplied for array parameter \"" + qp.getName() + "\", using String"); @@ -1027,7 +1041,7 @@ public class DefaultCodegen { p.baseType = pr.datatype; p.isContainer = true; imports.add(pr.baseType); - } else if ("object".equals(qp.getType())) { + } else if ("object".equals(type)) { Property inner = qp.getItems(); if (inner == null) { LOGGER.warn("warning! No inner type supplied for map parameter \"" + qp.getName() + "\", using String"); @@ -1040,12 +1054,13 @@ public class DefaultCodegen { imports.add(pr.baseType); } else { Map args = new HashMap(); + String format = qp.getFormat(); args.put(PropertyId.ENUM, qp.getEnum()); - property = PropertyBuilder.build(qp.getType(), qp.getFormat(), args); + property = PropertyBuilder.build(type, format, args); } if (property == null) { - LOGGER.warn("warning! Property type \"" + qp.getType() + "\" not found for parameter \"" + param.getName() + "\", using String"); - property = new StringProperty().description("//TODO automatically added by swagger-codegen. Type was " + qp.getType() + " but not supported"); + LOGGER.warn("warning! Property type \"" + type + "\" not found for parameter \"" + param.getName() + "\", using String"); + property = new StringProperty().description("//TODO automatically added by swagger-codegen. Type was " + type + " but not supported"); } property.setRequired(param.getRequired()); CodegenProperty model = fromProperty(qp.getName(), property); @@ -1060,6 +1075,10 @@ public class DefaultCodegen { imports.add(model.complexType); } } else { + if (!(param instanceof BodyParameter)) { + LOGGER.error("Cannot use Parameter " + param + " as Body Parameter"); + } + BodyParameter bp = (BodyParameter) param; Model model = bp.getSchema(); diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java index 40b676149a2..378a874d3e0 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java @@ -20,6 +20,8 @@ import io.swagger.models.parameters.Parameter; import io.swagger.util.Json; import org.apache.commons.io.IOUtils; import org.joda.time.DateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileInputStream; @@ -39,12 +41,15 @@ import java.util.Map; import java.util.Set; public class DefaultGenerator extends AbstractGenerator implements Generator { + Logger LOGGER = LoggerFactory.getLogger(DefaultGenerator.class); + protected CodegenConfig config; protected ClientOptInput opts = null; protected Swagger swagger = null; public CodeGenStatus status = CodeGenStatus.UNRUN; + @Override public Generator opts(ClientOptInput opts) { this.opts = opts; @@ -55,6 +60,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { return this; } + @Override public List generate() { if (swagger == null || config == null) { throw new RuntimeException("missing swagger input or config!"); @@ -150,6 +156,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { String template = readTemplate(templateFile); Template tmpl = Mustache.compiler() .withLoader(new Mustache.TemplateLoader() { + @Override public Reader getTemplate(String name) { return getTemplateReader(config.templateDir() + File.separator + name + ".mustache"); } @@ -203,6 +210,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { String template = readTemplate(templateFile); Template tmpl = Mustache.compiler() .withLoader(new Mustache.TemplateLoader() { + @Override public Reader getTemplate(String name) { return getTemplateReader(config.templateDir() + File.separator + name + ".mustache"); } @@ -277,6 +285,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { String template = readTemplate(templateFile); Template tmpl = Mustache.compiler() .withLoader(new Mustache.TemplateLoader() { + @Override public Reader getTemplate(String name) { return getTemplateReader(config.templateDir() + File.separator + name + ".mustache"); } @@ -416,6 +425,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { public void processOperation(String resourcePath, String httpMethod, Operation operation, Map> operations, Path path) { if (operation != null) { + LOGGER.info("processOperation: resourcePath= " + resourcePath + "\t;" + httpMethod + " " + operation + "\n"); List tags = operation.getTags(); if (tags == null) { tags = new ArrayList(); @@ -445,44 +455,54 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { } for (String tag : tags) { - CodegenOperation co = config.fromOperation(resourcePath, httpMethod, operation, swagger.getDefinitions()); - co.tags = new ArrayList(); - co.tags.add(sanitizeTag(tag)); - config.addOperationToGroup(sanitizeTag(tag), resourcePath, operation, co, operations); + CodegenOperation co = null; + try { + co = config.fromOperation(resourcePath, httpMethod, operation, swagger.getDefinitions()); + co.tags = new ArrayList(); + co.tags.add(sanitizeTag(tag)); + config.addOperationToGroup(sanitizeTag(tag), resourcePath, operation, co, operations); - List>> securities = operation.getSecurity(); - if (securities == null) { - continue; - } - Map authMethods = new HashMap(); - for (Map> security : securities) { - if (security.size() != 1) { - //Not sure what to do + List>> securities = operation.getSecurity(); + if (securities == null) { continue; } - String securityName = security.keySet().iterator().next(); - SecuritySchemeDefinition securityDefinition = fromSecurity(securityName); - if (securityDefinition != null) { - if(securityDefinition instanceof OAuth2Definition) { - OAuth2Definition oauth2Definition = (OAuth2Definition) securityDefinition; - OAuth2Definition oauth2Operation = new OAuth2Definition(); - oauth2Operation.setType(oauth2Definition.getType()); - oauth2Operation.setAuthorizationUrl(oauth2Definition.getAuthorizationUrl()); - oauth2Operation.setFlow(oauth2Definition.getFlow()); - oauth2Operation.setTokenUrl(oauth2Definition.getTokenUrl()); - for (String scope : security.values().iterator().next()) { - if (oauth2Definition.getScopes().containsKey(scope)) { - oauth2Operation.addScope(scope, oauth2Definition.getScopes().get(scope)); - } - } - authMethods.put(securityName, oauth2Operation); - } else { - authMethods.put(securityName, securityDefinition); - } + Map authMethods = new HashMap(); + for (Map> security : securities) { + if (security.size() != 1) { + //Not sure what to do + continue; + } + String securityName = security.keySet().iterator().next(); + SecuritySchemeDefinition securityDefinition = fromSecurity(securityName); + if (securityDefinition != null) { + if(securityDefinition instanceof OAuth2Definition) { + OAuth2Definition oauth2Definition = (OAuth2Definition) securityDefinition; + OAuth2Definition oauth2Operation = new OAuth2Definition(); + oauth2Operation.setType(oauth2Definition.getType()); + oauth2Operation.setAuthorizationUrl(oauth2Definition.getAuthorizationUrl()); + oauth2Operation.setFlow(oauth2Definition.getFlow()); + oauth2Operation.setTokenUrl(oauth2Definition.getTokenUrl()); + for (String scope : security.values().iterator().next()) { + if (oauth2Definition.getScopes().containsKey(scope)) { + oauth2Operation.addScope(scope, oauth2Definition.getScopes().get(scope)); + } + } + authMethods.put(securityName, oauth2Operation); + } else { + authMethods.put(securityName, securityDefinition); + } + } + } + if (!authMethods.isEmpty()) { + co.authMethods = config.fromSecurity(authMethods); + } + catch (Exception ex) { + LOGGER.error("Error while trying to get Config from Operation for tag(" + tag + ")\n" // + + "\tResource: " + httpMethod + " " + resourcePath + "\n"// + + "\tOperation:" + operation + "\n" // + + "\tDefinitions: " + swagger.getDefinitions() + "\n"); + ex.printStackTrace(); } - } - if (!authMethods.isEmpty()) { - co.authMethods = config.fromSecurity(authMethods); } } } diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java index 379a2db2eb1..0e9b189d77a 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java @@ -27,8 +27,12 @@ import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { + private static final Logger LOGGER = LoggerFactory.getLogger(JavaClientCodegen.class); + protected String invokerPackage = "io.swagger.client"; protected String groupId = "io.swagger"; protected String artifactId = "swagger-java-client"; @@ -85,14 +89,17 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { cliOptions.add(buildLibraryCliOption(supportedLibraries)); } + @Override public CodegenType getTag() { return CodegenType.CLIENT; } + @Override public String getName() { return "java"; } + @Override public String getHelp() { return "Generates a Java client library."; } @@ -194,6 +201,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar); } + @Override public String modelFileFolder() { return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar); } @@ -287,6 +295,9 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { } else { type = swaggerType; } + if (null == type) { + LOGGER.error("No Type defined for Property " + p); + } return toModelName(type); } From 3d89399b58eb60ae448e97308c1c09278121fce1 Mon Sep 17 00:00:00 2001 From: F481 Date: Mon, 24 Aug 2015 14:28:13 +0200 Subject: [PATCH 3/5] fixed syntax error --- .../java/io/swagger/codegen/DefaultGenerator.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java index 378a874d3e0..bcc86be0558 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java @@ -496,13 +496,13 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { if (!authMethods.isEmpty()) { co.authMethods = config.fromSecurity(authMethods); } - catch (Exception ex) { - LOGGER.error("Error while trying to get Config from Operation for tag(" + tag + ")\n" // - + "\tResource: " + httpMethod + " " + resourcePath + "\n"// - + "\tOperation:" + operation + "\n" // - + "\tDefinitions: " + swagger.getDefinitions() + "\n"); - ex.printStackTrace(); - } + } + catch (Exception ex) { + LOGGER.error("Error while trying to get Config from Operation for tag(" + tag + ")\n" // + + "\tResource: " + httpMethod + " " + resourcePath + "\n"// + + "\tOperation:" + operation + "\n" // + + "\tDefinitions: " + swagger.getDefinitions() + "\n"); + ex.printStackTrace(); } } } From d434b7c440206735bac71f41d17f11715405555f Mon Sep 17 00:00:00 2001 From: Hugo Wood Date: Fri, 21 Aug 2015 17:39:40 +0200 Subject: [PATCH 4/5] fix invalid JSON being generated in swagger.json of Node.js server --- .../codegen/languages/NodeJSServerCodegen.java | 16 ++++++++-------- .../src/main/resources/nodejs/swagger.mustache | 3 +-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/NodeJSServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/NodeJSServerCodegen.java index 5d0a7034537..10070ece512 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/NodeJSServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/NodeJSServerCodegen.java @@ -207,11 +207,14 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig } @SuppressWarnings("unchecked") - private Map getOperations(Map objs) { + private List> getOperations(Map objs) { + List> result = new ArrayList>(); Map apiInfo = (Map) objs.get("apiInfo"); List> apis = (List>) apiInfo.get("apis"); - Map api = apis.get(0); - return (Map) api.get("operations"); + for (Map api : apis) { + result.add((Map) api.get("operations")); + } + return result; } private List> sortOperationsByPath(List ops) { @@ -221,7 +224,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig opsByPath.put(op.path, op); } - List> opsByPathList = new ArrayList>(); + List> opsByPathList = new ArrayList>(); for (Entry> entry : opsByPath.asMap().entrySet()) { Map opsByPathEntry = new HashMap(); opsByPathList.add(opsByPathEntry); @@ -239,16 +242,13 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig @Override public Map postProcessSupportingFileData(Map objs) { - Map operations = getOperations(objs); - - if (operations != null) { + for (Map operations : getOperations(objs)) { @SuppressWarnings("unchecked") List ops = (List) operations.get("operation"); List> opsByPathList = sortOperationsByPath(ops); operations.put("operationsByPath", opsByPathList); } - return super.postProcessSupportingFileData(objs); } } \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/nodejs/swagger.mustache b/modules/swagger-codegen/src/main/resources/nodejs/swagger.mustache index 59940f08b15..3b975e53b80 100644 --- a/modules/swagger-codegen/src/main/resources/nodejs/swagger.mustache +++ b/modules/swagger-codegen/src/main/resources/nodejs/swagger.mustache @@ -14,7 +14,7 @@ {{#operations}} {{#operationsByPath}} "{{{path}}}": { - {{#operation}} + {{#operation}} "{{httpMethod}}": { "summary": "{{summary}}", "description":"{{notes}}", @@ -34,7 +34,6 @@ {{/operation}} } {{#hasMore}},{{/hasMore}} {{/operationsByPath}} - {{#hasMore}},{{/hasMore}} {{/operations}} {{/apis}} {{/apiInfo}} From fc4fce373184e5ee6419a66fd274997290578c35 Mon Sep 17 00:00:00 2001 From: F481 Date: Thu, 27 Aug 2015 08:06:24 +0200 Subject: [PATCH 5/5] write processOperation debug output only if the debugOperations property is set --- .../src/main/java/io/swagger/codegen/DefaultGenerator.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java index bcc86be0558..e5a49f4eba4 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java @@ -425,7 +425,9 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { public void processOperation(String resourcePath, String httpMethod, Operation operation, Map> operations, Path path) { if (operation != null) { - LOGGER.info("processOperation: resourcePath= " + resourcePath + "\t;" + httpMethod + " " + operation + "\n"); + if (System.getProperty("debugOperations") != null) { + LOGGER.debug("processOperation: resourcePath= " + resourcePath + "\t;" + httpMethod + " " + operation + "\n"); + } List tags = operation.getTags(); if (tags == null) { tags = new ArrayList();