diff --git a/bin/java-petstore-pkmst-server.sh b/bin/java-petstore-pkmst-server.sh new file mode 100644 index 00000000000..3f95c1f7343 --- /dev/null +++ b/bin/java-petstore-pkmst-server.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +SCRIPT="$0" + +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=`dirname "$SCRIPT"`/.. + APP_DIR=`cd "${APP_DIR}"; pwd` +fi + +executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar" + +if [ ! -f "$executable" ] +then + mvn clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="$@ generate -t modules/swagger-codegen/src/main/resources/pkmst -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l pkmst -o samples/server/petstore/java-pkmst/ -DhideGenerationTimestamp=true" + +echo "Removing files and folders under samples/server/petstore/java-pkmst/src/main" +rm -rf samples/server/petstore/java-pkmst/src/main +find samples/server/petstore/java-pkmst -maxdepth 1 -type f ! -name "README.md" ! -name "pom.xml" ! -name "mvn_test_jdk8_only.sh" ! -name ".swagger-codegen-ignore" -exec rm {} + +java $JAVA_OPTS -jar $executable $ags diff --git a/bin/windows/java-petstore-pkmst-server.bat b/bin/windows/java-petstore-pkmst-server.bat new file mode 100644 index 00000000000..a8e6669b943 --- /dev/null +++ b/bin/windows/java-petstore-pkmst-server.bat @@ -0,0 +1,10 @@ +set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar + +If Not Exist %executable% ( + mvn clean package +) + +REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M +set ags=generate -i modules\swagger-codegen\src\test\resources\2_0\petstore.yaml -l pkmst -o samples\server\petstore\java-pkmst + +java %JAVA_OPTS% -jar %executable% %ags% \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java new file mode 100644 index 00000000000..bf682626edb --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java @@ -0,0 +1,832 @@ +package io.swagger.codegen.languages; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.swagger.codegen.CliOption; +import io.swagger.codegen.CodegenConstants; +import io.swagger.codegen.CodegenModel; +import io.swagger.codegen.CodegenOperation; +import io.swagger.codegen.CodegenParameter; +import io.swagger.codegen.CodegenProperty; +import io.swagger.codegen.CodegenResponse; +import io.swagger.codegen.CodegenType; +import io.swagger.codegen.SupportingFile; +import io.swagger.models.Operation; +import io.swagger.models.Path; +import io.swagger.models.Swagger; +import io.swagger.models.Tag; +import io.swagger.models.parameters.FormParameter; +import io.swagger.models.parameters.Parameter; + +/** + * Created by prokarma on 04/09/17. + */ +public class JavaPKMSTServerCodegen extends AbstractJavaCodegen { + + public static final String FULL_JAVA_UTIL = "fullJavaUtil"; + public static final String SUPPORT_JAVA6 = "supportJava6"; + public static final String CONFIG_PACKAGE = "configPackage"; + public static final String BASE_PACKAGE = "basePackage"; + public static final String TITLE = "title"; + public static final String WITH_XML = "withXml"; + public static final String EUREKA_URI = "eurekaUri"; + public static final String ZIPKIN_URI = "zipkinUri"; + public static final String SPRINGADMIN_URI = "springBootAdminUri"; + protected String projectFolder; + protected String projectTestFolder; + protected String sourceFolder; + protected String testFolder; + protected String basePackage = "com.prokarma.pkmst"; + protected String serviceName = "Pkmst"; + protected String configPackage = "com.prokarma.pkmst.config"; + protected boolean implicitHeaders = false; + protected boolean serializeBigDecimalAsString = false; + protected boolean withXml = false; + protected boolean fullJavaUtil; + protected String javaUtilPrefix = ""; + protected Boolean serializableModel = false; + protected String invokerPackage; + protected String title; + protected String eurekaUri; + protected String zipkinUri; + protected String springBootAdminUri; + + public JavaPKMSTServerCodegen() { + super(); + this.projectFolder = "src" + File.separator + "main"; + this.projectTestFolder = "src" + File.separator + "test"; + this.sourceFolder = this.projectFolder + File.separator + "java"; + this.testFolder = this.projectTestFolder + File.separator + "java"; + groupId = "com.prokarma"; + artifactId = "pkmst-microservice"; + artifactVersion = "1.0.0"; + embeddedTemplateDir = templateDir = "pkmst"; + apiPackage = "com.prokarma.pkmst.controller"; + modelPackage = "com.prokarma.pkmst.model"; + invokerPackage = "com.prokarma.pkmst.controller"; + additionalProperties.put("jackson", "true"); + this.cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml")); + this.cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml")); + this.cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml")); + this.cliOptions.add(new CliOption("basePackage", "base package for java source code")); + this.cliOptions.add(new CliOption("serviceName", "Service Name")); + this.cliOptions.add(new CliOption(TITLE, "server title name or client service name")); + this.cliOptions.add(new CliOption("eurekaUri", "Eureka URI")); + this.cliOptions.add(new CliOption("zipkinUri", "Zipkin URI")); + this.cliOptions.add(new CliOption("springBootAdminUri", "Spring-Boot URI")); + // Middleware config + this.cliOptions.add(new CliOption("pkmstInterceptor", "PKMST Interceptor")); + this.apiTestTemplateFiles.put("api_test.mustache", ".java"); + this.modelDocTemplateFiles.remove("model_doc.mustache", ".md"); + this.apiDocTemplateFiles.remove("api_doc.mustache", ".md"); + } + + private static String getAccept(Operation operation) { + String accepts = null; + String defaultContentType = "application/json"; + if (operation.getProduces() != null && !operation.getProduces().isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (String produces : operation.getProduces()) { + if (defaultContentType.equalsIgnoreCase(produces)) { + accepts = defaultContentType; + break; + } else { + if (sb.length() > 0) { + sb.append(","); + } + sb.append(produces); + } + } + if (accepts == null) { + accepts = sb.toString(); + } + } else { + accepts = defaultContentType; + } + + return accepts; + } + + public CodegenType getTag() { + return CodegenType.SERVER; + } + + public String getName() { + return "pkmst"; + } + + public String getHelp() { + return "Generates a PKMST SpringBoot Server application using the SpringFox integration." + + " Also enables EurekaServerClient / Zipkin / Spring-Boot admin"; + } + + public void processOpts() { + super.processOpts(); + if (this.additionalProperties.containsKey("basePackage")) { + this.setBasePackage((String) this.additionalProperties.get("basePackage")); + this.setInvokerPackage(this.getBasePackage()); + this.apiPackage = this.getBasePackage() + ".controller"; + this.modelPackage = this.getBasePackage() + ".model"; + this.setConfigPackage(this.getBasePackage() + ".config"); + } else { + this.additionalProperties.put(BASE_PACKAGE, basePackage); + this.additionalProperties.put(CONFIG_PACKAGE, this.getConfigPackage()); + this.additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); + this.additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage); + this.additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); + } + if (this.additionalProperties.containsKey("groupId")) { + this.setGroupId((String) this.additionalProperties.get("groupId")); + } else { + // not set, use to be passed to template + additionalProperties.put(CodegenConstants.GROUP_ID, groupId); + } + if (this.additionalProperties.containsKey("artifactId")) { + this.setArtifactId((String) this.additionalProperties.get("artifactId")); + } else { + // not set, use to be passed to template + additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); + } + if (this.additionalProperties.containsKey("artifactVersion")) { + this.setArtifactVersion((String) this.additionalProperties.get("artifactVersion")); + } else { + // not set, use to be passed to template + additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); + } + if (this.additionalProperties.containsKey("serviceName")) { + this.setServiceName((String) this.additionalProperties.get("serviceName")); + } else { + // not set, use to be passed to template + additionalProperties.put("serviceName", serviceName); + } + + if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING)) { + this.setSerializeBigDecimalAsString(Boolean.valueOf( + this.additionalProperties.get(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING).toString())); + } + if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) { + this.setSerializableModel( + Boolean.valueOf(this.additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString())); + } + if (this.additionalProperties.containsKey(TITLE)) { + this.setTitle((String) this.additionalProperties.get(TITLE)); + } + this.additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel); + if (this.additionalProperties.containsKey(FULL_JAVA_UTIL)) { + this.setFullJavaUtil(Boolean.valueOf(this.additionalProperties.get(FULL_JAVA_UTIL).toString())); + } + + if (this.additionalProperties.containsKey(EUREKA_URI)) { + this.setEurekaUri((String) this.additionalProperties.get(EUREKA_URI)); + } + if (this.additionalProperties.containsKey(ZIPKIN_URI)) { + this.setZipkinUri((String) this.additionalProperties.get(ZIPKIN_URI)); + } + if (this.additionalProperties.containsKey(SPRINGADMIN_URI)) { + this.setSpringBootAdminUri((String) this.additionalProperties.get(SPRINGADMIN_URI)); + } + if (fullJavaUtil) { + javaUtilPrefix = "java.util."; + } + this.additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil); + this.additionalProperties.put("javaUtilPrefix", javaUtilPrefix); + this.additionalProperties.put(SUPPORT_JAVA6, false); + this.additionalProperties.put("java8", true); + + if (this.additionalProperties.containsKey(WITH_XML)) { + this.setWithXml(Boolean.valueOf(additionalProperties.get(WITH_XML).toString())); + } + this.additionalProperties.put(WITH_XML, withXml); + + this.apiTemplateFiles.put("api.mustache", ".java"); + this.apiTemplateFiles.put("apiController.mustache", "Controller.java"); + + this.modelTemplateFiles.put("model.mustache", ".java"); + + this.supportingFiles.add(new SupportingFile("SpringBootApplication.mustache", + (this.getSourceFolder() + File.separator + this.getBasePackage()).replace(".", File.separator), + this.getServiceName() + "Application" + ".java")); + + this.supportingFiles + .add(new SupportingFile("config" + File.separator + "swaggerDocumentationConfig.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", + java.io.File.separator) + File.separator + "swagger", + "SwaggerDocumentationConfig.java")); + + this.supportingFiles.add(new SupportingFile("config" + File.separator + "pkmstproperties.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) + + File.separator + "swagger", + "PkmstProperties.java")); + this.supportingFiles.add(new SupportingFile("config" + File.separator + "appconfig.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) + + File.separator, + "AppConfig.java")); + + // Security + this.supportingFiles + .add(new SupportingFile("security" + File.separator + "authorizationServerConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "AuthorizationServerConfiguration.java")); + this.supportingFiles + .add(new SupportingFile("security" + File.separator + "oAuth2SecurityConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "OAuth2SecurityConfiguration.java")); + this.supportingFiles + .add(new SupportingFile("security" + File.separator + "resourceServerConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "ResourceServerConfiguration.java")); + + // logging + + this.supportingFiles.add(new SupportingFile("logging" + File.separator + "httpLoggingFilter.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + File.separator + + "logging", + "HttpLoggingFilter.java")); + + // Resources + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-local.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "application-local.yml")); + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "application-dev.yml")); + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev-config.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "application-dev-config.yml")); + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "bootstrap.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "bootstrap.yml")); + + // POM + this.supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); + + // Readme + this.supportingFiles.add(new SupportingFile("readme.mustache", "", "Readme.md")); + + // manifest + + this.supportingFiles.add(new SupportingFile("manifest.mustache", "", "manifest.yml")); + + // docker + this.supportingFiles.add(new SupportingFile("docker.mustache", "", "Dockerfile")); + + // logstash + + this.supportingFiles.add(new SupportingFile("logstash.mustache", "", "logstash.conf")); + + // Cucumber + this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "executeReport.mustache", + this.testFolder + File.separator + this.basePackage.replace(".", File.separator) + File.separator + + "cucumber" + File.separator + "report", + "ExecuteReport.java")); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "cucumberTest.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", + serviceName + "Test.java")); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "cucumberSteps.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", + serviceName + "Steps.java")); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "package.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", + serviceName + "package-info.java")); + + // test resources + this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "cucumber.mustache", + (("src.test.resources") + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "cucumber", + serviceName + ".feature")); + + this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "bootstrap.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "bootstrap.yml")); + this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "application.properties")); + this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application-test.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "application-test.properties")); + + // Gatling + this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "gatling.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "gatling.conf")); + + this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "application.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "application.conf")); + + this.supportingFiles.add(new SupportingFile( + "gatling" + File.separator + "testapi.mustache", ("src") + File.separator + ("test") + File.separator + + ("scala") + File.separator + ("scalaFiles").replace(".", java.io.File.separator), + "testapi.scala")); + + // adding class for integration test + this.supportingFiles.add(new SupportingFile( + "integration" + File.separator + "integrationtest.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "controller", + serviceName + "IT.java")); + } + + @SuppressWarnings("unchecked") + @Override + public Map postProcessOperations(Map objs) { + Map operations = (Map) objs.get("operations"); + if (operations != null) { + List ops = (List) operations.get("operation"); + for (final CodegenOperation operation : ops) { + List responses = operation.responses; + if (responses != null) { + for (final CodegenResponse resp : responses) { + if ("0".equals(resp.code)) { + resp.code = "200"; + } + doDataTypeAssignment(resp.dataType, new DataTypeAssigner() { + + public void setReturnType(final String returnType) { + resp.dataType = returnType; + } + + public void setReturnContainer(final String returnContainer) { + resp.containerType = returnContainer; + } + }); + } + } + + doDataTypeAssignment(operation.returnType, new DataTypeAssigner() { + + public void setReturnType(final String returnType) { + operation.returnType = returnType; + } + + public void setReturnContainer(final String returnContainer) { + operation.returnContainer = returnContainer; + } + }); + + if (implicitHeaders) { + removeHeadersFromAllParams(operation.allParams); + } + } + } + + return objs; + } + + /** + * This method removes header parameters from the list of parameters and + * also corrects last allParams hasMore state. + * + * @param allParams + * list of all parameters + */ + private void removeHeadersFromAllParams(List allParams) { + if (allParams.isEmpty()) { + return; + } + final ArrayList copy = new ArrayList<>(allParams); + allParams.clear(); + + for (CodegenParameter p : copy) { + if (!p.isHeaderParam) { + allParams.add(p); + } + } + allParams.get(allParams.size() - 1).hasMore = false; + } + + /** + * @param returnType + * The return type that needs to be converted + * @param dataTypeAssigner + * An object that will assign the data to the respective fields + * in the model. + */ + private void doDataTypeAssignment(String returnType, DataTypeAssigner dataTypeAssigner) { + final String rt = returnType; + if (rt == null) { + dataTypeAssigner.setReturnType("Void"); + } else if (rt.startsWith("List")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("List<".length(), end).trim()); + dataTypeAssigner.setReturnContainer("List"); + } + } else if (rt.startsWith("Map")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("Map<".length(), end).split(",")[1].trim()); + dataTypeAssigner.setReturnContainer("Map"); + } + } else if (rt.startsWith("Set")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("Set<".length(), end).trim()); + dataTypeAssigner.setReturnContainer("Set"); + } + } + } + + @Override + public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + super.postProcessModelProperty(model, property); + + if ("null".equals(property.example)) { + property.example = null; + } + + // Add imports for Jackson + if (!Boolean.TRUE.equals(model.isEnum)) { + model.imports.add("JsonProperty"); + + if (Boolean.TRUE.equals(model.hasEnums)) { + model.imports.add("JsonValue"); + } + } else { // enum class + // Needed imports for Jackson's JsonCreator + if (this.additionalProperties.containsKey("jackson")) { + model.imports.add("JsonCreator"); + } + } + + } + + @SuppressWarnings("unchecked") + @Override + public Map postProcessModelsEnum(Map objs) { + objs = super.postProcessModelsEnum(objs); + + // Add imports for Jackson + List> imports = (List>) objs.get("imports"); + List models = (List) objs.get("models"); + for (Object _mo : models) { + Map mo = (Map) _mo; + CodegenModel cm = (CodegenModel) mo.get("model"); + // for enum model + if (Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null) { + cm.imports.add(this.importMapping.get("JsonValue")); + Map item = new HashMap(); + item.put("import", this.importMapping.get("JsonValue")); + imports.add(item); + } + } + + return objs; + } + + @SuppressWarnings("unchecked") + @Override + public void preprocessSwagger(Swagger swagger) { + super.preprocessSwagger(swagger); + if (swagger == null || swagger.getPaths() == null) { + return; + } + if (swagger.getTags() != null) { + List resourcePaths = new ArrayList<>(); + for (Tag tag : swagger.getTags()) { + ResourcePath resourcePath = new ResourcePath(); + resourcePath.setPath(tag.getName()); + resourcePaths.add(resourcePath); + } + this.additionalProperties.put("resourcePaths", resourcePaths); + } + // get vendor extensions + + Map vendorExt = swagger.getInfo().getVendorExtensions(); + if (vendorExt != null && !vendorExt.toString().equals("")) { + if (vendorExt.containsKey("x-codegen")) { + + Map uris = (Map) vendorExt.get("x-codegen"); + if (uris.containsKey("eurekaUri")) { + String eurekaUri = uris.get("eurekaUri"); + additionalProperties.put(EUREKA_URI, eurekaUri); + } + if (uris.containsKey("zipkinUri")) { + String zipkinUri = uris.get("zipkinUri"); + additionalProperties.put(ZIPKIN_URI, zipkinUri); + } + if (uris.containsKey("springBootAdminUri")) { + String springBootAdminUri = uris.get("springBootAdminUri"); + additionalProperties.put(SPRINGADMIN_URI, springBootAdminUri); + } + if (uris.containsKey("pkmstInterceptor")) { + String pkmstInterceptor = uris.get("pkmstInterceptor"); + additionalProperties.put("pkmstInterceptor", pkmstInterceptor); + } + } + } + + for (String pathname : swagger.getPaths().keySet()) { + Path path = swagger.getPath(pathname); + if (path.getOperations() == null) { + continue; + } + for (Operation operation : path.getOperations()) { + boolean hasFormParameters = false; + for (Parameter parameter : operation.getParameters()) { + if (parameter instanceof FormParameter) { + hasFormParameters = true; + } + } + // only add content-Type if its no a GET-Method + if (path.getGet() != null || !operation.equals(path.getGet())) { + String defaultContentType = hasFormParameters ? "application/x-www-form-urlencoded" + : "application/json"; + String contentType = operation.getConsumes() == null || operation.getConsumes().isEmpty() + ? defaultContentType : operation.getConsumes().get(0); + operation.setVendorExtension("x-contentType", contentType); + } + String accepts = getAccept(operation); + operation.setVendorExtension("x-accepts", accepts); + } + } + + if ("/".equals(swagger.getBasePath())) { + swagger.setBasePath(""); + } + + if (!additionalProperties.containsKey(TITLE)) { + // From the title, compute a reasonable name for the package and the + // API + String title = swagger.getInfo().getTitle(); + + // Drop any API suffix + if (title != null) { + title = title.trim().replace(" ", "-"); + if (title.toUpperCase().endsWith("API")) { + title = title.substring(0, title.length() - 3); + } + + this.title = camelize(sanitizeName(title), true); + } + additionalProperties.put(TITLE, this.title); + } + + String host = swagger.getHost(); + String port = "8008"; + if (host != null) { + String[] parts = host.split(":"); + if (parts.length > 1) { + port = parts[1]; + } + } + + this.additionalProperties.put("serverPort", port); + if (swagger.getPaths() != null) { + for (String pathname : swagger.getPaths().keySet()) { + Path path = swagger.getPath(pathname); + if (path.getOperations() != null) { + for (Operation operation : path.getOperations()) { + if (operation.getTags() != null) { + List> tags = new ArrayList>(); + for (String tag : operation.getTags()) { + Map value = new HashMap(); + value.put("tag", tag); + value.put("hasMore", "true"); + tags.add(value); + } + if (tags.size() > 0) { + tags.get(tags.size() - 1).remove("hasMore"); + } + if (operation.getTags().size() > 0) { + String tag = operation.getTags().get(0); + operation.setTags(Arrays.asList(tag)); + } + operation.setVendorExtension("x-tags", tags); + } + } + } + } + } + } + + @Override + public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, + Map> operations) { + super.addOperationToGroup(tag, resourcePath, operation, co, operations); + co.subresourceOperation = !co.path.isEmpty(); + } + + @Override + public String toApiName(String name) { + if (name.length() == 0) { + return "DefaultApi"; + } + name = sanitizeName(name); + return camelize(name) + "Api"; + } + + @Override + public String apiFileFolder() { + return this.outputFolder + "/" + this.sourceFolder + "/" + apiPackage().replace(".", "/"); + } + + @Override + public String apiTestFileFolder() { + return this.outputFolder + "/" + this.testFolder + "/" + apiPackage().replace(".", "/"); + } + + @Override + public String modelFileFolder() { + return this.outputFolder + "/" + this.sourceFolder + "/" + modelPackage().replace(".", "/"); + } + + @Override + public String apiDocFileFolder() { + return (this.outputFolder + "/" + this.apiDocPath).replace("/", File.separator); + } + + @Override + public String modelDocFileFolder() { + return (this.outputFolder + "/" + this.modelDocPath).replace("/", File.separator); + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getArtifactVersion() { + return artifactVersion; + } + + public void setArtifactVersion(String artifactVersion) { + this.artifactVersion = artifactVersion; + } + + public String getProjectFolder() { + return projectFolder; + } + + public void setProjectFolder(String projectFolder) { + this.projectFolder = projectFolder; + } + + public String getEurekaUri() { + return eurekaUri; + } + + public void setEurekaUri(String eurekaUri) { + this.eurekaUri = eurekaUri; + } + + public String getZipkinUri() { + return zipkinUri; + } + + public void setZipkinUri(String zipkinUri) { + this.zipkinUri = zipkinUri; + } + + public String getSpringBootAdminUri() { + return springBootAdminUri; + } + + public void setSpringBootAdminUri(String springBootAdminUri) { + this.springBootAdminUri = springBootAdminUri; + } + + public String getProjectTestFolder() { + return projectTestFolder; + } + + public void setProjectTestFolder(String projectTestFolder) { + this.projectTestFolder = projectTestFolder; + } + + public String getSourceFolder() { + return sourceFolder; + } + + public void setSourceFolder(String sourceFolder) { + this.sourceFolder = sourceFolder; + } + + public String getTestFolder() { + return testFolder; + } + + public void setTestFolder(String testFolder) { + this.testFolder = testFolder; + } + + public String getBasePackage() { + return basePackage; + } + + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public String getConfigPackage() { + return configPackage; + } + + public void setConfigPackage(String configPackage) { + this.configPackage = configPackage; + } + + public boolean isImplicitHeaders() { + return implicitHeaders; + } + + public void setImplicitHeaders(boolean implicitHeaders) { + this.implicitHeaders = implicitHeaders; + } + + public boolean isSerializeBigDecimalAsString() { + return serializeBigDecimalAsString; + } + + public void setSerializeBigDecimalAsString(boolean serializeBigDecimalAsString) { + this.serializeBigDecimalAsString = serializeBigDecimalAsString; + } + + public boolean isFullJavaUtil() { + return fullJavaUtil; + } + + public void setFullJavaUtil(boolean fullJavaUtil) { + this.fullJavaUtil = fullJavaUtil; + } + + public Boolean getSerializableModel() { + return serializableModel; + } + + public void setSerializableModel(Boolean serializableModel) { + this.serializableModel = serializableModel; + } + + public String getInvokerPackage() { + return invokerPackage; + } + + public void setInvokerPackage(String invokerPackage) { + this.invokerPackage = invokerPackage; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public boolean isWithXml() { + return withXml; + } + + public void setWithXml(boolean withXml) { + this.withXml = withXml; + } + + private interface DataTypeAssigner { + + void setReturnType(String returnType); + + void setReturnContainer(String returnContainer); + } + + private class ResourcePath { + + private String path; + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + @Override + public String toString() { + return this.path; + } + } +} diff --git a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig index 5c5d4220bad..38ab874450a 100644 --- a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig +++ b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig @@ -33,6 +33,7 @@ io.swagger.codegen.languages.JavaJAXRSSpecServerCodegen io.swagger.codegen.languages.JavaJerseyServerCodegen io.swagger.codegen.languages.JavaJerseyServerCodegen io.swagger.codegen.languages.JavaMSF4JServerCodegen +io.swagger.codegen.languages.JavaPKMSTServerCodegen io.swagger.codegen.languages.JavaPlayFrameworkCodegen io.swagger.codegen.languages.JavaResteasyEapServerCodegen io.swagger.codegen.languages.JavaResteasyServerCodegen @@ -47,7 +48,6 @@ io.swagger.codegen.languages.NodeJSServerCodegen io.swagger.codegen.languages.ObjcClientCodegen io.swagger.codegen.languages.PerlClientCodegen io.swagger.codegen.languages.PhpClientCodegen -io.swagger.codegen.languages.SymfonyServerCodegen io.swagger.codegen.languages.PowerShellClientCodegen io.swagger.codegen.languages.PistacheServerCodegen io.swagger.codegen.languages.PythonClientCodegen @@ -74,6 +74,7 @@ io.swagger.codegen.languages.SwaggerYamlGenerator io.swagger.codegen.languages.Swift4Codegen io.swagger.codegen.languages.Swift3Codegen io.swagger.codegen.languages.SwiftCodegen +io.swagger.codegen.languages.SymfonyServerCodegen io.swagger.codegen.languages.TizenClientCodegen io.swagger.codegen.languages.TypeScriptAureliaClientCodegen io.swagger.codegen.languages.TypeScriptAngularClientCodegen @@ -82,4 +83,4 @@ io.swagger.codegen.languages.TypeScriptFetchClientCodegen io.swagger.codegen.languages.TypeScriptJqueryClientCodegen io.swagger.codegen.languages.TypeScriptNodeClientCodegen io.swagger.codegen.languages.UndertowCodegen -io.swagger.codegen.languages.ZendExpressivePathHandlerServerCodegen \ No newline at end of file +io.swagger.codegen.languages.ZendExpressivePathHandlerServerCodegen diff --git a/modules/swagger-codegen/src/main/resources/pkmst/RFC3339DateFormat.mustache b/modules/swagger-codegen/src/main/resources/pkmst/RFC3339DateFormat.mustache new file mode 100644 index 00000000000..afe24ed9aba --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/RFC3339DateFormat.mustache @@ -0,0 +1,20 @@ +package {{basePackage}}; + +import com.fasterxml.jackson.databind.util.ISO8601DateFormat; +import com.fasterxml.jackson.databind.util.ISO8601Utils; + +import java.text.FieldPosition; +import java.util.Date; + + +public class RFC3339DateFormat extends ISO8601DateFormat { + + // Same as ISO8601DateFormat but serializing milliseconds. + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { + String value = ISO8601Utils.format(date, true); + toAppendTo.append(value); + return toAppendTo; + } + +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/SpringBootApplication.mustache b/modules/swagger-codegen/src/main/resources/pkmst/SpringBootApplication.mustache new file mode 100644 index 00000000000..30ef294c8b2 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/SpringBootApplication.mustache @@ -0,0 +1,36 @@ +package {{basePackage}}; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; +{{#eurekaUri}} +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +{{/eurekaUri}} +import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * starts the spring boot application + * @author pkmst + * + */ + +@SpringBootApplication +@EnableSwagger2 +{{#eurekaUri}} +@EnableEurekaClient +{{/eurekaUri}} +@EnableCircuitBreaker +@EnableHystrixDashboard +public class {{serviceName}}Application { + + private static final Logger LOGGER = LoggerFactory.getLogger({{serviceName}}Application.class); + + public static void main(String[] args) { + LOGGER.debug("Running spring boot application"); + SpringApplication.run({{serviceName}}Application.class, args); + } +} + diff --git a/modules/swagger-codegen/src/main/resources/pkmst/api.mustache b/modules/swagger-codegen/src/main/resources/pkmst/api.mustache new file mode 100644 index 00000000000..27a199fba13 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/api.mustache @@ -0,0 +1,87 @@ +/** + * NOTE: This class is auto generated by the swagger code generator program ({{{generatorVersion}}}). + * https://github.com/swagger-api/swagger-codegen + * Do not edit the class manually. + */ +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} + +import io.swagger.annotations.*; +{{#jdk8}} +import org.springframework.http.HttpStatus; +{{/jdk8}} +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +{{^useSpringCloudClient}} +import java.io.IOException; +{{/useSpringCloudClient}} + +import java.util.List; +{{#useOptional}} +import java.util.Optional; +{{/useOptional}} +{{#async}} +import java.util.concurrent.{{^jdk8}}Callable{{/jdk8}}{{#jdk8}}CompletableFuture{{/jdk8}}; +{{/async}} +{{#useBeanValidation}} +import org.springframework.validation.annotation.Validated; +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} +/** + * Provides the info about api methods + * @author pkmst + * + */ +{{>generatedAnnotation}} +@Api(value = "{{{baseName}}}", description = "the {{{baseName}}} API") +{{#operations}} +public interface {{classname}} { +{{#operation}} + + @ApiOperation(value = "{{{summary}}}", notes = "{{{notes}}}", response = {{{returnType}}}.class{{#returnContainer}}, responseContainer = "{{{returnContainer}}}"{{/returnContainer}}{{#hasAuthMethods}}, authorizations = { + {{#authMethods}}@Authorization(value = "{{name}}"{{#isOAuth}}, scopes = { + {{#scopes}}@AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{#hasMore}}, + {{/hasMore}}{{/scopes}} + }{{/isOAuth}}){{#hasMore}}, + {{/hasMore}}{{/authMethods}} + }{{/hasAuthMethods}}, tags={ {{#vendorExtensions.x-tags}}"{{tag}}",{{/vendorExtensions.x-tags}} }) + @ApiResponses(value = { {{#responses}} + @ApiResponse(code = {{{code}}}, message = "{{{message}}}"{{#baseType}}, response = {{{baseType}}}.class{{/baseType}}{{#containerType}}, responseContainer = "{{{containerType}}}"{{/containerType}}){{#hasMore}},{{/hasMore}}{{/responses}} }) + {{#implicitHeaders}} + @ApiImplicitParams({ + {{#headerParams}}{{>implicitHeader}}{{/headerParams}} + }) + {{/implicitHeaders}} + @RequestMapping(value = "{{{path}}}",{{#singleContentTypes}} + produces = "{{{vendorExtensions.x-accepts}}}", + consumes = "{{{vendorExtensions.x-contentType}}}",{{/singleContentTypes}}{{^singleContentTypes}}{{#hasProduces}} + produces = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }, {{/hasProduces}}{{#hasConsumes}} + consumes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} },{{/hasConsumes}}{{/singleContentTypes}} + method = RequestMethod.{{httpMethod}}) +{{#useSpringCloudClient}} + {{#jdk8}}default {{/jdk8}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},{{/hasMore}}{{/allParams}}){{^jdk8}};{{/jdk8}}{{#jdk8}} { + // do some magic! + return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<{{>returnTypes}}>(HttpStatus.NOT_IMPLEMENTED){{#async}}){{/async}}; + }{{/jdk8}} + +{{/useSpringCloudClient}} +{{^useSpringCloudClient}} + {{#jdk8}}default {{/jdk8}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}},{{/allParams}} @RequestHeader(value = "Accept", required = false) String accept) throws Exception{{^jdk8}};{{/jdk8}}{{#jdk8}} { + // do some magic! + return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK){{#async}}){{/async}}; + }{{/jdk8}} + +{{/useSpringCloudClient}} +{{/operation}} +} +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/apiController.mustache b/modules/swagger-codegen/src/main/resources/pkmst/apiController.mustache new file mode 100644 index 00000000000..602df07de08 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/apiController.mustache @@ -0,0 +1,115 @@ +package {{package}}; + +{{^jdk8-no-delegate}} +{{#imports}}import {{import}}; +{{/imports}} + +import io.swagger.annotations.*; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +{{/jdk8-no-delegate}} +import org.springframework.stereotype.Controller; +{{^jdk8-no-delegate}} +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +{{#useOptional}} +import java.util.Optional; +{{/useOptional}} +{{#async}} +import java.util.concurrent.Callable; +{{/async}} +{{/jdk8-no-delegate}} +{{^useSpringCloudClient}} +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +{{/useSpringCloudClient}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} +/** + * Api implemention + * @author pkmst + * + */ +{{>generatedAnnotation}} +@Controller +{{#operations}} +public class {{classname}}Controller implements {{classname}} { + private final ObjectMapper objectMapper; +@Autowired + public {{classname}}Controller(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + +{{#isDelegate}} + private final {{classname}}Delegate delegate; + + @org.springframework.beans.factory.annotation.Autowired + public {{classname}}Controller({{classname}}Delegate delegate) { + this.delegate = delegate; + } + +{{/isDelegate}} +{{^jdk8-no-delegate}} +{{#operation}} + public {{#async}}Callable<{{/async}}ResponseEntity<{{>returnTypes}}>{{#async}}>{{/async}} {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}, + {{/allParams}}@RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! +{{#useSpringCloudClient}} + {{^isDelegate}} + {{^async}} + return new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK); + {{/async}} + {{#async}} + return new CallablereturnTypes}}>>() { + @Override + public ResponseEntity<{{>returnTypes}}> call() throws Exception { + return new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK); + } + }; + {{/async}} + {{/isDelegate}} + {{#isDelegate}} + return delegate.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/isDelegate}} +{{/useSpringCloudClient}} +{{^useSpringCloudClient}} + {{^isDelegate}} + {{^async}} + {{#examples}} + + if (accept != null && accept.contains("{{{contentType}}}")) { + return new ResponseEntity<{{>returnTypes}}>(objectMapper.readValue("{{#lambdaRemoveLineBreak}}{{#lambdaEscapeDoubleQuote}}{{{example}}}{{/lambdaEscapeDoubleQuote}}{{/lambdaRemoveLineBreak}}", {{>exampleReturnTypes}}.class), HttpStatus.OK); + } + + {{/examples}} + return new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK); + {{/async}} + {{#async}} + return new CallablereturnTypes}}>>() { + @Override + public ResponseEntity<{{>returnTypes}}> call() throws Exception { + return new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK); + } + }; + {{/async}} + {{/isDelegate}} + {{#isDelegate}} + return delegate.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/isDelegate}} +{{/useSpringCloudClient}} + } + +{{/operation}} +{{/jdk8-no-delegate}} +} +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/api_test.mustache b/modules/swagger-codegen/src/main/resources/pkmst/api_test.mustache new file mode 100644 index 00000000000..615a0b9b71f --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/api_test.mustache @@ -0,0 +1,57 @@ +{{>licenseInfo}} + +package {{package}}; + +import com.fasterxml.jackson.databind.ObjectMapper; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + private final {{classname}} api = new {{classname}}Controller(objectMapper); + + private final String accept = "application/json"; + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws Exception + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws Exception { + {{#allParams}} + {{^isFile}} + {{{dataType}}} {{paramName}} = null; + {{/isFile}} + {{#isFile}} + MultipartFile {{paramName}} = null; + {{/isFile}} + {{/allParams}} + ResponseEntity<{{>returnTypes}}> response = api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}} {{#allParams}}{{^hasMore}},{{/hasMore}}{{/allParams}} accept); + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/beanValidation.mustache b/modules/swagger-codegen/src/main/resources/pkmst/beanValidation.mustache new file mode 100644 index 00000000000..3e4ef612a4c --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/beanValidation.mustache @@ -0,0 +1,6 @@ +{{#required}} + @NotNull +{{/required}}{{#isContainer}}{{^isPrimitiveType}}{{^isEnum}} + @Valid{{/isEnum}}{{/isPrimitiveType}}{{/isContainer}}{{#isNotContainer}}{{^isPrimitiveType}} + @Valid{{/isPrimitiveType}}{{/isNotContainer}} +{{>beanValidationCore}} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/beanValidationPathParams.mustache b/modules/swagger-codegen/src/main/resources/pkmst/beanValidationPathParams.mustache new file mode 100644 index 00000000000..051bd53c0a5 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/beanValidationPathParams.mustache @@ -0,0 +1 @@ +{{! PathParam is always required, no @NotNull necessary }}{{>beanValidationCore}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/beanValidationQueryParams.mustache b/modules/swagger-codegen/src/main/resources/pkmst/beanValidationQueryParams.mustache new file mode 100644 index 00000000000..9cca8cb8874 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/beanValidationQueryParams.mustache @@ -0,0 +1 @@ +{{#required}}@NotNull {{/required}}{{>beanValidationCore}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/bodyParams.mustache b/modules/swagger-codegen/src/main/resources/pkmst/bodyParams.mustache new file mode 100644 index 00000000000..7fef9ad2b6f --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/bodyParams.mustache @@ -0,0 +1 @@ +{{#isBodyParam}}@ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}} {{^isContainer}}{{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{/isContainer}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestBody {{{dataType}}} {{paramName}}{{/isBodyParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/config/appconfig.mustache b/modules/swagger-codegen/src/main/resources/pkmst/config/appconfig.mustache new file mode 100644 index 00000000000..67d99d563e8 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/config/appconfig.mustache @@ -0,0 +1,101 @@ +package {{basePackage}}.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +{{#pkmstInterceptor}} +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import com.prokarma.pkmst.interceptor.AuditInterceptor; +import com.prokarma.pkmst.interceptor.BodyInterceptor; +//import com.prokarma.pkmst.interceptor.CorrelationInterceptor; +import com.prokarma.pkmst.interceptor.RateLimitInterceptor; +import com.prokarma.pkmst.interceptor.TraceabilityInterceptor; +{{/pkmstInterceptor}} +/** + * Registers the interceptors which are configurable via yaml + * @author pkmst + * + */ +@Configuration +public class AppConfig extends WebMvcConfigurerAdapter { + {{#pkmstInterceptor}} + @Value("${interceptor.enable.traceability:false}") + boolean traceabilityEnable; + @Bean + public HandlerInterceptor traceabilityInterceptor() { + return new TraceabilityInterceptor(); + } + @Value("${interceptor.enable.correlation:false}") + boolean correlationEnable; + /*@Bean + public HandlerInterceptor correlationInterceptor() { + return new CorrelationInterceptor(); + }*/ + @Value("${interceptor.enable.rateLimit:false}") + boolean rateLimitEnable; + @Bean + public HandlerInterceptor rateLimitInterceptor() { + return new RateLimitInterceptor(); + } + @Value("${interceptor.enable.audit:false}") + boolean auditEnable; + @Bean + public HandlerInterceptor auditInterceptor() { + return new AuditInterceptor(); + } + @Value("${interceptor.enable.body:false}") + boolean bodyEnable; + @Bean + public HandlerInterceptor bodyInterceptor() { + return new BodyInterceptor(); + } + + + @Override + public void addInterceptors(InterceptorRegistry registry) { + + if (traceabilityEnable) { + registry.addInterceptor(traceabilityInterceptor()); + } + if (correlationEnable) { + // registry.addInterceptor(correlationInterceptor); + } + if (rateLimitEnable) { + registry.addInterceptor(rateLimitInterceptor()); + } + if (auditEnable) { + registry.addInterceptor(auditInterceptor()); + } + if (bodyEnable) { + registry.addInterceptor(bodyInterceptor()); + } + + + + } + + {{/pkmstInterceptor}} + /** + * enabling cors support at global level which can be applied at various + * level also as below registry.addMapping("/api/**") + * .allowedOrigins("http://domain2.com") .allowedMethods("PUT", "DELETE") + * .allowedHeaders("header1", "header2", "header3") + * .exposedHeaders("header1", "header2") + * .allowCredentials(false).maxAge(3600); + * + * @return + */ + @Bean + public WebMvcConfigurer corsConfigurer() { + return new WebMvcConfigurerAdapter() { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**"); + } + }; + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/config/pkmstproperties.mustache b/modules/swagger-codegen/src/main/resources/pkmst/config/pkmstproperties.mustache new file mode 100644 index 00000000000..86554ed8cc8 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/config/pkmstproperties.mustache @@ -0,0 +1,113 @@ +package {{basePackage}}.config.swagger; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +/** + * Provides the swagger API info + * @author pkmst + * + */ +@Configuration +@ConfigurationProperties(prefix = "pkmst", ignoreUnknownFields = false) +public class PkmstProperties { + + private final Swagger swagger = new Swagger(); + + + public Swagger getSwagger() { + return swagger; + } + + + public static class Swagger { + + private String title = "Pkmst API"; + + private String description = "Pkmst API documentation"; + + private String version = "0.0.1"; + + private String termsOfServiceUrl; + + private String contactName; + + private String contactUrl; + + private String contactEmail; + + private String license; + + private String licenseUrl; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getTermsOfServiceUrl() { + return termsOfServiceUrl; + } + + public void setTermsOfServiceUrl(String termsOfServiceUrl) { + this.termsOfServiceUrl = termsOfServiceUrl; + } + + public String getContactName() { + return contactName; + } + + public void setContactName(String contactName) { + this.contactName = contactName; + } + + public String getContactUrl() { + return contactUrl; + } + + public void setContactUrl(String contactUrl) { + this.contactUrl = contactUrl; + } + + public String getContactEmail() { + return contactEmail; + } + + public void setContactEmail(String contactEmail) { + this.contactEmail = contactEmail; + } + + public String getLicense() { + return license; + } + + public void setLicense(String license) { + this.license = license; + } + + public String getLicenseUrl() { + return licenseUrl; + } + + public void setLicenseUrl(String licenseUrl) { + this.licenseUrl = licenseUrl; + } + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/config/swaggerDocumentationConfig.mustache b/modules/swagger-codegen/src/main/resources/pkmst/config/swaggerDocumentationConfig.mustache new file mode 100644 index 00000000000..08c74b4b824 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/config/swaggerDocumentationConfig.mustache @@ -0,0 +1,61 @@ +package {{basePackage}}.config.swagger; + +import java.util.Date; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.ResponseEntity; +import org.springframework.util.StopWatch; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +//import static springfox.documentation.builders.PathSelectors.regex; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; +/** + * Enable swagger ui for application + * @author pkmst + * + */ +@EnableSwagger2 +@Configuration +public class SwaggerDocumentationConfig { + + public static final String DEFAULT_INCLUDE_PATTERN = "/pkmst/.*"; + @Bean + public Docket swaggerSpringfoxDocket(PkmstProperties pkmstProperties) { + StopWatch watch = new StopWatch(); + watch.start(); + Contact contact = new Contact( + pkmstProperties.getSwagger().getContactName(), + pkmstProperties.getSwagger().getContactUrl(), + pkmstProperties.getSwagger().getContactEmail()); + + ApiInfo apiInfo = new ApiInfo( + pkmstProperties.getSwagger().getTitle(), + pkmstProperties.getSwagger().getDescription(), + pkmstProperties.getSwagger().getVersion(), + pkmstProperties.getSwagger().getTermsOfServiceUrl(), + contact, + pkmstProperties.getSwagger().getLicense(), + pkmstProperties.getSwagger().getLicenseUrl()); + + Docket docket = new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo) + .forCodeGeneration(true) + .genericModelSubstitutes(ResponseEntity.class) + .ignoredParameterTypes(java.sql.Date.class) + .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class) + .directModelSubstitute(java.time.ZonedDateTime.class, Date.class) + .directModelSubstitute(java.time.LocalDateTime.class, Date.class) + .select() + .apis(RequestHandlerSelectors.basePackage("com.prokarma.pkmst")) + // .paths(regex(DEFAULT_INCLUDE_PATTERN)) + .paths(PathSelectors.any()) + .build(); + watch.stop(); + return docket; + } + +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumber.mustache b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumber.mustache new file mode 100644 index 00000000000..a22095793d4 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumber.mustache @@ -0,0 +1,33 @@ +#Feature: List of scenarios. +#Scenario: Business rule through list of steps with arguments. +#Given: Some precondition step +#When: Some key actions +#Then: To observe outcomes or validation +#And,But: To enumerate more Given,When,Then steps +#Scenario Outline: List of steps for data-driven as an Examples and + +#Sample Feature Definition Template +@tag +Feature: Title of your feature + I want to use this template for my feature file + +@tag1 +Scenario: Title of your scenario +Given I want to write a step with precondition + And some other precondition +When I complete action + And some other action + And yet another action +Then I validate the outcomes + And check more outcomes + +@tag2 +Scenario Outline: Title of your scenario outline +Given I want to write a step with +When I check for the in step +Then I verify the in step + +Examples: + | name |value | status | + | name1 | 5 | success| + | name2 | 7 | Fail | \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumberSteps.mustache b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumberSteps.mustache new file mode 100644 index 00000000000..d2c9398f7cd --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumberSteps.mustache @@ -0,0 +1,76 @@ +package {{basePackage}}.cucumber; +import cucumber.api.java.After; +import cucumber.api.java.Before; +import cucumber.api.java.en.Given; +import cucumber.api.java.en.Then; +import cucumber.api.java.en.When; +import cucumber.api.PendingException; + +public class {{serviceName}}Steps { + +@Given("^I want to write a step with precondition$") +public void i_want_to_write_a_step_with_precondition() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Given("^some other precondition$") +public void some_other_precondition() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^I complete action$") +public void i_complete_action() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^some other action$") +public void some_other_action() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^yet another action$") +public void yet_another_action() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^I validate the outcomes$") +public void i_validate_the_outcomes() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^check more outcomes$") +public void check_more_outcomes() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Given("^I want to write a step with name(\\d+)$") +public void i_want_to_write_a_step_with_name(int arg1) throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^I check for the (\\d+) in step$") +public void i_check_for_the_in_step(int arg1) throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^I verify the success in step$") +public void i_verify_the_success_in_step() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^I verify the Fail in step$") +public void i_verify_the_Fail_in_step() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumberTest.mustache b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumberTest.mustache new file mode 100644 index 00000000000..684121ae59b --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumberTest.mustache @@ -0,0 +1,15 @@ +package {{basePackage}}.cucumber; + +import org.junit.runner.RunWith; +import org.springframework.test.context.ActiveProfiles; +import cucumber.api.CucumberOptions; +import cucumber.api.junit.Cucumber; + +@RunWith(Cucumber.class) +@ActiveProfiles("test") +@CucumberOptions(format = { "pretty", "html:target/cucumber-html-report", +{{#resourcePaths}} + "json:./report/{{path}}-report-json/{{path}}.json", +{{/resourcePaths}} }) +public class {{serviceName}}Test { +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/cucumber/executeReport.mustache b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/executeReport.mustache new file mode 100644 index 00000000000..c60e1ca5642 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/executeReport.mustache @@ -0,0 +1,42 @@ +package {{basePackage}}.cucumber.report; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import net.masterthought.cucumber.Configuration; +import net.masterthought.cucumber.ReportBuilder; + +public class ExecuteReport { + + public static void main(String[] args) { + generateReport(); + } + + private static void generateReport() { + String buildNumber = "1"; + String projectName = "Spring-micro-sample"; + boolean runWithJenkins = false; + boolean parallelTesting = false; + + File reportOutputDirectory = null; + List jsonFiles = null; + Configuration configuration = null; + ReportBuilder reportBuilder = null; + {{#resourcePaths}} + reportOutputDirectory = new File("./report/{{path}}-report-html/"); + jsonFiles = new ArrayList(); + jsonFiles.add("./report/{{path}}-report-json/{{path}}.json"); + + configuration = new Configuration(reportOutputDirectory,projectName); + // optionally only if you need + configuration.setParallelTesting(parallelTesting); + configuration.setRunWithJenkins(runWithJenkins); + configuration.setBuildNumber(buildNumber); + + reportBuilder = new ReportBuilder(jsonFiles, configuration); + reportBuilder.generateReports(); + {{/resourcePaths}} + + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/cucumber/package.mustache b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/package.mustache new file mode 100644 index 00000000000..cfc71028133 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/package.mustache @@ -0,0 +1,2 @@ +package {{basePackage}}.cucumber; +//Implement the feature file steps in this package. \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/docker.mustache b/modules/swagger-codegen/src/main/resources/pkmst/docker.mustache new file mode 100644 index 00000000000..a742c3dbb10 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/docker.mustache @@ -0,0 +1,3 @@ +FROM frolvlad/alpine-oraclejdk8:slim +COPY target/{{artifactId}}.jar app.jar +ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/docs/swaggercodegnimage.png b/modules/swagger-codegen/src/main/resources/pkmst/docs/swaggercodegnimage.png new file mode 100644 index 00000000000..f7a3cc491ad Binary files /dev/null and b/modules/swagger-codegen/src/main/resources/pkmst/docs/swaggercodegnimage.png differ diff --git a/modules/swagger-codegen/src/main/resources/pkmst/enumClass.mustache b/modules/swagger-codegen/src/main/resources/pkmst/enumClass.mustache new file mode 100644 index 00000000000..c5c3143cb94 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/enumClass.mustache @@ -0,0 +1,44 @@ + /** + * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{{description}}}{{/description}} + */ + public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { + {{#gson}} + {{#allowableValues}} + {{#enumVars}} + @SerializedName({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}} + {{/enumVars}} + {{/allowableValues}} + {{/gson}} + {{^gson}} + {{#allowableValues}} + {{#enumVars}} + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}} + {{/enumVars}} + {{/allowableValues}} + {{/gson}} + + private {{{datatype}}} value; + + {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}({{{datatype}}} value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + return null; + } + } diff --git a/modules/swagger-codegen/src/main/resources/pkmst/enumOuterClass.mustache b/modules/swagger-codegen/src/main/resources/pkmst/enumOuterClass.mustache new file mode 100644 index 00000000000..76c2cbf5a76 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/enumOuterClass.mustache @@ -0,0 +1,42 @@ +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonCreator; +{{/jackson}} + +/** + * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{{description}}}{{/description}} + */ +public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { + {{#gson}} + {{#allowableValues}}{{#enumVars}} + @SerializedName({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} + {{/gson}} + {{^gson}} + {{#allowableValues}}{{#enumVars}} + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} + {{/gson}} + + private {{{dataType}}} value; + + {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + return null; + } +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/exampleReturnTypes.mustache b/modules/swagger-codegen/src/main/resources/pkmst/exampleReturnTypes.mustache new file mode 100644 index 00000000000..395e3889c20 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/exampleReturnTypes.mustache @@ -0,0 +1 @@ +{{#returnContainer}}{{#isMapContainer}}Map{{/isMapContainer}}{{#isListContainer}}List{{/isListContainer}}{{/returnContainer}}{{^returnContainer}}{{{returnType}}}{{/returnContainer}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/formParams.mustache b/modules/swagger-codegen/src/main/resources/pkmst/formParams.mustache new file mode 100644 index 00000000000..8f6cb5213c4 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/formParams.mustache @@ -0,0 +1 @@ +{{#isFormParam}}{{#notFile}}@ApiParam(value = "{{{description}}}"{{#required}}, required=true{{/required}}{{#allowableValues}}, allowableValues="{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @RequestPart(value="{{baseName}}"{{#required}}, required=true{{/required}}{{^required}}, required=false{{/required}}) {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}@ApiParam(value = "file detail") {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestPart("file") MultipartFile {{baseName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/gatling/application.mustache b/modules/swagger-codegen/src/main/resources/pkmst/gatling/application.mustache new file mode 100644 index 00000000000..6a42f95f1fa --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/gatling/application.mustache @@ -0,0 +1,14 @@ +#################################### +# Akka Actor Config File # +#################################### + +akka { + scheduler { + tick-duration = 50ms + } +} + +url="http://localhost:8081" +noOfUsers=10 #Number of Users +deleteProductId=4 #Delete the Product by using productID +getProduct=2 #Get the Product \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/gatling/gatling.mustache b/modules/swagger-codegen/src/main/resources/pkmst/gatling/gatling.mustache new file mode 100644 index 00000000000..c7b4fa7f8c8 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/gatling/gatling.mustache @@ -0,0 +1,157 @@ +######################### +# Gatling Configuration # +######################### + +# This file contains all the settings configurable for Gatling with their default values + +gatling { + core { + #outputDirectoryBaseName = "" # The prefix for each simulation result folder (then suffixed by the report generation timestamp) + #runDescription = "" # The description for this simulation run, displayed in each report + #encoding = "utf-8" # Encoding to use throughout Gatling for file and string manipulation + #simulationClass = "" # The FQCN of the simulation to run (when used in conjunction with noReports, the simulation for which assertions will be validated) + #mute = false # When set to true, don't ask for simulation name nor run description (currently only used by Gatling SBT plugin) + + extract { + regex { + #cacheMaxCapacity = 200 # Cache size for the compiled regexes, set to 0 to disable caching + } + xpath { + #cacheMaxCapacity = 200 # Cache size for the compiled XPath queries, set to 0 to disable caching + } + jsonPath { + #cacheMaxCapacity = 200 # Cache size for the compiled jsonPath queries, set to 0 to disable caching + #preferJackson = false # When set to true, prefer Jackson over Boon for JSON-related operations + jackson { + #allowComments = false # Allow comments in JSON files + #allowUnquotedFieldNames = false # Allow unquoted JSON fields names + #allowSingleQuotes = false # Allow single quoted JSON field names + } + + } + css { + #cacheMaxCapacity = 200 # Cache size for the compiled CSS selectors queries, set to 0 to disable caching + } + } + + timeOut { + #simulation = 8640000 # Absolute timeout, in seconds, of a simulation + } + directory { + #data = src/test/resource/data # Folder where user's data (e.g. files used by Feeders) is located + #bodies = src/test/resource/bodies # Folder where bodies are located + #simulations = user-src/test/java/simulations # Folder where the bundle's simulations are located< + #reportsOnly = "" # If set, name of report folder to look for in order to generate its report + #binaries = "" # If set, name of the folder where compiles classes are located: Defaults to GATLING_HOME/target. + #results = results # Name of the folder where all reports folder are located + } + } + charting { + #noReports = false # When set to true, don't generate HTML reports + #maxPlotPerSeries = 1000 # Number of points per graph in Gatling reports + #accuracy = 10 # Accuracy, in milliseconds, of the report's stats + indicators { + #lowerBound = 800 # Lower bound for the requests' response time to track in the reports and the console summary + #higherBound = 1200 # Higher bound for the requests' response time to track in the reports and the console summary + #percentile1 = 50 # Value for the 1st percentile to track in the reports, the console summary and GraphiteDataWriter + #percentile2 = 75 # Value for the 2nd percentile to track in the reports, the console summary and GraphiteDataWriter + #percentile3 = 95 # Value for the 3rd percentile to track in the reports, the console summary and GraphiteDataWriter + #percentile4 = 99 # Value for the 4th percentile to track in the reports, the console summary and GraphiteDataWriter + } + } + http { + #elFileBodiesCacheMaxCapacity = 200 # Cache size for request body EL templates, set to 0 to disable + #rawFileBodiesCacheMaxCapacity = 200 # Cache size for request body Raw templates, set to 0 to disable + #fetchedCssCacheMaxCapacity = 200 # Cache size for CSS parsed content, set to 0 to disable + #fetchedHtmlCacheMaxCapacity = 200 # Cache size for HTML parsed content, set to 0 to disable + #redirectPerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent redirects, set to 0 to disable + #expirePerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent 'Expire' headers, set to 0 to disable + #lastModifiedPerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent 'Last-Modified' headers, set to 0 to disable + #etagPerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent ETag headers, set to 0 to disable + #warmUpUrl = "http://gatling.io" # The URL to use to warm-up the HTTP stack (blank means disabled) + #enableGA = true # Very light Google Analytics, please support + ssl { + trustStore { + #type = "" # Type of SSLContext's TrustManagers store + #file = "" # Location of SSLContext's TrustManagers store + #password = "" # Password for SSLContext's TrustManagers store + #algorithm = "" # Algorithm used by SSLContext's TrustManagers store + } + keyStore { + #type = "" # Type of SSLContext's KeyManagers store + #file = "" # Location of SSLContext's KeyManagers store + #password = "" # Password for SSLContext's KeyManagers store + #algorithm = "" # Algorithm used SSLContext's KeyManagers store + } + } + ahc { + #allowPoolingConnections = true # Allow pooling HTTP connections (keep-alive header automatically added) + #allowPoolingSslConnections = true # Allow pooling HTTPS connections (keep-alive header automatically added) + #compressionEnforced = false # Enforce gzip/deflate when Accept-Encoding header is not defined + #connectTimeout = 60000 # Timeout when establishing a connection + #pooledConnectionIdleTimeout = 60000 # Timeout when a connection stays unused in the pool + #readTimeout = 60000 # Timeout when a used connection stays idle + #connectionTTL = -1 # Max duration a connection can stay open (-1 means no limit) + #ioThreadMultiplier = 2 # Number of Netty worker threads per core + #maxConnectionsPerHost = -1 # Max number of connections per host (-1 means no limit) + #maxConnections = -1 # Max number of connections (-1 means no limit) + #maxRetry = 2 # Number of times that a request should be tried again + #requestTimeout = 60000 # Timeout of the requests + #useProxyProperties = false # When set to true, supports standard Proxy System properties + #webSocketTimeout = 60000 # Timeout when a used websocket connection stays idle + #useRelativeURIsWithConnectProxies = true # When set to true, use relative URIs when talking with an SSL proxy or a WebSocket proxy + #acceptAnyCertificate = true # When set to true, doesn't validate SSL certificates + #httpClientCodecMaxInitialLineLength = 4096 # Maximum length of the initial line of the response (e.g. "HTTP/1.0 200 OK") + #httpClientCodecMaxHeaderSize = 8192 # Maximum size, in bytes, of each request's headers + #httpClientCodecMaxChunkSize = 8192 # Maximum length of the content or each chunk + #keepEncodingHeader = true # Don't drop Encoding response header after decoding + #webSocketMaxFrameSize = 10240 # Maximum frame payload size + #httpsEnabledProtocols = "" # Comma separated enabled protocols for HTTPS, if empty use the JDK defaults + #httpsEnabledCipherSuites = "" # Comma separated enabled cipher suites for HTTPS, if empty use the JDK defaults + #sslSessionCacheSize = 20000 # SSLSession cache size (set to 0 to disable) + #sslSessionTimeout = 86400 # SSLSession timeout (default is 24, like Hotspot) + } + } + data { + #writers = "console, file" # The lists of DataWriters to which Gatling write simulation data (currently supported : "console", "file", "graphite", "jdbc") + #reader = file # The DataReader used by the charting engine for reading simulation results + console { + #light = false # When set to true, displays a light version without detailed request stats + } + file { + #bufferSize = 8192 # FileDataWriter's internal data buffer size, in bytes + } + leak { + #noActivityTimeout = 30 # Period, in seconds, for which Gatling may have no activity before considering a leak may be happening + } + jdbc { + db { + #url = "jdbc:mysql://localhost:3306/temp" # The JDBC URL used by the JDBC DataWriter + #username = "root" # The database user used by the JDBC DataWriter + #password = "123123q" # The password for the specified user + } + #bufferSize = 20 # The size for each batch of SQL inserts to send to the database + create { + #createRunRecordTable = "CREATE TABLE IF NOT EXISTS `RunRecords` ( `id` INT NOT NULL AUTO_INCREMENT , `runDate` DATETIME NULL , `simulationId` VARCHAR(45) NULL , `runDescription` VARCHAR(45) NULL , PRIMARY KEY (`id`) )" + #createRequestRecordTable = "CREATE TABLE IF NOT EXISTS `RequestRecords` (`id` int(11) NOT NULL AUTO_INCREMENT, `runId` int DEFAULT NULL, `scenario` varchar(45) DEFAULT NULL, `userId` VARCHAR(30) NULL, `name` varchar(50) DEFAULT NULL, `requestStartDate` bigint DEFAULT NULL, `requestEndDate` bigint DEFAULT NULL, `responseStartDate` bigint DEFAULT NULL, `responseEndDate` bigint DEFAULT NULL, `status` varchar(2) DEFAULT NULL, `message` varchar(4500) DEFAULT NULL, `responseTime` bigint DEFAULT NULL, PRIMARY KEY (`id`) )" + #createScenarioRecordTable = "CREATE TABLE IF NOT EXISTS `ScenarioRecords` (`id` int(11) NOT NULL AUTO_INCREMENT, `runId` int DEFAULT NULL, `scenarioName` varchar(45) DEFAULT NULL, `userId` VARCHAR(30) NULL, `event` varchar(50) DEFAULT NULL, `startDate` bigint DEFAULT NULL, `endDate` bigint DEFAULT NULL, PRIMARY KEY (`id`) )" + #createGroupRecordTable = "CREATE TABLE IF NOT EXISTS `GroupRecords` (`id` int(11) NOT NULL AUTO_INCREMENT, `runId` int DEFAULT NULL, `scenarioName` varchar(45) DEFAULT NULL, `userId` VARCHAR(30) NULL, `entryDate` bigint DEFAULT NULL, `exitDate` bigint DEFAULT NULL, `status` varchar(2) DEFAULT NULL, PRIMARY KEY (`id`) )" + } + insert { + #insertRunRecord = "INSERT INTO RunRecords (runDate, simulationId, runDescription) VALUES (?,?,?)" + #insertRequestRecord = "INSERT INTO RequestRecords (runId, scenario, userId, name, requestStartDate, requestEndDate, responseStartDate, responseEndDate, status, message, responseTime) VALUES (?,?,?,?,?,?,?,?,?,?,?)" + #insertScenarioRecord = "INSERT INTO ScenarioRecords (runId, scenarioName, userId, event, startDate, endDate) VALUES (?,?,?,?,?,?)" + #insertGroupRecord = "INSERT INTO GroupRecords (runId, scenarioName, userId, entryDate, exitDate, status) VALUES (?,?,?,?,?,?)" + } + } + graphite { + #light = false # only send the all* stats + #host = "localhost" # The host where the Carbon server is located + #port = 2003 # The port to which the Carbon server listens to + #protocol = "tcp" # The protocol used to send data to Carbon (currently supported : "tcp", "udp") + #rootPathPrefix = "gatling" # The common prefix of all metrics sent to Graphite + #bufferSize = 8192 # GraphiteDataWriter's internal data buffer size, in bytes + #writeInterval = 1 # GraphiteDataWriter's write interval, in seconds + } + } +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/gatling/package.mustache b/modules/swagger-codegen/src/main/resources/pkmst/gatling/package.mustache new file mode 100644 index 00000000000..e69de29bb2d diff --git a/modules/swagger-codegen/src/main/resources/pkmst/gatling/testapi.mustache b/modules/swagger-codegen/src/main/resources/pkmst/gatling/testapi.mustache new file mode 100644 index 00000000000..ef5163aa929 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/gatling/testapi.mustache @@ -0,0 +1,41 @@ +# Sample gatling test for Get Product. Please implement likewise for your API. +import scala.concurrent.duration._ + +import io.gatling.core.Predef._ +import io.gatling.http.Predef._ +import io.gatling.jdbc.Predef._ +import com.typesafe.config._ +import org.springframework.boot.SpringApplication +import org.springframework.context.ConfigurableApplicationContext + + +class get{{path}} extends Simulation { + + + val app: ConfigurableApplicationContext = SpringApplication.run(classOf[{{basePackage}}.{{serviceName}}Application]) + Runtime.getRuntime.addShutdownHook(new Thread() { + override def run(): Unit = app.stop() + }) + + val conf = ConfigFactory.load() + val baseUrl = conf.getString("url") + val noOfUsers: Int = conf.getInt("noOfUsers") + val httpProtocol = http + .baseURL(baseUrl) + .inferHtmlResources() + .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8") + .acceptEncodingHeader("gzip, deflate, sdch") + .acceptLanguageHeader("en-US,en;q=0.8") + .userAgentHeader("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36") + + val headers_0 = Map( + "Cache-Control" -> "max-age=0", + "Upgrade-Insecure-Requests" -> "1") + + val scn = scenario("getProduct") + .exec(http("request_0") + .get("/{{{path}}}") + .headers(headers_0)) + + setUp(scn.inject(atOnceUsers(noOfUsers))).protocols(httpProtocol) +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/generatedAnnotation.mustache b/modules/swagger-codegen/src/main/resources/pkmst/generatedAnnotation.mustache new file mode 100644 index 00000000000..ad17a426e96 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/generatedAnnotation.mustache @@ -0,0 +1,3 @@ +{{^hideGenerationTimestamp}} +@javax.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}") +{{/hideGenerationTimestamp}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/headerParams.mustache b/modules/swagger-codegen/src/main/resources/pkmst/headerParams.mustache new file mode 100644 index 00000000000..89645c9436a --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/headerParams.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}@ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}}{{#allowableValues}}, allowableValues="{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @RequestHeader(value="{{baseName}}", required={{#required}}true{{/required}}{{^required}}false{{/required}}) {{>optionalDataType}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/implicitHeader.mustache b/modules/swagger-codegen/src/main/resources/pkmst/implicitHeader.mustache new file mode 100644 index 00000000000..64d7af20808 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/implicitHeader.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}@ApiImplicitParam(name = "{{{paramName}}}", value = "{{{description}}}", {{#required}}required=true,{{/required}} dataType = "{{{dataType}}}", paramType = "header"){{#hasMore}},{{/hasMore}}{{/isHeaderParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/integration/integrationtest.mustache b/modules/swagger-codegen/src/main/resources/pkmst/integration/integrationtest.mustache new file mode 100644 index 00000000000..45ebd423d60 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/integration/integrationtest.mustache @@ -0,0 +1,34 @@ +package {{basePackage}}.controller; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; +import {{basePackage}}.{{serviceName}}Application; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {{serviceName}}Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class {{serviceName}}IT { + + @LocalServerPort + private int port; + + TestRestTemplate restTemplate = new TestRestTemplate(); + + HttpHeaders headers = new HttpHeaders(); + + @Test + public void testYourMethod() { + + //add your logic + } + + private String createURLWithPort(String uri) { + return "http://localhost:" + port + uri; + } +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/licenseInfo.mustache b/modules/swagger-codegen/src/main/resources/pkmst/licenseInfo.mustache new file mode 100644 index 00000000000..94c36dda3af --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/licenseInfo.mustache @@ -0,0 +1,11 @@ +/* + * {{{appName}}} + * {{{appDescription}}} + * + * {{#version}}OpenAPI spec version: {{{version}}}{{/version}} + * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ diff --git a/modules/swagger-codegen/src/main/resources/pkmst/logging/httpLoggingFilter.mustache b/modules/swagger-codegen/src/main/resources/pkmst/logging/httpLoggingFilter.mustache new file mode 100644 index 00000000000..de21a130b46 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/logging/httpLoggingFilter.mustache @@ -0,0 +1,438 @@ +package {{basePackage}}.logging; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ReadListener; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.WriteListener; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; +import java.util.Arrays; +import org.apache.commons.io.output.TeeOutputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +/** + * Implements javax.servlet.Filter and dump the request/response to syslog + * @author pkmst + * + */ + +@Component +public class HttpLoggingFilter implements Filter { + + private static final Logger log = LoggerFactory.getLogger(HttpLoggingFilter.class); + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException { + try { + HttpServletRequest httpServletRequest = (HttpServletRequest) request; + HttpServletResponse httpServletResponse = (HttpServletResponse) response; + Map requestMap = this.getTypesafeRequestMap(httpServletRequest); + BufferedRequestWrapper bufferedRequest = new BufferedRequestWrapper(httpServletRequest); + BufferedResponseWrapper bufferedResponse = new BufferedResponseWrapper(httpServletResponse); + final StringBuilder logMessage = new StringBuilder( + "REST Request - ").append("[HTTP METHOD:") + .append(httpServletRequest.getMethod()) + .append("] [PATH INFO:") + .append(httpServletRequest.getServletPath()) + .append("] [REQUEST PARAMETERS:").append(requestMap) + .append("] [REQUEST BODY:") + .append(bufferedRequest.getRequestBody()) + .append("] [REMOTE ADDRESS:") + .append(httpServletRequest.getRemoteAddr()).append("]"); + long start = System.currentTimeMillis(); + chain.doFilter(bufferedRequest, bufferedResponse); + long elapsedTime = System.currentTimeMillis() - start; + String respContent = null; + if (bufferedResponse.getContent() == null || bufferedResponse.getContent() == "") { + respContent = "No data"; + } else { + respContent = bufferedResponse.getContent(); + } + logMessage.append(" [RESPONSE:").append(respContent) + .append("] [STATUS CODE:") + .append(bufferedResponse.getStatus()) + .append("] [Response Time(ms):").append(elapsedTime) + .append("]"); + String [] nonLoggingPaths = {"/v2/api-docs","/swagger-resources","/configuration/security","/swagger-ui.html","/webjars"}; + String urlPath = httpServletRequest.getRequestURL().toString(); + if (! ( Arrays.stream(nonLoggingPaths).parallel().anyMatch(urlPath::contains) )){ + log.info(logMessage.toString()); + } + } catch (Throwable a) { + log.error(a.getMessage()); + a.printStackTrace(); + } + } + + private Map getTypesafeRequestMap(HttpServletRequest request) { + Map typesafeRequestMap = new HashMap(); + Enumeration requestParamNames = request.getParameterNames(); + while (requestParamNames.hasMoreElements()) { + String requestParamName = (String) requestParamNames.nextElement(); + String requestParamValue; + if (requestParamName.equalsIgnoreCase("password")) { + requestParamValue = "********"; + } else { + requestParamValue = request.getParameter(requestParamName); + } + typesafeRequestMap.put(requestParamName, requestParamValue); + } + return typesafeRequestMap; + } + + @Override + public void destroy() { + } + + private static final class BufferedRequestWrapper extends HttpServletRequestWrapper { + + private ByteArrayInputStream bais = null; + private ByteArrayOutputStream baos = null; + private BufferedServletInputStream bsis = null; + private byte[] buffer = null; + + public BufferedRequestWrapper(HttpServletRequest req) throws IOException { + super(req); + // Read InputStream and store its content in a buffer. + InputStream is = req.getInputStream(); + this.baos = new ByteArrayOutputStream(); + byte buf[] = new byte[1024]; + int read; + while ((read = is.read(buf)) > 0) { + this.baos.write(buf, 0, read); + } + this.buffer = this.baos.toByteArray(); + } + + @Override + public ServletInputStream getInputStream() { + this.bais = new ByteArrayInputStream(this.buffer); + this.bsis = new BufferedServletInputStream(this.bais); + return this.bsis; + } + + String getRequestBody() throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(this.getInputStream())); + String line = null; + StringBuilder inputBuffer = new StringBuilder(); + do { + line = reader.readLine(); + if (null != line) { + inputBuffer.append(line.trim()); + } + } while (line != null); + reader.close(); + return inputBuffer.toString().trim(); + } + + } + + private static final class BufferedServletInputStream extends ServletInputStream { + + private ByteArrayInputStream bais; + + public BufferedServletInputStream(ByteArrayInputStream bais) { + this.bais = bais; + } + + @Override + public int available() { + return this.bais.available(); + } + + @Override + public int read() { + return this.bais.read(); + } + + @Override + public int read(byte[] buf, int off, int len) { + return this.bais.read(buf, off, len); + } + + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + } + + public class TeeServletOutputStream extends ServletOutputStream { + + private final TeeOutputStream targetStream; + + public TeeServletOutputStream(OutputStream one, OutputStream two) { + targetStream = new TeeOutputStream(one, two); + } + + @Override + public void write(int arg0) throws IOException { + this.targetStream.write(arg0); + } + + public void flush() throws IOException { + super.flush(); + this.targetStream.flush(); + } + + public void close() throws IOException { + super.close(); + this.targetStream.close(); + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setWriteListener(WriteListener writeListener) { + + } + } + + public class BufferedResponseWrapper implements HttpServletResponse { + + HttpServletResponse original; + TeeServletOutputStream tee; + ByteArrayOutputStream bos; + + public BufferedResponseWrapper(HttpServletResponse response) { + original = response; + } + + public String getContent() { + if (bos == null) { + return null; + } else + return bos.toString(); + } + + public PrintWriter getWriter() throws IOException { + return original.getWriter(); + } + + public ServletOutputStream getOutputStream() throws IOException { + if (tee == null) { + bos = new ByteArrayOutputStream(); + tee = new TeeServletOutputStream(original.getOutputStream(),bos); + } + return tee; + + } + + @Override + public String getCharacterEncoding() { + return original.getCharacterEncoding(); + } + + @Override + public String getContentType() { + return original.getContentType(); + } + + @Override + public void setCharacterEncoding(String charset) { + original.setCharacterEncoding(charset); + } + + @Override + public void setContentLength(int len) { + original.setContentLength(len); + } + + @Override + public void setContentLengthLong(long l) { + original.setContentLengthLong(l); + } + + @Override + public void setContentType(String type) { + original.setContentType(type); + } + + @Override + public void setBufferSize(int size) { + original.setBufferSize(size); + } + + @Override + public int getBufferSize() { + return original.getBufferSize(); + } + + @Override + public void flushBuffer() throws IOException { + tee.flush(); + } + + @Override + public void resetBuffer() { + original.resetBuffer(); + } + + @Override + public boolean isCommitted() { + return original.isCommitted(); + } + + @Override + public void reset() { + original.reset(); + } + + @Override + public void setLocale(Locale loc) { + original.setLocale(loc); + } + + @Override + public Locale getLocale() { + return original.getLocale(); + } + + @Override + public void addCookie(Cookie cookie) { + original.addCookie(cookie); + } + + @Override + public boolean containsHeader(String name) { + return original.containsHeader(name); + } + + @Override + public String encodeURL(String url) { + return original.encodeURL(url); + } + + @Override + public String encodeRedirectURL(String url) { + return original.encodeRedirectURL(url); + } + + @SuppressWarnings("deprecation") + @Override + public String encodeUrl(String url) { + return original.encodeUrl(url); + } + + @SuppressWarnings("deprecation") + @Override + public String encodeRedirectUrl(String url) { + return original.encodeRedirectUrl(url); + } + + @Override + public void sendError(int sc, String msg) throws IOException { + original.sendError(sc, msg); + } + + @Override + public void sendError(int sc) throws IOException { + original.sendError(sc); + } + + @Override + public void sendRedirect(String location) throws IOException { + original.sendRedirect(location); + } + + @Override + public void setDateHeader(String name, long date) { + original.setDateHeader(name, date); + } + + @Override + public void addDateHeader(String name, long date) { + original.addDateHeader(name, date); + } + + @Override + public void setHeader(String name, String value) { + original.setHeader(name, value); + } + + @Override + public void addHeader(String name, String value) { + original.addHeader(name, value); + } + + @Override + public void setIntHeader(String name, int value) { + original.setIntHeader(name, value); + } + + @Override + public void addIntHeader(String name, int value) { + original.addIntHeader(name, value); + } + + @Override + public void setStatus(int sc) { + original.setStatus(sc); + } + + @SuppressWarnings("deprecation") + @Override + public void setStatus(int sc, String sm) { + original.setStatus(sc, sm); + } + + @Override + public String getHeader(String arg0) { + return original.getHeader(arg0); + } + + @Override + public Collection getHeaderNames() { + return original.getHeaderNames(); + } + + @Override + public Collection getHeaders(String arg0) { + return original.getHeaders(arg0); + } + + @Override + public int getStatus() { + return original.getStatus(); + } + } +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/logstash.mustache b/modules/swagger-codegen/src/main/resources/pkmst/logstash.mustache new file mode 100644 index 00000000000..491be1e7f7c --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/logstash.mustache @@ -0,0 +1,35 @@ +input { + file { + path => "" + start_position => "beginning" + + } +} + + +filter { + # pattern matching logback pattern + grok { + + } + + +} + + + +} + +output { + # Print each event to stdout, useful for debugging. Should be commented out in production. + # Enabling 'rubydebug' codec on the stdout output will make logstash + # pretty-print the entire event as something similar to a JSON representation. + stdout { + codec => rubydebug + } + + # Sending properly parsed log events to elasticsearch + elasticsearch { + hosts => ["localhost:9200"] + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/manifest.mustache b/modules/swagger-codegen/src/main/resources/pkmst/manifest.mustache new file mode 100644 index 00000000000..2d27f25bace --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/manifest.mustache @@ -0,0 +1,12 @@ +applications: +- name: + memory: 1G + instances: 1 + host: + buildpack: https://github.com/cloudfoundry/java-buildpack.git + path: + services: + - + - + env: + \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/model.mustache b/modules/swagger-codegen/src/main/resources/pkmst/model.mustache new file mode 100644 index 00000000000..ef8b9e7422e --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/model.mustache @@ -0,0 +1,37 @@ +package {{package}}; + +import java.util.Objects; +{{#imports}}import {{import}}; +{{/imports}} +{{#serializableModel}} +import java.io.Serializable; +{{/serializableModel}} +{{#useBeanValidation}} +import org.springframework.validation.annotation.Validated; +import javax.validation.Valid; +import javax.validation.constraints.*; +{{/useBeanValidation}} +{{#jackson}} +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +{{/withXml}} +{{/jackson}} +{{#withXml}} +import javax.xml.bind.annotation.*; +{{/withXml}} +/** + * Response class to be returned by Api + * @author pkmst + * + */ +{{#models}} +{{#model}} +{{#isEnum}} +{{>enumOuterClass}} +{{/isEnum}} +{{^isEnum}} +{{>pojo}} +{{/isEnum}} +{{/model}} +{{/models}} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/notFoundException.mustache b/modules/swagger-codegen/src/main/resources/pkmst/notFoundException.mustache new file mode 100644 index 00000000000..40c25c5ea5c --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/notFoundException.mustache @@ -0,0 +1,10 @@ +package {{apiPackage}}; + +{{>generatedAnnotation}} +public class NotFoundException extends ApiException { + private int code; + public NotFoundException (int code, String msg) { + super(code, msg); + this.code = code; + } +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/optionalDataType.mustache b/modules/swagger-codegen/src/main/resources/pkmst/optionalDataType.mustache new file mode 100644 index 00000000000..976950e27e8 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/optionalDataType.mustache @@ -0,0 +1 @@ +{{#useOptional}}{{#required}}{{{dataType}}}{{/required}}{{^required}}Optional<{{{dataType}}}>{{/required}}{{/useOptional}}{{^useOptional}}{{{dataType}}}{{/useOptional}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/pathParams.mustache b/modules/swagger-codegen/src/main/resources/pkmst/pathParams.mustache new file mode 100644 index 00000000000..62342d01bfa --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/pathParams.mustache @@ -0,0 +1 @@ +{{#isPathParam}}{{#useBeanValidation}}{{>beanValidationPathParams}}{{/useBeanValidation}}@ApiParam(value = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}} {{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @PathVariable("{{baseName}}") {{>optionalDataType}} {{paramName}}{{/isPathParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/pojo.mustache b/modules/swagger-codegen/src/main/resources/pkmst/pojo.mustache new file mode 100644 index 00000000000..5830c643aeb --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/pojo.mustache @@ -0,0 +1,140 @@ +/** + * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} + */{{#description}} +@ApiModel(description = "{{{description}}}"){{/description}} +{{#useBeanValidation}}@Validated{{/useBeanValidation}} +{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} +public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {{#serializableModel}}implements Serializable{{/serializableModel}} { +{{#serializableModel}} + private static final long serialVersionUID = 1L; + +{{/serializableModel}} + {{#vars}} + {{#isEnum}} + {{^isContainer}} +{{>enumClass}} + {{/isContainer}} + {{/isEnum}} + {{#items.isEnum}} + {{#items}} + {{^isContainer}} +{{>enumClass}} + {{/isContainer}} + {{/items}} + {{/items.isEnum}} + {{#jackson}} + @JsonProperty("{{baseName}}"){{#withXml}} + @JacksonXmlProperty({{#isXmlAttribute}}isAttribute = true, {{/isXmlAttribute}}{{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}"){{/withXml}} + {{/jackson}} + {{#gson}} + @SerializedName("{{baseName}}") + {{/gson}} + {{#isContainer}} + {{#useBeanValidation}}@Valid{{/useBeanValidation}} + private {{{datatypeWithEnum}}} {{name}}{{#required}} = {{{defaultValue}}}{{/required}}{{^required}} = null{{/required}}; + {{/isContainer}} + {{^isContainer}} + private {{{datatypeWithEnum}}} {{name}} = {{{defaultValue}}}; + {{/isContainer}} + + {{/vars}} + {{#vars}} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + return this; + } + {{#isListContainer}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.add({{name}}Item); + return this; + } + {{/isListContainer}} + {{#isMapContainer}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.put(key, {{name}}Item); + return this; + } + {{/isMapContainer}} + + /** + {{#description}} + * {{{description}}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{minimum}} + {{/minimum}} + {{#maximum}} + * maximum: {{maximum}} + {{/maximum}} + * @return {{name}} + **/ + {{#vendorExtensions.extraAnnotation}} + {{{vendorExtensions.extraAnnotation}}} + {{/vendorExtensions.extraAnnotation}} + @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}") +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} public {{{datatypeWithEnum}}} {{getter}}() { + return {{name}}; + } + + public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + } + + {{/vars}} + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}Objects.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && + {{/hasMore}}{{/vars}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return true;{{/hasVars}} + } + + @Override + public int hashCode() { + return Objects.hash({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}}sb.append(" ").append(toIndentedString(super.toString())).append("\n");{{/parent}} + {{#vars}}sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}}sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/pom.mustache b/modules/swagger-codegen/src/main/resources/pkmst/pom.mustache new file mode 100644 index 00000000000..7af313005e9 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/pom.mustache @@ -0,0 +1,447 @@ + + + 4.0.0 + {{groupId}} + {{artifactId}} + {{artifactVersion}} + jar + {{artifactId}} + Demo project for Spring Boot Microservices + + UTF-8 + UTF-8 + 1.8 + 1.5.6.RELEASE + 1.2.5 + 1.2.5 + 3.10.0 + 2.6.1-SNAPSHOT + 2.6.0 + 1.7.25 + 4.11 + 1.2.3 + 1.2.3 + 2.3.0 + 2.2.4 + 3.2.2 + Camden.SR7 + 1.1.3.RELEASE + + + org.springframework.boot + spring-boot-starter-parent + 1.5.6.RELEASE + + + + + + oss-snapshots + JFrog OSS Snapshots + https://oss.jfrog.org/simple/oss-snapshot-local/ + + true + + + + central + Maven Repository Switchboard + default + http://repo1.maven.org/maven2 + + false + + + + jitpack.io + https://jitpack.io + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.assertj + assertj-core + + {{#eurekaUri}} + + org.springframework.cloud + spring-cloud-starter-eureka + + + org.springframework.cloud + spring-cloud-starter-eureka-server + + {{/eurekaUri}} + + {{#zipkinUri}} + + org.springframework.cloud + spring-cloud-starter-zipkin + + {{/zipkinUri}} + + + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-jetty + + + + org.springframework.cloud + spring-cloud-starter-hystrix-dashboard + + + org.springframework + spring-jdbc + + {{#springBootAdminUri}} + + de.codecentric + spring-boot-admin-starter-client + 1.2.4 + + {{/springBootAdminUri}} + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + com.netflix.hystrix + hystrix-javanica + 1.4.1 + + + org.apache.commons + commons-lang3 + 3.6 + + + commons-logging + commons-logging + 1.2 + + {{#pkmstInterceptor}} + + + com.github.rkumar-pk + pkmst-extension + 1.0.1 + + {{/pkmstInterceptor}} + + + info.cukes + cucumber-junit + ${cucumber-junit.version} + + + info.cukes + cucumber-java + ${cucumber-java.version} + + + info.cukes + cucumber-spring + ${cucumber-java.version} + + + net.masterthought + cucumber-reporting + ${cucumber-reporting.version} + + + com.github.tomakehurst + wiremock + 1.46 + test + + + io.springfox + springfox-swagger2 + ${springfox-swagger2} + + + io.springfox + springfox-swagger-ui + ${springfox-swagger-ui} + + + org.slf4j + slf4j-api + ${slf4j-api} + + + net.logstash.logback + logstash-logback-encoder + ${logstash-logback-encoder} + + + ch.qos.logback + logback-core + + + ch.qos.logback + logback-classic + + + org.springframework.boot + spring-boot-starter-remote-shell + + + org.jolokia + jolokia-core + + + + io.gatling.highcharts + gatling-charts-highcharts + ${gatling.version} + test + + + com.typesafe + config + 1.3.1 + + + com.jayway.restassured + rest-assured + 2.9.0 + + + org.springframework + spring-test + + + org.threeten + threetenbp + 1.3.6 + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + development + + true + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + + + **/*CucumberTest*.java + + **/cucumber/*.java + + + + + + net.alchim31.maven + scala-maven-plugin + ${scala-maven-plugin.version} + + + + + org.springframework.boot + spring-boot-maven-plugin + + ${project.name} + + + + org.jacoco + jacoco-maven-plugin + 0.7.7.201606060606 + + ${basedir}/target/coverage-reports/jacoco-unit.exec + ${basedir}/target/coverage-reports/jacoco-unit.exec + + + + jacoco-initialize + + prepare-agent + + + + jacoco-site + test + + report + + + + + + org.apache.maven.plugins + maven-site-plugin + 3.5.1 + + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.4 + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.17 + + + org.apache.maven.plugins + maven-surefire-report-plugin + 2.19.1 + + + org.apache.maven.plugins + maven-pmd-plugin + + + + + + + + + cucumber-tests + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + + none + + + + {{serverName}}Test.java + + + + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.springframework.cloud + spring-cloud-contract-maven-plugin + [1.0.1.RELEASE,) + + convert + generateTests + + + + + + + + + + + + + + diff --git a/modules/swagger-codegen/src/main/resources/pkmst/queryParams.mustache b/modules/swagger-codegen/src/main/resources/pkmst/queryParams.mustache new file mode 100644 index 00000000000..182152c6e5a --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/queryParams.mustache @@ -0,0 +1 @@ +{{#isQueryParam}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}@ApiParam(value = "{{{description}}}"{{#required}}, required = true{{/required}}{{#allowableValues}}, allowableValues = "{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/allowableValues}}{{#defaultValue}}, defaultValue = "{{{defaultValue}}}"{{/defaultValue}}) {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestParam(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) {{>optionalDataType}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache b/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache new file mode 100644 index 00000000000..38701b4e848 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache @@ -0,0 +1,155 @@ +Dear Reader : Thanks for selecting PKMST swagger code generation toolkit for starting your microservice journey. +We believe the hard work we put into this framework will help you kick start your journey sooner and you will find it +easy to scale your service to enterprise grade. Another great thing is you don't need to enable all capabilities as you start, +but can enable as your microservice capabilities needs to be extended to meet strict enterprise standards. + +PKMST feature set. +a)Read the Swagger supplied and will create a maven project +b)Create basic controller based on rest verb and path configured in swagger +c)generate default unit test cose using junit +d)generate all needed dependency needed to run the microservice on local +e)generate a default manifest file that allows you to push code to cloudfoundry instance ( eg pcf , ibm bluemix etc) + +As you mature your knowledge with pkmst, you can leverage vendor extensions feature that will allow you to supply specific configuration +in your swagger and generate respective configuration that will +f)Allow you integrate with registry server (Example Eureka) +g)Allow you to integrate with tracing server (Example Zipkin) +h)Allow you to capture log in your microservice and send to Log management server (Ex ELK or splunk) +i)Allow you to configure Oauth2 security based authorization for your microservice + + Additonal Features + j)generate sample cucumber file and dependency to drive your Behaviour driven development. + k)generate gatling based perfromance test , which can be excuted via build pipeline like jenkins etc. + + +Working: +Using swagger specification you can convert any definition to spring boot microservice. +It has the integration with the below services: +eureka registry, zipkin , spring boot admin, circuit breaker. + +By default only the circuit breaker annotation is enabled. But one has to write the fallback method. The needed dependency for it is also been enabled. To generate the integration and +related configuration for eureka, zipkin, spring boot admin one has two options: + +1) When generating from UI one has to provide vendor extensions inside the swagger specification as below: +swagger: "2.0" +info: + description: "This is a sample Product Catalogue Server.\ + \ For this sample, you can use the api key `special-key` to test the authorization\ + \ filters." + version: "1.0.0" + x-codegen: + eurekaUri: "http://localhost:8080" + zipkinUri: "http://localhost:9411" + springBootAdminUri: "http://localhost:8000" + pkmstInterceptor: "true" + +PLease note the vendor extensions are inside the info tag of the swagger specification. All the tags are case sensitive. Once given all the related configuration and the dependency +will be enabled. + +2) When generating from the maven plugin one has to provide configuration inside pom as below: +inside the swagger codegen maven plugin under the configuration section + + + product-swagger.yaml + pkmst + ${project.build.directory}/generated-sources + + com.prokarma + product-catalogue + 1.0 + com.prokarma.pkmst + ProductCatalogue + + http://localhost:9411 + http://localhost:4588 + true + + + + The project has three profiles local, dev, dev-config which can be configured accordingly. Once you have provided the uris you can see the necessary configurations generated inside the local and the dev + yml files. dev-config is for the config server if you want to use.(also enable the dependency for the config server inside the pom) + + [Note: one has to run the zipkin, eureka, spring boot admin servers to be able to connect from the app. This project assumes that you have all the servers + up and running.] + + Also provided are the middleware handlers: + +1) traceInterceptor:is an id passed in from client and will be unique with an application context. The id will be passed into the backend and return to the consumer for transaction tracing. + +2) correlationInterceptor:generates a UUID in the first API/service and pass it to all other APIs/services in the call tree for tracking purpose. + +3) rateLimitInterceptor:is a rate limiting handler to limit number of concurrent requests on the server. Once the limit is reached, subsequent requests will be queued for later execution. The size of the queue is configurable. + +4) auditInterceptor: audit logs most important info about request and response into audit.log in JSON format with config file that controls which fields to be logged + +5) bodyInterceptor:s a body parser middleware that is responsible for parsing the content of the request based on Content-Type in the request header. + +To be able to generate the handlers and the necessary configurations one has to provide the pkmstInterceptor key inside the vendor extensions or through +the maven plugin. +Once provided all the handlers are registered in the interceptor registry and can be enabled or disabled through the configuration provided inside +the application yml as below: +interceptor: + enable: + audit: true + body: true + rateLimit: true + traceability: true + correlation: true + +For testing we have placeholders for junit test class, integration test class, cucumber sample +feature file(implement according to your needs), gatling load test. + +Logstash: Logstash is a tool to collect, process, and forward events and log messages.Sample Logstash configuration file provided that developer can configure to collect wide variety of data.Logstash can dynamically unify data from disparate sources and normalize the data into destinations of their choice. + +Ways to run the project: +1) Normal spring boot application + +2) Using Dockerfile to run in the container: +dockerfile will be generated inside the project by default. Image can be created using docker cli or through the maven plugin + + + + ... + + com.spotify + docker-maven-plugin + VERSION GOES HERE + + example + docker + + + / + ${project.build.directory} + ${project.build.finalName}.jar + + + + + ... + + + +Use manifest.yml file to push the application to the cloud. + +HttpLogging filter is provided for logging in the request and response. Can be found inside the com.prokarma.pkmst.logging package. +Spring security is also provided to secure the resources. Please modify according to your needs. + +First run: +Import the project in to the eclipse. Run the app as an spring boot application.The project will run on http://localhost:8008 +Swagger ui available on: +http://localhost:8008/swagger-ui.html +If all the configurations have been enabled(depending on the port) below are some of the URls to access: +eureka: http://localhost:8080 +zipkin: http://localhost:9411 + +Please visit below links for more information on PKMST: + +Getting started +https://pkmst-getting-started.mybluemix.net + +Pkmst examples +https://github.com/ProKarma-Inc/pkmst-getting-started-examples + +Pkmst Extensions +https://github.com/ProKarma-Inc/pkmst-extention \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/resources/application-dev-config.mustache b/modules/swagger-codegen/src/main/resources/pkmst/resources/application-dev-config.mustache new file mode 100644 index 00000000000..79292387bb5 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/resources/application-dev-config.mustache @@ -0,0 +1,7 @@ +#Enable cloud config. Also enable the dependency in pom + #cloud: + #config: + #uri: {{configUri}} + #fail-fast: true + #password: user + #username: user \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/resources/application-dev.mustache b/modules/swagger-codegen/src/main/resources/pkmst/resources/application-dev.mustache new file mode 100644 index 00000000000..a8ad3b2a0a7 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/resources/application-dev.mustache @@ -0,0 +1,78 @@ +# Discovery Server Access +{{#eurekaUri}} +eureka: + instance: + leaseRenewalIntervalInSeconds: 1 + leaseExpirationDurationInSeconds: 2 + hostname: localhost + healthCheckUrl: http://localhost:{{serverPort}}/health + nonSecurePort: 80 + client: + enabled: true + healthcheck: + enabled: true + registerWithEureka: true + #fetchRegistry: true + serviceUrl: + defaultZone: {{eurekaUri}}/eureka/ +{{/eurekaUri}} +server: + port: {{serverPort}} + +# Spring Actuator +management: + health: + redis: + enabled: false + security: + enabled: false + + +endpoints: + health: + sensitive: false + +info: + app: + name: {{serviceName}} + description: Microservice developed by PKMST + version: {{artifactVersion}} + +health: + hystrix: + enabled: true + +security: + basic: + enabled: false +# provide rabbitmq configuration +spring: + rabbitmq: + host: + virtual-host: + username: + password: + port: + {{#zipkinUri}} + zipkin: + base-url: {{zipkinUri}} + {{/zipkinUri}} + + {{#springBootAdminUri}} + boot: + admin: + url: {{springBootAdminUri}} + client: + health-url: http://localhost:{{serverPort}}/health + management-url: http://localhost:{{serverPort}} + service-url: http://localhost:{{serverPort}} + {{/springBootAdminUri}} + sleuth: + sampler: + percentage: 1.0 +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/resources/application-local.mustache b/modules/swagger-codegen/src/main/resources/pkmst/resources/application-local.mustache new file mode 100644 index 00000000000..b8025d85db2 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/resources/application-local.mustache @@ -0,0 +1,87 @@ +# Discovery Server Access +{{#eurekaUri}} +eureka: + instance: + leaseRenewalIntervalInSeconds: 1 + leaseExpirationDurationInSeconds: 2 + hostname: localhost + healthCheckUrl: http://localhost:{{serverPort}}/health + nonSecurePort: 80 + client: + enabled: true + healthcheck: + enabled: true + registerWithEureka: true + #fetchRegistry: true + serviceUrl: + defaultZone: {{eurekaUri}}/eureka/ +{{/eurekaUri}} +server: + port: {{serverPort}} + +# Spring Actuator +management: + health: + redis: + enabled: false + security: + enabled: false + + +endpoints: + health: + sensitive: false + +info: + app: + name: {{serviceName}} + description: Microservice developed by PKMST + version: {{artifactVersion}} + +health: + hystrix: + enabled: true + +security: + basic: + enabled: false +# provide rabbitmq configuration +spring: + rabbitmq: + host: + virtual-host: + username: + password: + port: + {{#zipkinUri}} + zipkin: + base-url: {{zipkinUri}} + {{/zipkinUri}} + + {{#springBootAdminUri}} + boot: + admin: + url: {{springBootAdminUri}} + client: + health-url: http://localhost:{{serverPort}}/health + management-url: http://localhost:{{serverPort}} + service-url: http://localhost:{{serverPort}} + {{/springBootAdminUri}} + sleuth: + sampler: + percentage: 1.0 +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG +{{#pkmstInterceptor}} +interceptor: + enable: + audit: true + body: true + rateLimit: true + traceability: true + correlation: true +{{/pkmstInterceptor}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/resources/application.mustache b/modules/swagger-codegen/src/main/resources/pkmst/resources/application.mustache new file mode 100644 index 00000000000..e686a5a0c33 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/resources/application.mustache @@ -0,0 +1,5 @@ +springfox.documentation.swagger.v2.path=/api-docs +server.contextPath={{^contextPath}}/{{/contextPath}}{{#contextPath}}{{contextPath}}{{/contextPath}} +server.port={{serverPort}} +spring.jackson.date-format={{basePackage}}.RFC3339DateFormat +spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/resources/bootstrap.mustache b/modules/swagger-codegen/src/main/resources/pkmst/resources/bootstrap.mustache new file mode 100644 index 00000000000..2f125971180 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/resources/bootstrap.mustache @@ -0,0 +1,5 @@ +spring: + application: + name: {{artifactId}} + profiles: + active: local \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/returnTypes.mustache b/modules/swagger-codegen/src/main/resources/pkmst/returnTypes.mustache new file mode 100644 index 00000000000..c8f7a56938a --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/returnTypes.mustache @@ -0,0 +1 @@ +{{#returnContainer}}{{#isMapContainer}}Map{{/isMapContainer}}{{#isListContainer}}List<{{{returnType}}}>{{/isListContainer}}{{/returnContainer}}{{^returnContainer}}{{{returnType}}}{{/returnContainer}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/security/authorizationServerConfiguration.mustache b/modules/swagger-codegen/src/main/resources/pkmst/security/authorizationServerConfiguration.mustache new file mode 100644 index 00000000000..8db45c3b578 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/security/authorizationServerConfiguration.mustache @@ -0,0 +1,61 @@ +package {{basePackage}}.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; +import org.springframework.security.oauth2.provider.token.TokenStore; +/** + * Convenient strategy for configuring an OAUth2 Authorization Server. Beans of this type are applied to the Spring + * context automatically if you {@link EnableAuthorizationServer @EnableAuthorizationServer}. + * + * @author pkmst + * + */ +@Configuration +@EnableAuthorizationServer +public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { + + private static String REALM="MY_OAUTH_REALM"; + + @Autowired + private TokenStore tokenStore; + + @Autowired + private UserApprovalHandler userApprovalHandler; + + @Autowired + @Qualifier("authenticationManagerBean") + private AuthenticationManager authenticationManager; + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .secret("secret") + .accessTokenValiditySeconds(120).//Access token is only valid for 2 minutes. + refreshTokenValiditySeconds(600);//Refresh token is only valid for 10 minutes. + } + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler) + .authenticationManager(authenticationManager); + } + + @Override + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { + oauthServer.realm(REALM+"/client"); + } + +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/security/oAuth2SecurityConfiguration.mustache b/modules/swagger-codegen/src/main/resources/pkmst/security/oAuth2SecurityConfiguration.mustache new file mode 100644 index 00000000000..a84cd0ba579 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/security/oAuth2SecurityConfiguration.mustache @@ -0,0 +1,82 @@ +package {{basePackage}}.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.security.SecurityProperties; +import org.springframework.core.annotation.Order; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.approval.ApprovalStore; +import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; +import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; +/** + * Provides a convenient base class for creating a {@link WebSecurityConfigurer} + * instance. The implementation allows customization by overriding methods. + * + * @see EnableWebSecurity + * + * @author pkmst + */ +@Configuration +@EnableWebSecurity +@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) +public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Autowired + private ClientDetailsService clientDetailsService; + + @Autowired + public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication() + .withUser("admin").password("admin@123").roles("ADMIN").and() + .withUser("user").password("user@123").roles("USER"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .csrf().disable() + .anonymous().disable() + .authorizeRequests() + .antMatchers("/oauth/token").permitAll(); + } + + @Override + @Bean + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + + @Bean + public TokenStore tokenStore() { + return new InMemoryTokenStore(); + } + + @Bean + @Autowired + public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){ + TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler(); + handler.setTokenStore(tokenStore); + handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService)); + handler.setClientDetailsService(clientDetailsService); + return handler; + } + + @Bean + @Autowired + public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception { + TokenApprovalStore store = new TokenApprovalStore(); + store.setTokenStore(tokenStore); + return store; + } + +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/security/resourceServerConfiguration.mustache b/modules/swagger-codegen/src/main/resources/pkmst/security/resourceServerConfiguration.mustache new file mode 100644 index 00000000000..654fa148910 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/security/resourceServerConfiguration.mustache @@ -0,0 +1,42 @@ +package {{basePackage}}.security; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; +import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; +import org.springframework.http.HttpMethod; +/** + * Configurer class for @EnableResourceServer classes. This class adjust the access + * rules and paths that are protected by OAuth2 security. If more than one configures the same property, then the last + * one wins. The configurers are sorted by {@link Order} before being applied. + * + * @author pkmst + * + */ +@Configuration +@EnableResourceServer +public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { + + private static final String RESOURCE_ID = "my_rest_api"; + + @Override + public void configure(ResourceServerSecurityConfigurer resources) { + resources.resourceId(RESOURCE_ID).stateless(false); + } + + @Override + public void configure(HttpSecurity http) throws Exception { + //configure security for the http methods + {{#resourcePaths}} + http. + anonymous().disable() + .requestMatchers().antMatchers(HttpMethod.GET, "/{{path}}/**") + .and().authorizeRequests() + .antMatchers(HttpMethod.GET, "/{{path}}/**").access("hasRole('ADMIN')") + .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); + {{/resourcePaths}} + } + +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/testresources/application-test.mustache b/modules/swagger-codegen/src/main/resources/pkmst/testresources/application-test.mustache new file mode 100644 index 00000000000..5b21a67c370 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/testresources/application-test.mustache @@ -0,0 +1,4 @@ +server.port = 8081 +{{#eurekaUri}} +eureka.client.enabled=false +{{/eurekaUri}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/testresources/application.mustache b/modules/swagger-codegen/src/main/resources/pkmst/testresources/application.mustache new file mode 100644 index 00000000000..5b21a67c370 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/testresources/application.mustache @@ -0,0 +1,4 @@ +server.port = 8081 +{{#eurekaUri}} +eureka.client.enabled=false +{{/eurekaUri}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/testresources/bootstrap.mustache b/modules/swagger-codegen/src/main/resources/pkmst/testresources/bootstrap.mustache new file mode 100644 index 00000000000..abde2ab27c5 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/testresources/bootstrap.mustache @@ -0,0 +1,5 @@ +spring: + application: + name: {{artifactId}} + profiles: + active: test \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/typeInfoAnnotation.mustache b/modules/swagger-codegen/src/main/resources/pkmst/typeInfoAnnotation.mustache new file mode 100644 index 00000000000..2d7983d0101 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/typeInfoAnnotation.mustache @@ -0,0 +1,7 @@ +{{#jackson}} +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{discriminator}}", visible = true ) +@JsonSubTypes({ + {{#children}} + @JsonSubTypes.Type(value = {{classname}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"), + {{/children}} +}){{/jackson}} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/xmlAnnotation.mustache b/modules/swagger-codegen/src/main/resources/pkmst/xmlAnnotation.mustache new file mode 100644 index 00000000000..fd81a4cf5d8 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/xmlAnnotation.mustache @@ -0,0 +1,6 @@ +{{#withXml}} +{{#jackson}} +@JacksonXmlRootElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}") +{{/jackson}} +@XmlRootElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}") +@XmlAccessorType(XmlAccessType.FIELD){{/withXml}} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 06e025965be..81cb656cfa9 100644 --- a/pom.xml +++ b/pom.xml @@ -838,7 +838,7 @@ - + samples/client/petstore/php/SwaggerClient-php samples/client/petstore/ruby samples/client/petstore/scala diff --git a/pom.xml.circleci b/pom.xml.circleci index ef26365ef55..38736dbb1c9 100644 --- a/pom.xml.circleci +++ b/pom.xml.circleci @@ -844,6 +844,7 @@ samples/client/petstore/ruby samples/server/petstore/java-inflector + samples/server/petstore/java-pkmst samples/server/petstore/java-play-framework samples/server/petstore/undertow samples/server/petstore/jaxrs/jersey1 diff --git a/samples/server/petstore/java-pkmst/.swagger-codegen-ignore b/samples/server/petstore/java-pkmst/.swagger-codegen-ignore new file mode 100644 index 00000000000..c5fa491b4c5 --- /dev/null +++ b/samples/server/petstore/java-pkmst/.swagger-codegen-ignore @@ -0,0 +1,23 @@ +# Swagger Codegen Ignore +# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/server/petstore/java-pkmst/.swagger-codegen/VERSION b/samples/server/petstore/java-pkmst/.swagger-codegen/VERSION new file mode 100644 index 00000000000..f9f7450d135 --- /dev/null +++ b/samples/server/petstore/java-pkmst/.swagger-codegen/VERSION @@ -0,0 +1 @@ +2.3.0-SNAPSHOT \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/Dockerfile b/samples/server/petstore/java-pkmst/Dockerfile new file mode 100644 index 00000000000..57da37138f2 --- /dev/null +++ b/samples/server/petstore/java-pkmst/Dockerfile @@ -0,0 +1,3 @@ +FROM frolvlad/alpine-oraclejdk8:slim +COPY target/pkmst-microservice.jar app.jar +ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/Readme.md b/samples/server/petstore/java-pkmst/Readme.md new file mode 100644 index 00000000000..27d8199c6f7 --- /dev/null +++ b/samples/server/petstore/java-pkmst/Readme.md @@ -0,0 +1,142 @@ +Dear Reader : Thanks for selecting PKMST swagger code generation toolkit for starting your microservice journey. +We believe the hard work we put into this framework will help you kick start your journey sooner and you will find it +easy to scale your service to enterprise grade. Another great thing is you don't need to enable all capabilities as you start, +but can enable as your microservice capabilities needs to be extended to meet strict enterprise standards. + +PKMST feature set. +a)Read the Swagger supplied and will create a maven project +b)Create basic controller based on rest verb and path configured in swagger +c)generate default unit test cose using junit +d)generate all needed dependency needed to run the microservice on local +e)generate a default manifest file that allows you to push code to cloudfoundry instance ( eg pcf , ibm bluemix etc) + +As you mature your knowledge with pkmst, you can leverage vendor extensions feature that will allow you to supply specific configuration +in your swagger and generate respective configuration that will +f)Allow you integrate with registry server (Example Eureka) +g)Allow you to integrate with tracing server (Example Zipkin) +h)Allow you to capture log in your microservice and send to Log management server (Ex ELK or splunk) +i)Allow you to configure Oauth2 security based authorization for your microservice + + Additonal Features + j)generate sample cucumber file and dependency to drive your Behaviour driven development. + k)generate gatling based perfromance test , which can be excuted via build pipeline like jenkins etc. + + +Working: +Using swagger specification you can convert any definition to spring boot microservice. +It has the integration with the below services: +eureka registry, zipkin , spring boot admin, circuit breaker. + +By default only the circuit breaker annotation is enabled. But one has to write the fallback method. The needed dependency for it is also been enabled. To generate the integration and +related configuration for eureka, zipkin, spring boot admin one has two options: + +1) When generating from UI one has to provide vendor extensions inside the swagger specification as below: +swagger: "2.0" +info: + description: "This is a sample Product Catalogue Server.\ + \ For this sample, you can use the api key `special-key` to test the authorization\ + \ filters." + version: "1.0.0" + x-codegen: + eurekaUri: "http://localhost:8080" + zipkinUri: "http://localhost:9411" + springBootAdminUri: "http://localhost:8000" + pkmstInterceptor: "true" + +PLease note the vendor extensions are inside the info tag of the swagger specification. All the tags are case sensitive. Once given all the related configuration and the dependency +will be enabled. + +2) When generating from the maven plugin one has to provide configuration inside pom as below: +inside the swagger codegen maven plugin under the configuration section + + + product-swagger.yaml + pkmst + ${project.build.directory}/generated-sources + + com.prokarma + product-catalogue + 1.0 + com.prokarma.pkmst + ProductCatalogue + + http://localhost:9411 + http://localhost:4588 + true + + + + The project has three profiles local, dev, dev-config which can be configured accordingly. Once you have provided the uris you can see the necessary configurations generated inside the local and the dev + yml files. dev-config is for the config server if you want to use.(also enable the dependency for the config server inside the pom) + + [Note: one has to run the zipkin, eureka, spring boot admin servers to be able to connect from the app. This project assumes that you have all the servers + up and running.] + + Also provided are the middleware handlers: + +1) traceInterceptor:is an id passed in from client and will be unique with an application context. The id will be passed into the backend and return to the consumer for transaction tracing. + +2) correlationInterceptor:generates a UUID in the first API/service and pass it to all other APIs/services in the call tree for tracking purpose. + +3) rateLimitInterceptor:is a rate limiting handler to limit number of concurrent requests on the server. Once the limit is reached, subsequent requests will be queued for later execution. The size of the queue is configurable. + +4) auditInterceptor: audit logs most important info about request and response into audit.log in JSON format with config file that controls which fields to be logged + +5) bodyInterceptor:s a body parser middleware that is responsible for parsing the content of the request based on Content-Type in the request header. + +To be able to generate the handlers and the necessary configurations one has to provide the pkmstInterceptor key inside the vendor extensions or through +the maven plugin. +Once provided all the handlers are registered in the interceptor registry and can be enabled or disabled through the configuration provided inside +the application yml as below: +interceptor: + enable: + audit: true + body: true + rateLimit: true + traceability: true + correlation: true + +For testing we have placeholders for junit test class, integration test class, cucumber sample +feature file(implement according to your needs), gatling load test. + +Ways to run the project: +1) Normal spring boot application + +2) Using Dockerfile to run in the container: +dockerfile will be generated inside the project by default. Image can be created using docker cli or through the maven plugin + + + + ... + + com.spotify + docker-maven-plugin + VERSION GOES HERE + + example + docker + + + / + ${project.build.directory} + ${project.build.finalName}.jar + + + + + ... + + + +Use manifest.yml file to push the application to the cloud. + +HttpLogging filter is provided for logging in the request and response. Can be found inside the com.prokarma.pkmst.logging package. +Spring security is also provided to secure the resources. Please modify according to your needs. + +First run: +Import the project in to the eclipse. Run the app as an spring boot application.The project will run on http://localhost:8008 +Swagger ui available on: +http://localhost:8008/swagger-ui.html +If all the configurations have been enabled(depending on the port) below are some of the URls to access: +eureka: http://localhost:8080 +zipkin: http://localhost:9411 diff --git a/samples/server/petstore/java-pkmst/logstash.conf b/samples/server/petstore/java-pkmst/logstash.conf new file mode 100644 index 00000000000..491be1e7f7c --- /dev/null +++ b/samples/server/petstore/java-pkmst/logstash.conf @@ -0,0 +1,35 @@ +input { + file { + path => "" + start_position => "beginning" + + } +} + + +filter { + # pattern matching logback pattern + grok { + + } + + +} + + + +} + +output { + # Print each event to stdout, useful for debugging. Should be commented out in production. + # Enabling 'rubydebug' codec on the stdout output will make logstash + # pretty-print the entire event as something similar to a JSON representation. + stdout { + codec => rubydebug + } + + # Sending properly parsed log events to elasticsearch + elasticsearch { + hosts => ["localhost:9200"] + } +} \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/manifest.yml b/samples/server/petstore/java-pkmst/manifest.yml new file mode 100644 index 00000000000..2d27f25bace --- /dev/null +++ b/samples/server/petstore/java-pkmst/manifest.yml @@ -0,0 +1,12 @@ +applications: +- name: + memory: 1G + instances: 1 + host: + buildpack: https://github.com/cloudfoundry/java-buildpack.git + path: + services: + - + - + env: + \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/pom.xml b/samples/server/petstore/java-pkmst/pom.xml new file mode 100644 index 00000000000..bdd77043a36 --- /dev/null +++ b/samples/server/petstore/java-pkmst/pom.xml @@ -0,0 +1,416 @@ + + + 4.0.0 + com.prokarma + pkmst-microservice + 1.0.0 + jar + pkmst-microservice + Demo project for Spring Boot Microservices + + UTF-8 + UTF-8 + 1.8 + 1.5.6.RELEASE + 1.2.5 + 1.2.5 + 3.10.0 + 2.6.1-SNAPSHOT + 2.6.0 + 1.7.25 + 4.11 + 1.2.3 + 1.2.3 + 2.3.0 + 2.2.4 + 3.2.2 + Camden.SR7 + 1.1.3.RELEASE + + + org.springframework.boot + spring-boot-starter-parent + 1.5.6.RELEASE + + + + + + oss-snapshots + JFrog OSS Snapshots + https://oss.jfrog.org/simple/oss-snapshot-local/ + + true + + + + central + Maven Repository Switchboard + default + http://repo1.maven.org/maven2 + + false + + + + jitpack.io + https://jitpack.io + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.assertj + assertj-core + + + + + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-jetty + + + + org.springframework.cloud + spring-cloud-starter-hystrix-dashboard + + + org.springframework + spring-jdbc + + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + com.netflix.hystrix + hystrix-javanica + 1.4.1 + + + org.apache.commons + commons-lang3 + 3.4 + + + commons-logging + commons-logging + 1.2 + + + + info.cukes + cucumber-junit + ${cucumber-junit.version} + + + info.cukes + cucumber-java + ${cucumber-java.version} + + + info.cukes + cucumber-spring + ${cucumber-java.version} + + + net.masterthought + cucumber-reporting + ${cucumber-reporting.version} + + + com.github.tomakehurst + wiremock + 1.46 + test + + + io.springfox + springfox-swagger2 + ${springfox-swagger2} + + + io.springfox + springfox-swagger-ui + ${springfox-swagger-ui} + + + org.slf4j + slf4j-api + ${slf4j-api} + + + net.logstash.logback + logstash-logback-encoder + ${logstash-logback-encoder} + + + ch.qos.logback + logback-core + + + ch.qos.logback + logback-classic + + + org.springframework.boot + spring-boot-starter-remote-shell + + + org.jolokia + jolokia-core + + + + io.gatling.highcharts + gatling-charts-highcharts + ${gatling.version} + test + + + com.typesafe + config + 1.3.1 + + + com.jayway.restassured + rest-assured + 2.9.0 + + + org.springframework + spring-test + + + org.threeten + threetenbp + 1.3.6 + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + development + + true + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + + + **/*CucumberTest*.java + + **/cucumber/*.java + + + + + + net.alchim31.maven + scala-maven-plugin + ${scala-maven-plugin.version} + + + + + org.springframework.boot + spring-boot-maven-plugin + + ${project.name} + + + + org.jacoco + jacoco-maven-plugin + 0.7.7.201606060606 + + ${basedir}/target/coverage-reports/jacoco-unit.exec + ${basedir}/target/coverage-reports/jacoco-unit.exec + + + + jacoco-initialize + + prepare-agent + + + + jacoco-site + test + + report + + + + + + org.apache.maven.plugins + maven-site-plugin + 3.5.1 + + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.4 + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.17 + + + org.apache.maven.plugins + maven-surefire-report-plugin + 2.19.1 + + + org.apache.maven.plugins + maven-pmd-plugin + + + + + + + + + cucumber-tests + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + + none + + + + Test.java + + + + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.springframework.cloud + spring-cloud-contract-maven-plugin + [1.0.1.RELEASE,) + + convert + generateTests + + + + + + + + + + + + + + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/PkmstApplication.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/PkmstApplication.java new file mode 100644 index 00000000000..63d2fac6ec5 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/PkmstApplication.java @@ -0,0 +1,30 @@ +package com.prokarma.pkmst; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; +import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * starts the spring boot application + * @author pkmst + * + */ + +@SpringBootApplication +@EnableSwagger2 +@EnableCircuitBreaker +@EnableHystrixDashboard +public class PkmstApplication { + + private static final Logger LOGGER = LoggerFactory.getLogger(PkmstApplication.class); + + public static void main(String[] args) { + LOGGER.debug("Running spring boot application"); + SpringApplication.run(PkmstApplication.class, args); + } +} + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/AppConfig.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/AppConfig.java new file mode 100644 index 00000000000..ba323306ce0 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/AppConfig.java @@ -0,0 +1,34 @@ +package com.prokarma.pkmst.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +/** + * Registers the interceptors which are configurable via yaml + * @author pkmst + * + */ +@Configuration +public class AppConfig extends WebMvcConfigurerAdapter { + /** + * enabling cors support at global level which can be applied at various + * level also as below registry.addMapping("/api/**") + * .allowedOrigins("http://domain2.com") .allowedMethods("PUT", "DELETE") + * .allowedHeaders("header1", "header2", "header3") + * .exposedHeaders("header1", "header2") + * .allowCredentials(false).maxAge(3600); + * + * @return + */ + @Bean + public WebMvcConfigurer corsConfigurer() { + return new WebMvcConfigurerAdapter() { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**"); + } + }; + } +} \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/swagger/PkmstProperties.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/swagger/PkmstProperties.java new file mode 100644 index 00000000000..6d64cd6e26a --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/swagger/PkmstProperties.java @@ -0,0 +1,113 @@ +package com.prokarma.pkmst.config.swagger; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +/** + * Provides the swagger API info + * @author pkmst + * + */ +@Configuration +@ConfigurationProperties(prefix = "pkmst", ignoreUnknownFields = false) +public class PkmstProperties { + + private final Swagger swagger = new Swagger(); + + + public Swagger getSwagger() { + return swagger; + } + + + public static class Swagger { + + private String title = "Pkmst API"; + + private String description = "Pkmst API documentation"; + + private String version = "0.0.1"; + + private String termsOfServiceUrl; + + private String contactName; + + private String contactUrl; + + private String contactEmail; + + private String license; + + private String licenseUrl; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getTermsOfServiceUrl() { + return termsOfServiceUrl; + } + + public void setTermsOfServiceUrl(String termsOfServiceUrl) { + this.termsOfServiceUrl = termsOfServiceUrl; + } + + public String getContactName() { + return contactName; + } + + public void setContactName(String contactName) { + this.contactName = contactName; + } + + public String getContactUrl() { + return contactUrl; + } + + public void setContactUrl(String contactUrl) { + this.contactUrl = contactUrl; + } + + public String getContactEmail() { + return contactEmail; + } + + public void setContactEmail(String contactEmail) { + this.contactEmail = contactEmail; + } + + public String getLicense() { + return license; + } + + public void setLicense(String license) { + this.license = license; + } + + public String getLicenseUrl() { + return licenseUrl; + } + + public void setLicenseUrl(String licenseUrl) { + this.licenseUrl = licenseUrl; + } + } +} \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/swagger/SwaggerDocumentationConfig.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/swagger/SwaggerDocumentationConfig.java new file mode 100644 index 00000000000..67599c9bb45 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/swagger/SwaggerDocumentationConfig.java @@ -0,0 +1,61 @@ +package com.prokarma.pkmst.config.swagger; + +import java.util.Date; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.ResponseEntity; +import org.springframework.util.StopWatch; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +//import static springfox.documentation.builders.PathSelectors.regex; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; +/** + * Enable swagger ui for application + * @author pkmst + * + */ +@EnableSwagger2 +@Configuration +public class SwaggerDocumentationConfig { + + public static final String DEFAULT_INCLUDE_PATTERN = "/pkmst/.*"; + @Bean + public Docket swaggerSpringfoxDocket(PkmstProperties pkmstProperties) { + StopWatch watch = new StopWatch(); + watch.start(); + Contact contact = new Contact( + pkmstProperties.getSwagger().getContactName(), + pkmstProperties.getSwagger().getContactUrl(), + pkmstProperties.getSwagger().getContactEmail()); + + ApiInfo apiInfo = new ApiInfo( + pkmstProperties.getSwagger().getTitle(), + pkmstProperties.getSwagger().getDescription(), + pkmstProperties.getSwagger().getVersion(), + pkmstProperties.getSwagger().getTermsOfServiceUrl(), + contact, + pkmstProperties.getSwagger().getLicense(), + pkmstProperties.getSwagger().getLicenseUrl()); + + Docket docket = new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo) + .forCodeGeneration(true) + .genericModelSubstitutes(ResponseEntity.class) + .ignoredParameterTypes(java.sql.Date.class) + .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class) + .directModelSubstitute(java.time.ZonedDateTime.class, Date.class) + .directModelSubstitute(java.time.LocalDateTime.class, Date.class) + .select() + .apis(RequestHandlerSelectors.basePackage("com.prokarma.pkmst")) + // .paths(regex(DEFAULT_INCLUDE_PATTERN)) + .paths(PathSelectors.any()) + .build(); + watch.stop(); + return docket; + } + +} \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/PetApi.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/PetApi.java new file mode 100644 index 00000000000..125678b28b1 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/PetApi.java @@ -0,0 +1,153 @@ +/** + * NOTE: This class is auto generated by the swagger code generator program (2.3.0-SNAPSHOT). + * https://github.com/swagger-api/swagger-codegen + * Do not edit the class manually. + */ +package com.prokarma.pkmst.controller; + +import java.io.File; +import com.prokarma.pkmst.model.ModelApiResponse; +import com.prokarma.pkmst.model.Pet; + +import io.swagger.annotations.*; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; + +import java.util.List; +/** + * Provides the info about api methods + * @author pkmst + * + */ +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +@Api(value = "Pet", description = "the Pet API") +public interface PetApi { + + @ApiOperation(value = "Add a new pet to the store", notes = "", response = Void.class, authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 405, message = "Invalid input") }) + @RequestMapping(value = "/pet", + produces = { "application/xml", "application/json" }, + consumes = { "application/json", "application/xml" }, + method = RequestMethod.POST) + ResponseEntity addPet(@ApiParam(value = "Pet object that needs to be added to the store" ,required=true ) @RequestBody Pet body, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Deletes a pet", notes = "", response = Void.class, authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid pet value") }) + @RequestMapping(value = "/pet/{petId}", + produces = { "application/xml", "application/json" }, + method = RequestMethod.DELETE) + ResponseEntity deletePet(@ApiParam(value = "Pet id to delete",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "" ) @RequestHeader(value="api_key", required=false) String apiKey, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Finds Pets by status", notes = "Multiple status values can be provided with comma separated strings", response = Pet.class, responseContainer = "List", authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Pet.class, responseContainer = "List"), + @ApiResponse(code = 400, message = "Invalid status value") }) + @RequestMapping(value = "/pet/findByStatus", + produces = { "application/xml", "application/json" }, + method = RequestMethod.GET) + ResponseEntity> findPetsByStatus(@ApiParam(value = "Status values that need to be considered for filter", required = true, allowableValues = "available, pending, sold") @RequestParam(value = "status", required = true) List status, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Finds Pets by tags", notes = "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", response = Pet.class, responseContainer = "List", authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Pet.class, responseContainer = "List"), + @ApiResponse(code = 400, message = "Invalid tag value") }) + @RequestMapping(value = "/pet/findByTags", + produces = { "application/xml", "application/json" }, + method = RequestMethod.GET) + ResponseEntity> findPetsByTags(@ApiParam(value = "Tags to filter by", required = true) @RequestParam(value = "tags", required = true) List tags, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Find pet by ID", notes = "Returns a single pet", response = Pet.class, authorizations = { + @Authorization(value = "api_key") + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Pet.class), + @ApiResponse(code = 400, message = "Invalid ID supplied"), + @ApiResponse(code = 404, message = "Pet not found") }) + @RequestMapping(value = "/pet/{petId}", + produces = { "application/xml", "application/json" }, + method = RequestMethod.GET) + ResponseEntity getPetById(@ApiParam(value = "ID of pet to return",required=true ) @PathVariable("petId") Long petId, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Update an existing pet", notes = "", response = Void.class, authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid ID supplied"), + @ApiResponse(code = 404, message = "Pet not found"), + @ApiResponse(code = 405, message = "Validation exception") }) + @RequestMapping(value = "/pet", + produces = { "application/xml", "application/json" }, + consumes = { "application/json", "application/xml" }, + method = RequestMethod.PUT) + ResponseEntity updatePet(@ApiParam(value = "Pet object that needs to be added to the store" ,required=true ) @RequestBody Pet body, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Updates a pet in the store with form data", notes = "", response = Void.class, authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 405, message = "Invalid input") }) + @RequestMapping(value = "/pet/{petId}", + produces = { "application/xml", "application/json" }, + consumes = { "application/x-www-form-urlencoded" }, + method = RequestMethod.POST) + ResponseEntity updatePetWithForm(@ApiParam(value = "ID of pet that needs to be updated",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "Updated name of the pet") @RequestPart(value="name", required=false) String name,@ApiParam(value = "Updated status of the pet") @RequestPart(value="status", required=false) String status, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "uploads an image", notes = "", response = ModelApiResponse.class, authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = ModelApiResponse.class) }) + @RequestMapping(value = "/pet/{petId}/uploadImage", + produces = { "application/json" }, + consumes = { "multipart/form-data" }, + method = RequestMethod.POST) + ResponseEntity uploadFile(@ApiParam(value = "ID of pet to update",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "Additional data to pass to server") @RequestPart(value="additionalMetadata", required=false) String additionalMetadata,@ApiParam(value = "file detail") @RequestPart("file") MultipartFile file, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/PetApiController.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/PetApiController.java new file mode 100644 index 00000000000..c8f9f82e9e6 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/PetApiController.java @@ -0,0 +1,126 @@ +package com.prokarma.pkmst.controller; + +import java.io.File; +import com.prokarma.pkmst.model.ModelApiResponse; +import com.prokarma.pkmst.model.Pet; + +import io.swagger.annotations.*; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +/** + * Api implemention + * @author pkmst + * + */ +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +@Controller +public class PetApiController implements PetApi { + private final ObjectMapper objectMapper; +@Autowired + public PetApiController(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + public ResponseEntity addPet(@ApiParam(value = "Pet object that needs to be added to the store" ,required=true ) @RequestBody Pet body, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity deletePet(@ApiParam(value = "Pet id to delete",required=true ) @PathVariable("petId") Long petId, + @ApiParam(value = "" ) @RequestHeader(value="api_key", required=false) String apiKey, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity> findPetsByStatus(@ApiParam(value = "Status values that need to be considered for filter", required = true, allowableValues = "available, pending, sold") @RequestParam(value = "status", required = true) List status, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/xml")) { + return new ResponseEntity>(objectMapper.readValue("", List.class), HttpStatus.OK); + } + + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity>(objectMapper.readValue("", List.class), HttpStatus.OK); + } + + return new ResponseEntity>(HttpStatus.OK); + } + + public ResponseEntity> findPetsByTags(@ApiParam(value = "Tags to filter by", required = true) @RequestParam(value = "tags", required = true) List tags, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/xml")) { + return new ResponseEntity>(objectMapper.readValue("", List.class), HttpStatus.OK); + } + + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity>(objectMapper.readValue("", List.class), HttpStatus.OK); + } + + return new ResponseEntity>(HttpStatus.OK); + } + + public ResponseEntity getPetById(@ApiParam(value = "ID of pet to return",required=true ) @PathVariable("petId") Long petId, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/xml")) { + return new ResponseEntity(objectMapper.readValue("", Pet.class), HttpStatus.OK); + } + + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity(objectMapper.readValue("", Pet.class), HttpStatus.OK); + } + + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity updatePet(@ApiParam(value = "Pet object that needs to be added to the store" ,required=true ) @RequestBody Pet body, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity updatePetWithForm(@ApiParam(value = "ID of pet that needs to be updated",required=true ) @PathVariable("petId") Long petId, + @ApiParam(value = "Updated name of the pet") @RequestPart(value="name", required=false) String name, + @ApiParam(value = "Updated status of the pet") @RequestPart(value="status", required=false) String status, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity uploadFile(@ApiParam(value = "ID of pet to update",required=true ) @PathVariable("petId") Long petId, + @ApiParam(value = "Additional data to pass to server") @RequestPart(value="additionalMetadata", required=false) String additionalMetadata, + @ApiParam(value = "file detail") @RequestPart("file") MultipartFile file, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity(objectMapper.readValue("", ModelApiResponse.class), HttpStatus.OK); + } + + return new ResponseEntity(HttpStatus.OK); + } + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/StoreApi.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/StoreApi.java new file mode 100644 index 00000000000..e457b0778a3 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/StoreApi.java @@ -0,0 +1,75 @@ +/** + * NOTE: This class is auto generated by the swagger code generator program (2.3.0-SNAPSHOT). + * https://github.com/swagger-api/swagger-codegen + * Do not edit the class manually. + */ +package com.prokarma.pkmst.controller; + +import java.util.Map; +import com.prokarma.pkmst.model.Order; + +import io.swagger.annotations.*; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; + +import java.util.List; +/** + * Provides the info about api methods + * @author pkmst + * + */ +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +@Api(value = "Store", description = "the Store API") +public interface StoreApi { + + @ApiOperation(value = "Delete purchase order by ID", notes = "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", response = Void.class, tags={ "store", }) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid ID supplied"), + @ApiResponse(code = 404, message = "Order not found") }) + @RequestMapping(value = "/store/order/{orderId}", + produces = { "application/xml", "application/json" }, + method = RequestMethod.DELETE) + ResponseEntity deleteOrder(@ApiParam(value = "ID of the order that needs to be deleted",required=true ) @PathVariable("orderId") String orderId, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Returns pet inventories by status", notes = "Returns a map of status codes to quantities", response = Integer.class, responseContainer = "Map", authorizations = { + @Authorization(value = "api_key") + }, tags={ "store", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Map.class, responseContainer = "Map") }) + @RequestMapping(value = "/store/inventory", + produces = { "application/json" }, + method = RequestMethod.GET) + ResponseEntity> getInventory( @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Find purchase order by ID", notes = "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", response = Order.class, tags={ "store", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Order.class), + @ApiResponse(code = 400, message = "Invalid ID supplied"), + @ApiResponse(code = 404, message = "Order not found") }) + @RequestMapping(value = "/store/order/{orderId}", + produces = { "application/xml", "application/json" }, + method = RequestMethod.GET) + ResponseEntity getOrderById(@ApiParam(value = "ID of pet that needs to be fetched",required=true ) @PathVariable("orderId") Long orderId, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Place an order for a pet", notes = "", response = Order.class, tags={ "store", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Order.class), + @ApiResponse(code = 400, message = "Invalid Order") }) + @RequestMapping(value = "/store/order", + produces = { "application/xml", "application/json" }, + method = RequestMethod.POST) + ResponseEntity placeOrder(@ApiParam(value = "order placed for purchasing the pet" ,required=true ) @RequestBody Order body, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/StoreApiController.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/StoreApiController.java new file mode 100644 index 00000000000..a34a38ce418 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/StoreApiController.java @@ -0,0 +1,85 @@ +package com.prokarma.pkmst.controller; + +import java.util.Map; +import com.prokarma.pkmst.model.Order; + +import io.swagger.annotations.*; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +/** + * Api implemention + * @author pkmst + * + */ +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +@Controller +public class StoreApiController implements StoreApi { + private final ObjectMapper objectMapper; +@Autowired + public StoreApiController(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + public ResponseEntity deleteOrder(@ApiParam(value = "ID of the order that needs to be deleted",required=true ) @PathVariable("orderId") String orderId, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity> getInventory(@RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity>(objectMapper.readValue("", Map.class), HttpStatus.OK); + } + + return new ResponseEntity>(HttpStatus.OK); + } + + public ResponseEntity getOrderById(@ApiParam(value = "ID of pet that needs to be fetched",required=true ) @PathVariable("orderId") Long orderId, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/xml")) { + return new ResponseEntity(objectMapper.readValue("", Order.class), HttpStatus.OK); + } + + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity(objectMapper.readValue("", Order.class), HttpStatus.OK); + } + + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity placeOrder(@ApiParam(value = "order placed for purchasing the pet" ,required=true ) @RequestBody Order body, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/xml")) { + return new ResponseEntity(objectMapper.readValue("", Order.class), HttpStatus.OK); + } + + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity(objectMapper.readValue("", Order.class), HttpStatus.OK); + } + + return new ResponseEntity(HttpStatus.OK); + } + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/UserApi.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/UserApi.java new file mode 100644 index 00000000000..4f591a67307 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/UserApi.java @@ -0,0 +1,110 @@ +/** + * NOTE: This class is auto generated by the swagger code generator program (2.3.0-SNAPSHOT). + * https://github.com/swagger-api/swagger-codegen + * Do not edit the class manually. + */ +package com.prokarma.pkmst.controller; + +import java.util.List; +import com.prokarma.pkmst.model.User; + +import io.swagger.annotations.*; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; + +import java.util.List; +/** + * Provides the info about api methods + * @author pkmst + * + */ +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +@Api(value = "User", description = "the User API") +public interface UserApi { + + @ApiOperation(value = "Create user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation") }) + @RequestMapping(value = "/user", + produces = { "application/xml", "application/json" }, + method = RequestMethod.POST) + ResponseEntity createUser(@ApiParam(value = "Created user object" ,required=true ) @RequestBody User body, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Creates list of users with given input array", notes = "", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation") }) + @RequestMapping(value = "/user/createWithArray", + produces = { "application/xml", "application/json" }, + method = RequestMethod.POST) + ResponseEntity createUsersWithArrayInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List body, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Creates list of users with given input array", notes = "", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation") }) + @RequestMapping(value = "/user/createWithList", + produces = { "application/xml", "application/json" }, + method = RequestMethod.POST) + ResponseEntity createUsersWithListInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List body, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Delete user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid username supplied"), + @ApiResponse(code = 404, message = "User not found") }) + @RequestMapping(value = "/user/{username}", + produces = { "application/xml", "application/json" }, + method = RequestMethod.DELETE) + ResponseEntity deleteUser(@ApiParam(value = "The name that needs to be deleted",required=true ) @PathVariable("username") String username, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Get user by user name", notes = "", response = User.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = User.class), + @ApiResponse(code = 400, message = "Invalid username supplied"), + @ApiResponse(code = 404, message = "User not found") }) + @RequestMapping(value = "/user/{username}", + produces = { "application/xml", "application/json" }, + method = RequestMethod.GET) + ResponseEntity getUserByName(@ApiParam(value = "The name that needs to be fetched. Use user1 for testing. ",required=true ) @PathVariable("username") String username, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Logs user into the system", notes = "", response = String.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = String.class), + @ApiResponse(code = 400, message = "Invalid username/password supplied") }) + @RequestMapping(value = "/user/login", + produces = { "application/xml", "application/json" }, + method = RequestMethod.GET) + ResponseEntity loginUser(@ApiParam(value = "The user name for login", required = true) @RequestParam(value = "username", required = true) String username,@ApiParam(value = "The password for login in clear text", required = true) @RequestParam(value = "password", required = true) String password, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Logs out current logged in user session", notes = "", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation") }) + @RequestMapping(value = "/user/logout", + produces = { "application/xml", "application/json" }, + method = RequestMethod.GET) + ResponseEntity logoutUser( @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Updated user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid user supplied"), + @ApiResponse(code = 404, message = "User not found") }) + @RequestMapping(value = "/user/{username}", + produces = { "application/xml", "application/json" }, + method = RequestMethod.PUT) + ResponseEntity updateUser(@ApiParam(value = "name that need to be deleted",required=true ) @PathVariable("username") String username,@ApiParam(value = "Updated user object" ,required=true ) @RequestBody User body, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/UserApiController.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/UserApiController.java new file mode 100644 index 00000000000..65c45ee62ab --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/UserApiController.java @@ -0,0 +1,106 @@ +package com.prokarma.pkmst.controller; + +import java.util.List; +import com.prokarma.pkmst.model.User; + +import io.swagger.annotations.*; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +/** + * Api implemention + * @author pkmst + * + */ +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +@Controller +public class UserApiController implements UserApi { + private final ObjectMapper objectMapper; +@Autowired + public UserApiController(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + public ResponseEntity createUser(@ApiParam(value = "Created user object" ,required=true ) @RequestBody User body, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity createUsersWithArrayInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List body, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity createUsersWithListInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List body, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity deleteUser(@ApiParam(value = "The name that needs to be deleted",required=true ) @PathVariable("username") String username, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity getUserByName(@ApiParam(value = "The name that needs to be fetched. Use user1 for testing. ",required=true ) @PathVariable("username") String username, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/xml")) { + return new ResponseEntity(objectMapper.readValue("", User.class), HttpStatus.OK); + } + + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity(objectMapper.readValue("", User.class), HttpStatus.OK); + } + + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity loginUser(@ApiParam(value = "The user name for login", required = true) @RequestParam(value = "username", required = true) String username, + @ApiParam(value = "The password for login in clear text", required = true) @RequestParam(value = "password", required = true) String password, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/xml")) { + return new ResponseEntity(objectMapper.readValue("", String.class), HttpStatus.OK); + } + + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity(objectMapper.readValue("", String.class), HttpStatus.OK); + } + + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity logoutUser(@RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity updateUser(@ApiParam(value = "name that need to be deleted",required=true ) @PathVariable("username") String username, + @ApiParam(value = "Updated user object" ,required=true ) @RequestBody User body, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/logging/HttpLoggingFilter.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/logging/HttpLoggingFilter.java new file mode 100644 index 00000000000..ffb1b3e6cb5 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/logging/HttpLoggingFilter.java @@ -0,0 +1,434 @@ +package com.prokarma.pkmst.logging; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ReadListener; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.WriteListener; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.output.TeeOutputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +/** + * Implements javax.servlet.Filter and dump the request/response to syslog + * @author pkmst + * + */ + +@Component +public class HttpLoggingFilter implements Filter { + + private static final Logger log = LoggerFactory.getLogger(HttpLoggingFilter.class); + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException { + try { + HttpServletRequest httpServletRequest = (HttpServletRequest) request; + HttpServletResponse httpServletResponse = (HttpServletResponse) response; + Map requestMap = this.getTypesafeRequestMap(httpServletRequest); + BufferedRequestWrapper bufferedRequest = new BufferedRequestWrapper(httpServletRequest); + BufferedResponseWrapper bufferedResponse = new BufferedResponseWrapper(httpServletResponse); + final StringBuilder logMessage = new StringBuilder( + "REST Request - ").append("[HTTP METHOD:") + .append(httpServletRequest.getMethod()) + .append("] [PATH INFO:") + .append(httpServletRequest.getServletPath()) + .append("] [REQUEST PARAMETERS:").append(requestMap) + .append("] [REQUEST BODY:") + .append(bufferedRequest.getRequestBody()) + .append("] [REMOTE ADDRESS:") + .append(httpServletRequest.getRemoteAddr()).append("]"); + long start = System.currentTimeMillis(); + chain.doFilter(bufferedRequest, bufferedResponse); + long elapsedTime = System.currentTimeMillis() - start; + String respContent = null; + if (bufferedResponse.getContent() == null || bufferedResponse.getContent() == "") { + respContent = "No data"; + } else { + respContent = bufferedResponse.getContent(); + } + logMessage.append(" [RESPONSE:").append(respContent) + .append("] [STATUS CODE:") + .append(bufferedResponse.getStatus()) + .append("] [Response Time(ms):").append(elapsedTime) + .append("]"); + log.info(logMessage.toString()); + } catch (Throwable a) { + log.error(a.getMessage()); + a.printStackTrace(); + } + } + + private Map getTypesafeRequestMap(HttpServletRequest request) { + Map typesafeRequestMap = new HashMap(); + Enumeration requestParamNames = request.getParameterNames(); + while (requestParamNames.hasMoreElements()) { + String requestParamName = (String) requestParamNames.nextElement(); + String requestParamValue; + if (requestParamName.equalsIgnoreCase("password")) { + requestParamValue = "********"; + } else { + requestParamValue = request.getParameter(requestParamName); + } + typesafeRequestMap.put(requestParamName, requestParamValue); + } + return typesafeRequestMap; + } + + @Override + public void destroy() { + } + + private static final class BufferedRequestWrapper extends HttpServletRequestWrapper { + + private ByteArrayInputStream bais = null; + private ByteArrayOutputStream baos = null; + private BufferedServletInputStream bsis = null; + private byte[] buffer = null; + + public BufferedRequestWrapper(HttpServletRequest req) throws IOException { + super(req); + // Read InputStream and store its content in a buffer. + InputStream is = req.getInputStream(); + this.baos = new ByteArrayOutputStream(); + byte buf[] = new byte[1024]; + int read; + while ((read = is.read(buf)) > 0) { + this.baos.write(buf, 0, read); + } + this.buffer = this.baos.toByteArray(); + } + + @Override + public ServletInputStream getInputStream() { + this.bais = new ByteArrayInputStream(this.buffer); + this.bsis = new BufferedServletInputStream(this.bais); + return this.bsis; + } + + String getRequestBody() throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(this.getInputStream())); + String line = null; + StringBuilder inputBuffer = new StringBuilder(); + do { + line = reader.readLine(); + if (null != line) { + inputBuffer.append(line.trim()); + } + } while (line != null); + reader.close(); + return inputBuffer.toString().trim(); + } + + } + + private static final class BufferedServletInputStream extends ServletInputStream { + + private ByteArrayInputStream bais; + + public BufferedServletInputStream(ByteArrayInputStream bais) { + this.bais = bais; + } + + @Override + public int available() { + return this.bais.available(); + } + + @Override + public int read() { + return this.bais.read(); + } + + @Override + public int read(byte[] buf, int off, int len) { + return this.bais.read(buf, off, len); + } + + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + } + + public class TeeServletOutputStream extends ServletOutputStream { + + private final TeeOutputStream targetStream; + + public TeeServletOutputStream(OutputStream one, OutputStream two) { + targetStream = new TeeOutputStream(one, two); + } + + @Override + public void write(int arg0) throws IOException { + this.targetStream.write(arg0); + } + + public void flush() throws IOException { + super.flush(); + this.targetStream.flush(); + } + + public void close() throws IOException { + super.close(); + this.targetStream.close(); + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setWriteListener(WriteListener writeListener) { + + } + } + + public class BufferedResponseWrapper implements HttpServletResponse { + + HttpServletResponse original; + TeeServletOutputStream tee; + ByteArrayOutputStream bos; + + public BufferedResponseWrapper(HttpServletResponse response) { + original = response; + } + + public String getContent() { + if (bos == null) { + return null; + } else + return bos.toString(); + } + + public PrintWriter getWriter() throws IOException { + return original.getWriter(); + } + + public ServletOutputStream getOutputStream() throws IOException { + if (tee == null) { + bos = new ByteArrayOutputStream(); + tee = new TeeServletOutputStream(original.getOutputStream(),bos); + } + return tee; + + } + + @Override + public String getCharacterEncoding() { + return original.getCharacterEncoding(); + } + + @Override + public String getContentType() { + return original.getContentType(); + } + + @Override + public void setCharacterEncoding(String charset) { + original.setCharacterEncoding(charset); + } + + @Override + public void setContentLength(int len) { + original.setContentLength(len); + } + + @Override + public void setContentLengthLong(long l) { + original.setContentLengthLong(l); + } + + @Override + public void setContentType(String type) { + original.setContentType(type); + } + + @Override + public void setBufferSize(int size) { + original.setBufferSize(size); + } + + @Override + public int getBufferSize() { + return original.getBufferSize(); + } + + @Override + public void flushBuffer() throws IOException { + tee.flush(); + } + + @Override + public void resetBuffer() { + original.resetBuffer(); + } + + @Override + public boolean isCommitted() { + return original.isCommitted(); + } + + @Override + public void reset() { + original.reset(); + } + + @Override + public void setLocale(Locale loc) { + original.setLocale(loc); + } + + @Override + public Locale getLocale() { + return original.getLocale(); + } + + @Override + public void addCookie(Cookie cookie) { + original.addCookie(cookie); + } + + @Override + public boolean containsHeader(String name) { + return original.containsHeader(name); + } + + @Override + public String encodeURL(String url) { + return original.encodeURL(url); + } + + @Override + public String encodeRedirectURL(String url) { + return original.encodeRedirectURL(url); + } + + @SuppressWarnings("deprecation") + @Override + public String encodeUrl(String url) { + return original.encodeUrl(url); + } + + @SuppressWarnings("deprecation") + @Override + public String encodeRedirectUrl(String url) { + return original.encodeRedirectUrl(url); + } + + @Override + public void sendError(int sc, String msg) throws IOException { + original.sendError(sc, msg); + } + + @Override + public void sendError(int sc) throws IOException { + original.sendError(sc); + } + + @Override + public void sendRedirect(String location) throws IOException { + original.sendRedirect(location); + } + + @Override + public void setDateHeader(String name, long date) { + original.setDateHeader(name, date); + } + + @Override + public void addDateHeader(String name, long date) { + original.addDateHeader(name, date); + } + + @Override + public void setHeader(String name, String value) { + original.setHeader(name, value); + } + + @Override + public void addHeader(String name, String value) { + original.addHeader(name, value); + } + + @Override + public void setIntHeader(String name, int value) { + original.setIntHeader(name, value); + } + + @Override + public void addIntHeader(String name, int value) { + original.addIntHeader(name, value); + } + + @Override + public void setStatus(int sc) { + original.setStatus(sc); + } + + @SuppressWarnings("deprecation") + @Override + public void setStatus(int sc, String sm) { + original.setStatus(sc, sm); + } + + @Override + public String getHeader(String arg0) { + return original.getHeader(arg0); + } + + @Override + public Collection getHeaderNames() { + return original.getHeaderNames(); + } + + @Override + public Collection getHeaders(String arg0) { + return original.getHeaders(arg0); + } + + @Override + public int getStatus() { + return original.getStatus(); + } + } +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Category.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Category.java new file mode 100644 index 00000000000..2d27297d3de --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Category.java @@ -0,0 +1,104 @@ +package com.prokarma.pkmst.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +/** + * Response class to be returned by Api + * @author pkmst + * + */ +/** + * A category for a pet + */ +@ApiModel(description = "A category for a pet") + +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +public class Category { + @JsonProperty("id") + private Long id = null; + + @JsonProperty("name") + private String name = null; + + public Category id(Long id) { + this.id = id; + return this; + } + + /** + * Get id + * @return id + **/ + @ApiModelProperty(value = "") + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Category name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * @return name + **/ + @ApiModelProperty(value = "") + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Category category = (Category) o; + return Objects.equals(this.id, category.id) && + Objects.equals(this.name, category.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Category {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/ModelApiResponse.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/ModelApiResponse.java new file mode 100644 index 00000000000..7a2ca9b4c95 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/ModelApiResponse.java @@ -0,0 +1,127 @@ +package com.prokarma.pkmst.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +/** + * Response class to be returned by Api + * @author pkmst + * + */ +/** + * Describes the result of uploading an image resource + */ +@ApiModel(description = "Describes the result of uploading an image resource") + +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +public class ModelApiResponse { + @JsonProperty("code") + private Integer code = null; + + @JsonProperty("type") + private String type = null; + + @JsonProperty("message") + private String message = null; + + public ModelApiResponse code(Integer code) { + this.code = code; + return this; + } + + /** + * Get code + * @return code + **/ + @ApiModelProperty(value = "") + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public ModelApiResponse type(String type) { + this.type = type; + return this; + } + + /** + * Get type + * @return type + **/ + @ApiModelProperty(value = "") + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public ModelApiResponse message(String message) { + this.message = message; + return this; + } + + /** + * Get message + * @return message + **/ + @ApiModelProperty(value = "") + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ModelApiResponse _apiResponse = (ModelApiResponse) o; + return Objects.equals(this.code, _apiResponse.code) && + Objects.equals(this.type, _apiResponse.type) && + Objects.equals(this.message, _apiResponse.message); + } + + @Override + public int hashCode() { + return Objects.hash(code, type, message); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ModelApiResponse {\n"); + + sb.append(" code: ").append(toIndentedString(code)).append("\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Order.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Order.java new file mode 100644 index 00000000000..70432b68f31 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Order.java @@ -0,0 +1,231 @@ +package com.prokarma.pkmst.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.threeten.bp.OffsetDateTime; +/** + * Response class to be returned by Api + * @author pkmst + * + */ +/** + * An order for a pets from the pet store + */ +@ApiModel(description = "An order for a pets from the pet store") + +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +public class Order { + @JsonProperty("id") + private Long id = null; + + @JsonProperty("petId") + private Long petId = null; + + @JsonProperty("quantity") + private Integer quantity = null; + + @JsonProperty("shipDate") + private OffsetDateTime shipDate = null; + + /** + * Order Status + */ + public enum StatusEnum { + PLACED("placed"), + + APPROVED("approved"), + + DELIVERED("delivered"); + + private String value; + + StatusEnum(String value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static StatusEnum fromValue(String text) { + for (StatusEnum b : StatusEnum.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + return null; + } + } + + @JsonProperty("status") + private StatusEnum status = null; + + @JsonProperty("complete") + private Boolean complete = false; + + public Order id(Long id) { + this.id = id; + return this; + } + + /** + * Get id + * @return id + **/ + @ApiModelProperty(value = "") + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Order petId(Long petId) { + this.petId = petId; + return this; + } + + /** + * Get petId + * @return petId + **/ + @ApiModelProperty(value = "") + public Long getPetId() { + return petId; + } + + public void setPetId(Long petId) { + this.petId = petId; + } + + public Order quantity(Integer quantity) { + this.quantity = quantity; + return this; + } + + /** + * Get quantity + * @return quantity + **/ + @ApiModelProperty(value = "") + public Integer getQuantity() { + return quantity; + } + + public void setQuantity(Integer quantity) { + this.quantity = quantity; + } + + public Order shipDate(OffsetDateTime shipDate) { + this.shipDate = shipDate; + return this; + } + + /** + * Get shipDate + * @return shipDate + **/ + @ApiModelProperty(value = "") + public OffsetDateTime getShipDate() { + return shipDate; + } + + public void setShipDate(OffsetDateTime shipDate) { + this.shipDate = shipDate; + } + + public Order status(StatusEnum status) { + this.status = status; + return this; + } + + /** + * Order Status + * @return status + **/ + @ApiModelProperty(value = "Order Status") + public StatusEnum getStatus() { + return status; + } + + public void setStatus(StatusEnum status) { + this.status = status; + } + + public Order complete(Boolean complete) { + this.complete = complete; + return this; + } + + /** + * Get complete + * @return complete + **/ + @ApiModelProperty(value = "") + public Boolean isComplete() { + return complete; + } + + public void setComplete(Boolean complete) { + this.complete = complete; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Order order = (Order) o; + return Objects.equals(this.id, order.id) && + Objects.equals(this.petId, order.petId) && + Objects.equals(this.quantity, order.quantity) && + Objects.equals(this.shipDate, order.shipDate) && + Objects.equals(this.status, order.status) && + Objects.equals(this.complete, order.complete); + } + + @Override + public int hashCode() { + return Objects.hash(id, petId, quantity, shipDate, status, complete); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Order {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" petId: ").append(toIndentedString(petId)).append("\n"); + sb.append(" quantity: ").append(toIndentedString(quantity)).append("\n"); + sb.append(" shipDate: ").append(toIndentedString(shipDate)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" complete: ").append(toIndentedString(complete)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Pet.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Pet.java new file mode 100644 index 00000000000..9d56722e870 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Pet.java @@ -0,0 +1,249 @@ +package com.prokarma.pkmst.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.prokarma.pkmst.model.Category; +import com.prokarma.pkmst.model.Tag; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +/** + * Response class to be returned by Api + * @author pkmst + * + */ +/** + * A pet for sale in the pet store + */ +@ApiModel(description = "A pet for sale in the pet store") + +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +public class Pet { + @JsonProperty("id") + private Long id = null; + + @JsonProperty("category") + private Category category = null; + + @JsonProperty("name") + private String name = null; + + @JsonProperty("photoUrls") + + private List photoUrls = new ArrayList<>(); + + @JsonProperty("tags") + + private List tags = null; + + /** + * pet status in the store + */ + public enum StatusEnum { + AVAILABLE("available"), + + PENDING("pending"), + + SOLD("sold"); + + private String value; + + StatusEnum(String value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static StatusEnum fromValue(String text) { + for (StatusEnum b : StatusEnum.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + return null; + } + } + + @JsonProperty("status") + private StatusEnum status = null; + + public Pet id(Long id) { + this.id = id; + return this; + } + + /** + * Get id + * @return id + **/ + @ApiModelProperty(value = "") + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Pet category(Category category) { + this.category = category; + return this; + } + + /** + * Get category + * @return category + **/ + @ApiModelProperty(value = "") + public Category getCategory() { + return category; + } + + public void setCategory(Category category) { + this.category = category; + } + + public Pet name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * @return name + **/ + @ApiModelProperty(example = "doggie", required = true, value = "") + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Pet photoUrls(List photoUrls) { + this.photoUrls = photoUrls; + return this; + } + + public Pet addPhotoUrlsItem(String photoUrlsItem) { + this.photoUrls.add(photoUrlsItem); + return this; + } + + /** + * Get photoUrls + * @return photoUrls + **/ + @ApiModelProperty(required = true, value = "") + public List getPhotoUrls() { + return photoUrls; + } + + public void setPhotoUrls(List photoUrls) { + this.photoUrls = photoUrls; + } + + public Pet tags(List tags) { + this.tags = tags; + return this; + } + + public Pet addTagsItem(Tag tagsItem) { + if (this.tags == null) { + this.tags = new ArrayList<>(); + } + this.tags.add(tagsItem); + return this; + } + + /** + * Get tags + * @return tags + **/ + @ApiModelProperty(value = "") + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + + public Pet status(StatusEnum status) { + this.status = status; + return this; + } + + /** + * pet status in the store + * @return status + **/ + @ApiModelProperty(value = "pet status in the store") + public StatusEnum getStatus() { + return status; + } + + public void setStatus(StatusEnum status) { + this.status = status; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Pet pet = (Pet) o; + return Objects.equals(this.id, pet.id) && + Objects.equals(this.category, pet.category) && + Objects.equals(this.name, pet.name) && + Objects.equals(this.photoUrls, pet.photoUrls) && + Objects.equals(this.tags, pet.tags) && + Objects.equals(this.status, pet.status); + } + + @Override + public int hashCode() { + return Objects.hash(id, category, name, photoUrls, tags, status); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Pet {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" category: ").append(toIndentedString(category)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" photoUrls: ").append(toIndentedString(photoUrls)).append("\n"); + sb.append(" tags: ").append(toIndentedString(tags)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Tag.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Tag.java new file mode 100644 index 00000000000..ae1b34a856f --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Tag.java @@ -0,0 +1,104 @@ +package com.prokarma.pkmst.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +/** + * Response class to be returned by Api + * @author pkmst + * + */ +/** + * A tag for a pet + */ +@ApiModel(description = "A tag for a pet") + +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +public class Tag { + @JsonProperty("id") + private Long id = null; + + @JsonProperty("name") + private String name = null; + + public Tag id(Long id) { + this.id = id; + return this; + } + + /** + * Get id + * @return id + **/ + @ApiModelProperty(value = "") + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Tag name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * @return name + **/ + @ApiModelProperty(value = "") + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tag tag = (Tag) o; + return Objects.equals(this.id, tag.id) && + Objects.equals(this.name, tag.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Tag {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/User.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/User.java new file mode 100644 index 00000000000..5633f163eb0 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/User.java @@ -0,0 +1,242 @@ +package com.prokarma.pkmst.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +/** + * Response class to be returned by Api + * @author pkmst + * + */ +/** + * A User who is purchasing from the pet store + */ +@ApiModel(description = "A User who is purchasing from the pet store") + +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +public class User { + @JsonProperty("id") + private Long id = null; + + @JsonProperty("username") + private String username = null; + + @JsonProperty("firstName") + private String firstName = null; + + @JsonProperty("lastName") + private String lastName = null; + + @JsonProperty("email") + private String email = null; + + @JsonProperty("password") + private String password = null; + + @JsonProperty("phone") + private String phone = null; + + @JsonProperty("userStatus") + private Integer userStatus = null; + + public User id(Long id) { + this.id = id; + return this; + } + + /** + * Get id + * @return id + **/ + @ApiModelProperty(value = "") + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public User username(String username) { + this.username = username; + return this; + } + + /** + * Get username + * @return username + **/ + @ApiModelProperty(value = "") + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public User firstName(String firstName) { + this.firstName = firstName; + return this; + } + + /** + * Get firstName + * @return firstName + **/ + @ApiModelProperty(value = "") + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public User lastName(String lastName) { + this.lastName = lastName; + return this; + } + + /** + * Get lastName + * @return lastName + **/ + @ApiModelProperty(value = "") + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public User email(String email) { + this.email = email; + return this; + } + + /** + * Get email + * @return email + **/ + @ApiModelProperty(value = "") + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public User password(String password) { + this.password = password; + return this; + } + + /** + * Get password + * @return password + **/ + @ApiModelProperty(value = "") + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public User phone(String phone) { + this.phone = phone; + return this; + } + + /** + * Get phone + * @return phone + **/ + @ApiModelProperty(value = "") + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public User userStatus(Integer userStatus) { + this.userStatus = userStatus; + return this; + } + + /** + * User Status + * @return userStatus + **/ + @ApiModelProperty(value = "User Status") + public Integer getUserStatus() { + return userStatus; + } + + public void setUserStatus(Integer userStatus) { + this.userStatus = userStatus; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + User user = (User) o; + return Objects.equals(this.id, user.id) && + Objects.equals(this.username, user.username) && + Objects.equals(this.firstName, user.firstName) && + Objects.equals(this.lastName, user.lastName) && + Objects.equals(this.email, user.email) && + Objects.equals(this.password, user.password) && + Objects.equals(this.phone, user.phone) && + Objects.equals(this.userStatus, user.userStatus); + } + + @Override + public int hashCode() { + return Objects.hash(id, username, firstName, lastName, email, password, phone, userStatus); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class User {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" username: ").append(toIndentedString(username)).append("\n"); + sb.append(" firstName: ").append(toIndentedString(firstName)).append("\n"); + sb.append(" lastName: ").append(toIndentedString(lastName)).append("\n"); + sb.append(" email: ").append(toIndentedString(email)).append("\n"); + sb.append(" password: ").append(toIndentedString(password)).append("\n"); + sb.append(" phone: ").append(toIndentedString(phone)).append("\n"); + sb.append(" userStatus: ").append(toIndentedString(userStatus)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/AuthorizationServerConfiguration.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/AuthorizationServerConfiguration.java new file mode 100644 index 00000000000..f2bedfec61c --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/AuthorizationServerConfiguration.java @@ -0,0 +1,61 @@ +package com.prokarma.pkmst.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; +import org.springframework.security.oauth2.provider.token.TokenStore; +/** + * Convenient strategy for configuring an OAUth2 Authorization Server. Beans of this type are applied to the Spring + * context automatically if you {@link EnableAuthorizationServer @EnableAuthorizationServer}. + * + * @author pkmst + * + */ +@Configuration +@EnableAuthorizationServer +public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { + + private static String REALM="MY_OAUTH_REALM"; + + @Autowired + private TokenStore tokenStore; + + @Autowired + private UserApprovalHandler userApprovalHandler; + + @Autowired + @Qualifier("authenticationManagerBean") + private AuthenticationManager authenticationManager; + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .secret("secret") + .accessTokenValiditySeconds(120).//Access token is only valid for 2 minutes. + refreshTokenValiditySeconds(600);//Refresh token is only valid for 10 minutes. + } + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler) + .authenticationManager(authenticationManager); + } + + @Override + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { + oauthServer.realm(REALM+"/client"); + } + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/OAuth2SecurityConfiguration.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/OAuth2SecurityConfiguration.java new file mode 100644 index 00000000000..ed96778f069 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/OAuth2SecurityConfiguration.java @@ -0,0 +1,82 @@ +package com.prokarma.pkmst.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.security.SecurityProperties; +import org.springframework.core.annotation.Order; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.approval.ApprovalStore; +import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; +import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; +/** + * Provides a convenient base class for creating a {@link WebSecurityConfigurer} + * instance. The implementation allows customization by overriding methods. + * + * @see EnableWebSecurity + * + * @author pkmst + */ +@Configuration +@EnableWebSecurity +@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) +public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Autowired + private ClientDetailsService clientDetailsService; + + @Autowired + public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication() + .withUser("admin").password("admin@123").roles("ADMIN").and() + .withUser("user").password("user@123").roles("USER"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .csrf().disable() + .anonymous().disable() + .authorizeRequests() + .antMatchers("/oauth/token").permitAll(); + } + + @Override + @Bean + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + + @Bean + public TokenStore tokenStore() { + return new InMemoryTokenStore(); + } + + @Bean + @Autowired + public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){ + TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler(); + handler.setTokenStore(tokenStore); + handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService)); + handler.setClientDetailsService(clientDetailsService); + return handler; + } + + @Bean + @Autowired + public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception { + TokenApprovalStore store = new TokenApprovalStore(); + store.setTokenStore(tokenStore); + return store; + } + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/ResourceServerConfiguration.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/ResourceServerConfiguration.java new file mode 100644 index 00000000000..a45c1f35647 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/ResourceServerConfiguration.java @@ -0,0 +1,52 @@ +package com.prokarma.pkmst.security; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; +import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; +import org.springframework.http.HttpMethod; +/** + * Configurer class for @EnableResourceServer classes. This class adjust the access + * rules and paths that are protected by OAuth2 security. If more than one configures the same property, then the last + * one wins. The configurers are sorted by {@link Order} before being applied. + * + * @author pkmst + * + */ +@Configuration +@EnableResourceServer +public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { + + private static final String RESOURCE_ID = "my_rest_api"; + + @Override + public void configure(ResourceServerSecurityConfigurer resources) { + resources.resourceId(RESOURCE_ID).stateless(false); + } + + @Override + public void configure(HttpSecurity http) throws Exception { + //configure security for the http methods + http. + anonymous().disable() + .requestMatchers().antMatchers(HttpMethod.GET, "/pet/**") + .and().authorizeRequests() + .antMatchers(HttpMethod.GET, "/pet/**").access("hasRole('ADMIN')") + .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); + http. + anonymous().disable() + .requestMatchers().antMatchers(HttpMethod.GET, "/store/**") + .and().authorizeRequests() + .antMatchers(HttpMethod.GET, "/store/**").access("hasRole('ADMIN')") + .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); + http. + anonymous().disable() + .requestMatchers().antMatchers(HttpMethod.GET, "/user/**") + .and().authorizeRequests() + .antMatchers(HttpMethod.GET, "/user/**").access("hasRole('ADMIN')") + .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); + } + +} diff --git a/samples/server/petstore/java-pkmst/src/main/resources/application-dev-config.yml b/samples/server/petstore/java-pkmst/src/main/resources/application-dev-config.yml new file mode 100644 index 00000000000..b0fbb498499 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/resources/application-dev-config.yml @@ -0,0 +1,7 @@ +#Enable cloud config. Also enable the dependency in pom + #cloud: + #config: + #uri: + #fail-fast: true + #password: user + #username: user \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/main/resources/application-dev.yml b/samples/server/petstore/java-pkmst/src/main/resources/application-dev.yml new file mode 100644 index 00000000000..a8218bcc828 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/resources/application-dev.yml @@ -0,0 +1,48 @@ +# Discovery Server Access +server: + port: 8008 + +# Spring Actuator +management: + health: + redis: + enabled: false + security: + enabled: false + + +endpoints: + health: + sensitive: false + +info: + app: + name: Pkmst + description: Microservice developed by PKMST + version: 1.0.0 + +health: + hystrix: + enabled: true + +security: + basic: + enabled: false +# provide rabbitmq configuration +spring: + rabbitmq: + host: + virtual-host: + username: + password: + port: + + sleuth: + sampler: + percentage: 1.0 +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/main/resources/application-local.yml b/samples/server/petstore/java-pkmst/src/main/resources/application-local.yml new file mode 100644 index 00000000000..cf2af23d832 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/resources/application-local.yml @@ -0,0 +1,49 @@ +# Discovery Server Access +server: + port: 8008 + +# Spring Actuator +management: + health: + redis: + enabled: false + security: + enabled: false + + +endpoints: + health: + sensitive: false + +info: + app: + name: Pkmst + description: Microservice developed by PKMST + version: 1.0.0 + +health: + hystrix: + enabled: true + +security: + basic: + enabled: false +# provide rabbitmq configuration +spring: + rabbitmq: + host: + virtual-host: + username: + password: + port: + + sleuth: + sampler: + percentage: 1.0 +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG + \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/main/resources/bootstrap.yml b/samples/server/petstore/java-pkmst/src/main/resources/bootstrap.yml new file mode 100644 index 00000000000..d353a41ff82 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/resources/bootstrap.yml @@ -0,0 +1,5 @@ +spring: + application: + name: pkmst-microservice + profiles: + active: local \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/PetApiTest.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/PetApiTest.java new file mode 100644 index 00000000000..68e9a0474b8 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/PetApiTest.java @@ -0,0 +1,177 @@ +/* + * Swagger Petstore + * This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters. + * + * OpenAPI spec version: 1.0.0 + * Contact: apiteam@swagger.io + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +package com.prokarma.pkmst.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import com.prokarma.pkmst.model.ModelApiResponse; +import com.prokarma.pkmst.model.Pet; +import org.junit.Test; +import org.junit.Ignore; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; + +/** + * API tests for PetApi + */ +@Ignore +public class PetApiTest { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + private final PetApi api = new PetApiController(objectMapper); + + private final String accept = "application/json"; + + + /** + * Add a new pet to the store + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void addPetTest() throws Exception { + Pet body = null; + ResponseEntity response = api.addPet(body , accept); + + // TODO: test validations + } + + /** + * Deletes a pet + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void deletePetTest() throws Exception { + Long petId = null; + String apiKey = null; + ResponseEntity response = api.deletePet(petId, apiKey , accept); + + // TODO: test validations + } + + /** + * Finds Pets by status + * + * Multiple status values can be provided with comma separated strings + * + * @throws Exception + * if the Api call fails + */ + @Test + public void findPetsByStatusTest() throws Exception { + List status = null; + ResponseEntity> response = api.findPetsByStatus(status , accept); + + // TODO: test validations + } + + /** + * Finds Pets by tags + * + * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + * + * @throws Exception + * if the Api call fails + */ + @Test + public void findPetsByTagsTest() throws Exception { + List tags = null; + ResponseEntity> response = api.findPetsByTags(tags , accept); + + // TODO: test validations + } + + /** + * Find pet by ID + * + * Returns a single pet + * + * @throws Exception + * if the Api call fails + */ + @Test + public void getPetByIdTest() throws Exception { + Long petId = null; + ResponseEntity response = api.getPetById(petId , accept); + + // TODO: test validations + } + + /** + * Update an existing pet + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void updatePetTest() throws Exception { + Pet body = null; + ResponseEntity response = api.updatePet(body , accept); + + // TODO: test validations + } + + /** + * Updates a pet in the store with form data + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void updatePetWithFormTest() throws Exception { + Long petId = null; + String name = null; + String status = null; + ResponseEntity response = api.updatePetWithForm(petId, name, status , accept); + + // TODO: test validations + } + + /** + * uploads an image + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void uploadFileTest() throws Exception { + Long petId = null; + String additionalMetadata = null; + MultipartFile file = null; + ResponseEntity response = api.uploadFile(petId, additionalMetadata, file , accept); + + // TODO: test validations + } + +} diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/PkmstIT.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/PkmstIT.java new file mode 100644 index 00000000000..5f4bb3acf74 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/PkmstIT.java @@ -0,0 +1,34 @@ +package com.prokarma.pkmst.controller; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; +import com.prokarma.pkmst.PkmstApplication; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = PkmstApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class PkmstIT { + + @LocalServerPort + private int port; + + TestRestTemplate restTemplate = new TestRestTemplate(); + + HttpHeaders headers = new HttpHeaders(); + + @Test + public void testYourMethod() { + + //add your logic + } + + private String createURLWithPort(String uri) { + return "http://localhost:" + port + uri; + } +} diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/StoreApiTest.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/StoreApiTest.java new file mode 100644 index 00000000000..09acff37e79 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/StoreApiTest.java @@ -0,0 +1,106 @@ +/* + * Swagger Petstore + * This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters. + * + * OpenAPI spec version: 1.0.0 + * Contact: apiteam@swagger.io + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +package com.prokarma.pkmst.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.Map; +import com.prokarma.pkmst.model.Order; +import org.junit.Test; +import org.junit.Ignore; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; + +/** + * API tests for StoreApi + */ +@Ignore +public class StoreApiTest { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + private final StoreApi api = new StoreApiController(objectMapper); + + private final String accept = "application/json"; + + + /** + * Delete purchase order by ID + * + * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + * + * @throws Exception + * if the Api call fails + */ + @Test + public void deleteOrderTest() throws Exception { + String orderId = null; + ResponseEntity response = api.deleteOrder(orderId , accept); + + // TODO: test validations + } + + /** + * Returns pet inventories by status + * + * Returns a map of status codes to quantities + * + * @throws Exception + * if the Api call fails + */ + @Test + public void getInventoryTest() throws Exception { + ResponseEntity> response = api.getInventory( accept); + + // TODO: test validations + } + + /** + * Find purchase order by ID + * + * For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + * + * @throws Exception + * if the Api call fails + */ + @Test + public void getOrderByIdTest() throws Exception { + Long orderId = null; + ResponseEntity response = api.getOrderById(orderId , accept); + + // TODO: test validations + } + + /** + * Place an order for a pet + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void placeOrderTest() throws Exception { + Order body = null; + ResponseEntity response = api.placeOrder(body , accept); + + // TODO: test validations + } + +} diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/UserApiTest.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/UserApiTest.java new file mode 100644 index 00000000000..b0b4e147e51 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/UserApiTest.java @@ -0,0 +1,172 @@ +/* + * Swagger Petstore + * This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters. + * + * OpenAPI spec version: 1.0.0 + * Contact: apiteam@swagger.io + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +package com.prokarma.pkmst.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; +import com.prokarma.pkmst.model.User; +import org.junit.Test; +import org.junit.Ignore; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; + +/** + * API tests for UserApi + */ +@Ignore +public class UserApiTest { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + private final UserApi api = new UserApiController(objectMapper); + + private final String accept = "application/json"; + + + /** + * Create user + * + * This can only be done by the logged in user. + * + * @throws Exception + * if the Api call fails + */ + @Test + public void createUserTest() throws Exception { + User body = null; + ResponseEntity response = api.createUser(body , accept); + + // TODO: test validations + } + + /** + * Creates list of users with given input array + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void createUsersWithArrayInputTest() throws Exception { + List body = null; + ResponseEntity response = api.createUsersWithArrayInput(body , accept); + + // TODO: test validations + } + + /** + * Creates list of users with given input array + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void createUsersWithListInputTest() throws Exception { + List body = null; + ResponseEntity response = api.createUsersWithListInput(body , accept); + + // TODO: test validations + } + + /** + * Delete user + * + * This can only be done by the logged in user. + * + * @throws Exception + * if the Api call fails + */ + @Test + public void deleteUserTest() throws Exception { + String username = null; + ResponseEntity response = api.deleteUser(username , accept); + + // TODO: test validations + } + + /** + * Get user by user name + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void getUserByNameTest() throws Exception { + String username = null; + ResponseEntity response = api.getUserByName(username , accept); + + // TODO: test validations + } + + /** + * Logs user into the system + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void loginUserTest() throws Exception { + String username = null; + String password = null; + ResponseEntity response = api.loginUser(username, password , accept); + + // TODO: test validations + } + + /** + * Logs out current logged in user session + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void logoutUserTest() throws Exception { + ResponseEntity response = api.logoutUser( accept); + + // TODO: test validations + } + + /** + * Updated user + * + * This can only be done by the logged in user. + * + * @throws Exception + * if the Api call fails + */ + @Test + public void updateUserTest() throws Exception { + String username = null; + User body = null; + ResponseEntity response = api.updateUser(username, body , accept); + + // TODO: test validations + } + +} diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/PkmstSteps.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/PkmstSteps.java new file mode 100644 index 00000000000..caf8907693f --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/PkmstSteps.java @@ -0,0 +1,76 @@ +package com.prokarma.pkmst.cucumber; +import cucumber.api.java.After; +import cucumber.api.java.Before; +import cucumber.api.java.en.Given; +import cucumber.api.java.en.Then; +import cucumber.api.java.en.When; +import cucumber.api.PendingException; + +public class PkmstSteps { + +@Given("^I want to write a step with precondition$") +public void i_want_to_write_a_step_with_precondition() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Given("^some other precondition$") +public void some_other_precondition() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^I complete action$") +public void i_complete_action() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^some other action$") +public void some_other_action() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^yet another action$") +public void yet_another_action() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^I validate the outcomes$") +public void i_validate_the_outcomes() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^check more outcomes$") +public void check_more_outcomes() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Given("^I want to write a step with name(\\d+)$") +public void i_want_to_write_a_step_with_name(int arg1) throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^I check for the (\\d+) in step$") +public void i_check_for_the_in_step(int arg1) throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^I verify the success in step$") +public void i_verify_the_success_in_step() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^I verify the Fail in step$") +public void i_verify_the_Fail_in_step() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} +} \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/PkmstTest.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/PkmstTest.java new file mode 100644 index 00000000000..1e8bf880c41 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/PkmstTest.java @@ -0,0 +1,16 @@ +package com.prokarma.pkmst.cucumber; + +import org.junit.runner.RunWith; +import org.springframework.test.context.ActiveProfiles; +import cucumber.api.CucumberOptions; +import cucumber.api.junit.Cucumber; + +@RunWith(Cucumber.class) +@ActiveProfiles("test") +@CucumberOptions(format = { "pretty", "html:target/cucumber-html-report", + "json:./report/pet-report-json/pet.json", + "json:./report/store-report-json/store.json", + "json:./report/user-report-json/user.json", + }) +public class PkmstTest { +} \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/Pkmstpackage-info.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/Pkmstpackage-info.java new file mode 100644 index 00000000000..81caf63ebbb --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/Pkmstpackage-info.java @@ -0,0 +1,2 @@ +package com.prokarma.pkmst.cucumber; +//Implement the feature file steps in this package. \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/report/ExecuteReport.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/report/ExecuteReport.java new file mode 100644 index 00000000000..ed29f822512 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/report/ExecuteReport.java @@ -0,0 +1,64 @@ +package com.prokarma.pkmst.cucumber.report; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import net.masterthought.cucumber.Configuration; +import net.masterthought.cucumber.ReportBuilder; + +public class ExecuteReport { + + public static void main(String[] args) { + generateReport(); + } + + private static void generateReport() { + String buildNumber = "1"; + String projectName = "Spring-micro-sample"; + boolean runWithJenkins = false; + boolean parallelTesting = false; + + File reportOutputDirectory = null; + List jsonFiles = null; + Configuration configuration = null; + ReportBuilder reportBuilder = null; + reportOutputDirectory = new File("./report/pet-report-html/"); + jsonFiles = new ArrayList(); + jsonFiles.add("./report/pet-report-json/pet.json"); + + configuration = new Configuration(reportOutputDirectory,projectName); + // optionally only if you need + configuration.setParallelTesting(parallelTesting); + configuration.setRunWithJenkins(runWithJenkins); + configuration.setBuildNumber(buildNumber); + + reportBuilder = new ReportBuilder(jsonFiles, configuration); + reportBuilder.generateReports(); + reportOutputDirectory = new File("./report/store-report-html/"); + jsonFiles = new ArrayList(); + jsonFiles.add("./report/store-report-json/store.json"); + + configuration = new Configuration(reportOutputDirectory,projectName); + // optionally only if you need + configuration.setParallelTesting(parallelTesting); + configuration.setRunWithJenkins(runWithJenkins); + configuration.setBuildNumber(buildNumber); + + reportBuilder = new ReportBuilder(jsonFiles, configuration); + reportBuilder.generateReports(); + reportOutputDirectory = new File("./report/user-report-html/"); + jsonFiles = new ArrayList(); + jsonFiles.add("./report/user-report-json/user.json"); + + configuration = new Configuration(reportOutputDirectory,projectName); + // optionally only if you need + configuration.setParallelTesting(parallelTesting); + configuration.setRunWithJenkins(runWithJenkins); + configuration.setBuildNumber(buildNumber); + + reportBuilder = new ReportBuilder(jsonFiles, configuration); + reportBuilder.generateReports(); + + } +} \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/resources/application-test.properties b/samples/server/petstore/java-pkmst/src/test/resources/application-test.properties new file mode 100644 index 00000000000..4ef5c891798 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/resources/application-test.properties @@ -0,0 +1 @@ +server.port = 8081 diff --git a/samples/server/petstore/java-pkmst/src/test/resources/application.conf b/samples/server/petstore/java-pkmst/src/test/resources/application.conf new file mode 100644 index 00000000000..6a42f95f1fa --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/resources/application.conf @@ -0,0 +1,14 @@ +#################################### +# Akka Actor Config File # +#################################### + +akka { + scheduler { + tick-duration = 50ms + } +} + +url="http://localhost:8081" +noOfUsers=10 #Number of Users +deleteProductId=4 #Delete the Product by using productID +getProduct=2 #Get the Product \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/resources/application.properties b/samples/server/petstore/java-pkmst/src/test/resources/application.properties new file mode 100644 index 00000000000..4ef5c891798 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/resources/application.properties @@ -0,0 +1 @@ +server.port = 8081 diff --git a/samples/server/petstore/java-pkmst/src/test/resources/bootstrap.yml b/samples/server/petstore/java-pkmst/src/test/resources/bootstrap.yml new file mode 100644 index 00000000000..4f8e3532104 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/resources/bootstrap.yml @@ -0,0 +1,5 @@ +spring: + application: + name: pkmst-microservice + profiles: + active: test \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/resources/com/prokarma/pkmst/cucumber/Pkmst.feature b/samples/server/petstore/java-pkmst/src/test/resources/com/prokarma/pkmst/cucumber/Pkmst.feature new file mode 100644 index 00000000000..a22095793d4 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/resources/com/prokarma/pkmst/cucumber/Pkmst.feature @@ -0,0 +1,33 @@ +#Feature: List of scenarios. +#Scenario: Business rule through list of steps with arguments. +#Given: Some precondition step +#When: Some key actions +#Then: To observe outcomes or validation +#And,But: To enumerate more Given,When,Then steps +#Scenario Outline: List of steps for data-driven as an Examples and + +#Sample Feature Definition Template +@tag +Feature: Title of your feature + I want to use this template for my feature file + +@tag1 +Scenario: Title of your scenario +Given I want to write a step with precondition + And some other precondition +When I complete action + And some other action + And yet another action +Then I validate the outcomes + And check more outcomes + +@tag2 +Scenario Outline: Title of your scenario outline +Given I want to write a step with +When I check for the in step +Then I verify the in step + +Examples: + | name |value | status | + | name1 | 5 | success| + | name2 | 7 | Fail | \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/resources/gatling.conf b/samples/server/petstore/java-pkmst/src/test/resources/gatling.conf new file mode 100644 index 00000000000..c7b4fa7f8c8 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/resources/gatling.conf @@ -0,0 +1,157 @@ +######################### +# Gatling Configuration # +######################### + +# This file contains all the settings configurable for Gatling with their default values + +gatling { + core { + #outputDirectoryBaseName = "" # The prefix for each simulation result folder (then suffixed by the report generation timestamp) + #runDescription = "" # The description for this simulation run, displayed in each report + #encoding = "utf-8" # Encoding to use throughout Gatling for file and string manipulation + #simulationClass = "" # The FQCN of the simulation to run (when used in conjunction with noReports, the simulation for which assertions will be validated) + #mute = false # When set to true, don't ask for simulation name nor run description (currently only used by Gatling SBT plugin) + + extract { + regex { + #cacheMaxCapacity = 200 # Cache size for the compiled regexes, set to 0 to disable caching + } + xpath { + #cacheMaxCapacity = 200 # Cache size for the compiled XPath queries, set to 0 to disable caching + } + jsonPath { + #cacheMaxCapacity = 200 # Cache size for the compiled jsonPath queries, set to 0 to disable caching + #preferJackson = false # When set to true, prefer Jackson over Boon for JSON-related operations + jackson { + #allowComments = false # Allow comments in JSON files + #allowUnquotedFieldNames = false # Allow unquoted JSON fields names + #allowSingleQuotes = false # Allow single quoted JSON field names + } + + } + css { + #cacheMaxCapacity = 200 # Cache size for the compiled CSS selectors queries, set to 0 to disable caching + } + } + + timeOut { + #simulation = 8640000 # Absolute timeout, in seconds, of a simulation + } + directory { + #data = src/test/resource/data # Folder where user's data (e.g. files used by Feeders) is located + #bodies = src/test/resource/bodies # Folder where bodies are located + #simulations = user-src/test/java/simulations # Folder where the bundle's simulations are located< + #reportsOnly = "" # If set, name of report folder to look for in order to generate its report + #binaries = "" # If set, name of the folder where compiles classes are located: Defaults to GATLING_HOME/target. + #results = results # Name of the folder where all reports folder are located + } + } + charting { + #noReports = false # When set to true, don't generate HTML reports + #maxPlotPerSeries = 1000 # Number of points per graph in Gatling reports + #accuracy = 10 # Accuracy, in milliseconds, of the report's stats + indicators { + #lowerBound = 800 # Lower bound for the requests' response time to track in the reports and the console summary + #higherBound = 1200 # Higher bound for the requests' response time to track in the reports and the console summary + #percentile1 = 50 # Value for the 1st percentile to track in the reports, the console summary and GraphiteDataWriter + #percentile2 = 75 # Value for the 2nd percentile to track in the reports, the console summary and GraphiteDataWriter + #percentile3 = 95 # Value for the 3rd percentile to track in the reports, the console summary and GraphiteDataWriter + #percentile4 = 99 # Value for the 4th percentile to track in the reports, the console summary and GraphiteDataWriter + } + } + http { + #elFileBodiesCacheMaxCapacity = 200 # Cache size for request body EL templates, set to 0 to disable + #rawFileBodiesCacheMaxCapacity = 200 # Cache size for request body Raw templates, set to 0 to disable + #fetchedCssCacheMaxCapacity = 200 # Cache size for CSS parsed content, set to 0 to disable + #fetchedHtmlCacheMaxCapacity = 200 # Cache size for HTML parsed content, set to 0 to disable + #redirectPerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent redirects, set to 0 to disable + #expirePerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent 'Expire' headers, set to 0 to disable + #lastModifiedPerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent 'Last-Modified' headers, set to 0 to disable + #etagPerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent ETag headers, set to 0 to disable + #warmUpUrl = "http://gatling.io" # The URL to use to warm-up the HTTP stack (blank means disabled) + #enableGA = true # Very light Google Analytics, please support + ssl { + trustStore { + #type = "" # Type of SSLContext's TrustManagers store + #file = "" # Location of SSLContext's TrustManagers store + #password = "" # Password for SSLContext's TrustManagers store + #algorithm = "" # Algorithm used by SSLContext's TrustManagers store + } + keyStore { + #type = "" # Type of SSLContext's KeyManagers store + #file = "" # Location of SSLContext's KeyManagers store + #password = "" # Password for SSLContext's KeyManagers store + #algorithm = "" # Algorithm used SSLContext's KeyManagers store + } + } + ahc { + #allowPoolingConnections = true # Allow pooling HTTP connections (keep-alive header automatically added) + #allowPoolingSslConnections = true # Allow pooling HTTPS connections (keep-alive header automatically added) + #compressionEnforced = false # Enforce gzip/deflate when Accept-Encoding header is not defined + #connectTimeout = 60000 # Timeout when establishing a connection + #pooledConnectionIdleTimeout = 60000 # Timeout when a connection stays unused in the pool + #readTimeout = 60000 # Timeout when a used connection stays idle + #connectionTTL = -1 # Max duration a connection can stay open (-1 means no limit) + #ioThreadMultiplier = 2 # Number of Netty worker threads per core + #maxConnectionsPerHost = -1 # Max number of connections per host (-1 means no limit) + #maxConnections = -1 # Max number of connections (-1 means no limit) + #maxRetry = 2 # Number of times that a request should be tried again + #requestTimeout = 60000 # Timeout of the requests + #useProxyProperties = false # When set to true, supports standard Proxy System properties + #webSocketTimeout = 60000 # Timeout when a used websocket connection stays idle + #useRelativeURIsWithConnectProxies = true # When set to true, use relative URIs when talking with an SSL proxy or a WebSocket proxy + #acceptAnyCertificate = true # When set to true, doesn't validate SSL certificates + #httpClientCodecMaxInitialLineLength = 4096 # Maximum length of the initial line of the response (e.g. "HTTP/1.0 200 OK") + #httpClientCodecMaxHeaderSize = 8192 # Maximum size, in bytes, of each request's headers + #httpClientCodecMaxChunkSize = 8192 # Maximum length of the content or each chunk + #keepEncodingHeader = true # Don't drop Encoding response header after decoding + #webSocketMaxFrameSize = 10240 # Maximum frame payload size + #httpsEnabledProtocols = "" # Comma separated enabled protocols for HTTPS, if empty use the JDK defaults + #httpsEnabledCipherSuites = "" # Comma separated enabled cipher suites for HTTPS, if empty use the JDK defaults + #sslSessionCacheSize = 20000 # SSLSession cache size (set to 0 to disable) + #sslSessionTimeout = 86400 # SSLSession timeout (default is 24, like Hotspot) + } + } + data { + #writers = "console, file" # The lists of DataWriters to which Gatling write simulation data (currently supported : "console", "file", "graphite", "jdbc") + #reader = file # The DataReader used by the charting engine for reading simulation results + console { + #light = false # When set to true, displays a light version without detailed request stats + } + file { + #bufferSize = 8192 # FileDataWriter's internal data buffer size, in bytes + } + leak { + #noActivityTimeout = 30 # Period, in seconds, for which Gatling may have no activity before considering a leak may be happening + } + jdbc { + db { + #url = "jdbc:mysql://localhost:3306/temp" # The JDBC URL used by the JDBC DataWriter + #username = "root" # The database user used by the JDBC DataWriter + #password = "123123q" # The password for the specified user + } + #bufferSize = 20 # The size for each batch of SQL inserts to send to the database + create { + #createRunRecordTable = "CREATE TABLE IF NOT EXISTS `RunRecords` ( `id` INT NOT NULL AUTO_INCREMENT , `runDate` DATETIME NULL , `simulationId` VARCHAR(45) NULL , `runDescription` VARCHAR(45) NULL , PRIMARY KEY (`id`) )" + #createRequestRecordTable = "CREATE TABLE IF NOT EXISTS `RequestRecords` (`id` int(11) NOT NULL AUTO_INCREMENT, `runId` int DEFAULT NULL, `scenario` varchar(45) DEFAULT NULL, `userId` VARCHAR(30) NULL, `name` varchar(50) DEFAULT NULL, `requestStartDate` bigint DEFAULT NULL, `requestEndDate` bigint DEFAULT NULL, `responseStartDate` bigint DEFAULT NULL, `responseEndDate` bigint DEFAULT NULL, `status` varchar(2) DEFAULT NULL, `message` varchar(4500) DEFAULT NULL, `responseTime` bigint DEFAULT NULL, PRIMARY KEY (`id`) )" + #createScenarioRecordTable = "CREATE TABLE IF NOT EXISTS `ScenarioRecords` (`id` int(11) NOT NULL AUTO_INCREMENT, `runId` int DEFAULT NULL, `scenarioName` varchar(45) DEFAULT NULL, `userId` VARCHAR(30) NULL, `event` varchar(50) DEFAULT NULL, `startDate` bigint DEFAULT NULL, `endDate` bigint DEFAULT NULL, PRIMARY KEY (`id`) )" + #createGroupRecordTable = "CREATE TABLE IF NOT EXISTS `GroupRecords` (`id` int(11) NOT NULL AUTO_INCREMENT, `runId` int DEFAULT NULL, `scenarioName` varchar(45) DEFAULT NULL, `userId` VARCHAR(30) NULL, `entryDate` bigint DEFAULT NULL, `exitDate` bigint DEFAULT NULL, `status` varchar(2) DEFAULT NULL, PRIMARY KEY (`id`) )" + } + insert { + #insertRunRecord = "INSERT INTO RunRecords (runDate, simulationId, runDescription) VALUES (?,?,?)" + #insertRequestRecord = "INSERT INTO RequestRecords (runId, scenario, userId, name, requestStartDate, requestEndDate, responseStartDate, responseEndDate, status, message, responseTime) VALUES (?,?,?,?,?,?,?,?,?,?,?)" + #insertScenarioRecord = "INSERT INTO ScenarioRecords (runId, scenarioName, userId, event, startDate, endDate) VALUES (?,?,?,?,?,?)" + #insertGroupRecord = "INSERT INTO GroupRecords (runId, scenarioName, userId, entryDate, exitDate, status) VALUES (?,?,?,?,?,?)" + } + } + graphite { + #light = false # only send the all* stats + #host = "localhost" # The host where the Carbon server is located + #port = 2003 # The port to which the Carbon server listens to + #protocol = "tcp" # The protocol used to send data to Carbon (currently supported : "tcp", "udp") + #rootPathPrefix = "gatling" # The common prefix of all metrics sent to Graphite + #bufferSize = 8192 # GraphiteDataWriter's internal data buffer size, in bytes + #writeInterval = 1 # GraphiteDataWriter's write interval, in seconds + } + } +} diff --git a/samples/server/petstore/java-pkmst/src/test/scala/scalaFiles/testapi.scala b/samples/server/petstore/java-pkmst/src/test/scala/scalaFiles/testapi.scala new file mode 100644 index 00000000000..11ee5bfda1d --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/scala/scalaFiles/testapi.scala @@ -0,0 +1,41 @@ +# Sample gatling test for Get Product. Please implement likewise for your API. +import scala.concurrent.duration._ + +import io.gatling.core.Predef._ +import io.gatling.http.Predef._ +import io.gatling.jdbc.Predef._ +import com.typesafe.config._ +import org.springframework.boot.SpringApplication +import org.springframework.context.ConfigurableApplicationContext + + +class get extends Simulation { + + + val app: ConfigurableApplicationContext = SpringApplication.run(classOf[com.prokarma.pkmst.PkmstApplication]) + Runtime.getRuntime.addShutdownHook(new Thread() { + override def run(): Unit = app.stop() + }) + + val conf = ConfigFactory.load() + val baseUrl = conf.getString("url") + val noOfUsers: Int = conf.getInt("noOfUsers") + val httpProtocol = http + .baseURL(baseUrl) + .inferHtmlResources() + .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8") + .acceptEncodingHeader("gzip, deflate, sdch") + .acceptLanguageHeader("en-US,en;q=0.8") + .userAgentHeader("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36") + + val headers_0 = Map( + "Cache-Control" -> "max-age=0", + "Upgrade-Insecure-Requests" -> "1") + + val scn = scenario("getProduct") + .exec(http("request_0") + .get("/") + .headers(headers_0)) + + setUp(scn.inject(atOnceUsers(noOfUsers))).protocols(httpProtocol) +} \ No newline at end of file