You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ni...@apache.org on 2019/06/21 07:09:18 UTC

[servicecomb-toolkit] 02/49: initial version.Support for generating ServiceComb code that used Springmvc model.

This is an automated email from the ASF dual-hosted git repository.

ningjiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-toolkit.git

commit bfa5bd740a5263bffef468eed493fb1a56f7aa87
Author: MabinGo <bi...@huawei.com>
AuthorDate: Thu May 16 21:31:32 2019 +0800

    initial version.Support for generating ServiceComb code that used Springmvc model.
    
    Signed-off-by: MabinGo <bi...@huawei.com>
---
 .gitignore                                         |  86 ++++++++++++
 code-generator/pom.xml                             |  69 +++++++++
 .../servicecomb/toolkit/codegen/CodeGenerator.java |  30 ++++
 .../toolkit/codegen/DefaultCodeGenerator.java      |  41 ++++++
 .../codegen/ServiceCombProviderCodegen.java        | 155 +++++++++++++++++++++
 .../services/io.swagger.codegen.CodegenConfig      |  18 +++
 .../resources/ServiceCombProvider/README.mustache  |  20 +++
 .../ServiceCombProvider/enumClass.mustache         |  43 ++++++
 .../ServiceCombProvider/enumOuterClass.mustache    |  37 +++++
 .../generatedAnnotation.mustache                   |   1 +
 .../libraries/SpringMvc/Application.mustache       |  28 ++++
 .../libraries/SpringMvc/api.mustache               |  42 ++++++
 .../libraries/SpringMvc/api_test.mustache          | 102 ++++++++++++++
 .../libraries/SpringMvc/bodyParams.mustache        |   1 +
 .../libraries/SpringMvc/formParams.mustache        |   2 +
 .../libraries/SpringMvc/headerParams.mustache      |   1 +
 .../libraries/SpringMvc/pathParams.mustache        |   1 +
 .../libraries/SpringMvc/pom.mustache               | 104 ++++++++++++++
 .../libraries/SpringMvc/queryParams.mustache       |   1 +
 .../resources/ServiceCombProvider/log4j2.mustache  |  41 ++++++
 .../ServiceCombProvider/microservice.mustache      |  43 ++++++
 .../resources/ServiceCombProvider/model.mustache   |  27 ++++
 .../resources/ServiceCombProvider/pojo.mustache    | 134 ++++++++++++++++++
 .../ServiceCombProvider/returnTypes.mustache       |   1 +
 .../typeInfoAnnotation.mustache                    |   7 +
 .../ServiceCombProvider/xmlAnnotation.mustache     |   6 +
 pom.xml                                            |  40 ++++++
 toolkit-cli/dependency-reduced-pom.xml             |  64 +++++++++
 toolkit-cli/pom.xml                                | 102 ++++++++++++++
 .../servicecomb/toolkit/cli/CodeGenerate.java      | 114 +++++++++++++++
 .../servicecomb/toolkit/cli/ToolkitMain.java       |  58 ++++++++
 .../src/main/resources/application.properties      |   1 +
 32 files changed, 1420 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100755
index 0000000..e396f22
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,86 @@
+# Output Directory
+target/
+
+# C pre-compile
+*.gch
+*.pch
+
+# C compile
+*.a
+*.o
+*.ko
+*.la
+*.lo
+*.obj
+*.elf
+*.so
+*.so.*
+*.dylib
+*.exe
+*.lib
+*.dll
+*.out
+*.app
+*.hex
+
+# Debug files
+*.dSYM/
+
+# Java
+*.class
+
+# Java Package Files
+*.jar
+*.war
+*.ear
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+# Zip Files
+*.rar
+*.zip
+*.7z
+*.tar
+*.gz
+
+# Ant
+build/
+
+# Compiled Python
+__pycache__/
+*.py[cod]
+*py.class
+
+# Eclipse
+.settings/
+.classpath
+.project
+
+# IntelliJ, based on http://devnet.jetbrains.net/docs/DOC-1186
+.idea/
+*.iml
+*.ipr
+*.iws
+
+# logs and trace
+*.log
+*.trace
+*.dat
+
+# vi swap
+*.swp
+
+# Backup Files
+*.bak
+*.old
+
+# SVN metadata
+.svn/
+
+# Mac
+.DS_Store
+
+# gradle
+.gradle
+
diff --git a/code-generator/pom.xml b/code-generator/pom.xml
new file mode 100755
index 0000000..9866719
--- /dev/null
+++ b/code-generator/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>toolkit</artifactId>
+    <groupId>org.apache.servicecomb</groupId>
+    <version>0.1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>code-generator</artifactId>
+
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <swagger-codegen-version>2.4.3</swagger-codegen-version>
+    <maven-plugin-version>1.0.0</maven-plugin-version>
+    <junit-version>4.8.1</junit-version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>io.swagger</groupId>
+      <artifactId>swagger-codegen</artifactId>
+      <version>${swagger-codegen-version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.6.1</version>
+        <configuration>
+          <source>8</source>
+          <target>8</target>
+        </configuration>
+      </plugin>
+    </plugins>
+
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+        <includes>
+          <include>**/*.*</include>
+        </includes>
+      </resource>
+    </resources>
+  </build>
+</project>
diff --git a/code-generator/src/main/java/org/apache/servicecomb/toolkit/codegen/CodeGenerator.java b/code-generator/src/main/java/org/apache/servicecomb/toolkit/codegen/CodeGenerator.java
new file mode 100755
index 0000000..2ac18c5
--- /dev/null
+++ b/code-generator/src/main/java/org/apache/servicecomb/toolkit/codegen/CodeGenerator.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.toolkit.codegen;
+
+import java.io.File;
+import java.util.List;
+
+import io.swagger.codegen.config.CodegenConfigurator;
+
+public interface CodeGenerator {
+
+  CodeGenerator opts(CodegenConfigurator opts);
+
+  List<File> generate();
+}
diff --git a/code-generator/src/main/java/org/apache/servicecomb/toolkit/codegen/DefaultCodeGenerator.java b/code-generator/src/main/java/org/apache/servicecomb/toolkit/codegen/DefaultCodeGenerator.java
new file mode 100755
index 0000000..459cf56
--- /dev/null
+++ b/code-generator/src/main/java/org/apache/servicecomb/toolkit/codegen/DefaultCodeGenerator.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.toolkit.codegen;
+
+import java.io.File;
+import java.util.List;
+
+import io.swagger.codegen.DefaultGenerator;
+import io.swagger.codegen.config.CodegenConfigurator;
+
+public class DefaultCodeGenerator implements CodeGenerator {
+
+  private DefaultGenerator generator = new DefaultGenerator();
+
+  @Override
+  public CodeGenerator opts(CodegenConfigurator opts) {
+
+    generator.opts(opts.toClientOptInput());
+    return this;
+  }
+
+  @Override
+  public List<File> generate() {
+    return generator.generate();
+  }
+}
diff --git a/code-generator/src/main/java/org/apache/servicecomb/toolkit/codegen/ServiceCombProviderCodegen.java b/code-generator/src/main/java/org/apache/servicecomb/toolkit/codegen/ServiceCombProviderCodegen.java
new file mode 100755
index 0000000..25b345f
--- /dev/null
+++ b/code-generator/src/main/java/org/apache/servicecomb/toolkit/codegen/ServiceCombProviderCodegen.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.toolkit.codegen;
+
+import java.io.File;
+import java.util.Map;
+
+import io.swagger.codegen.CliOption;
+import io.swagger.codegen.CodegenConfig;
+import io.swagger.codegen.CodegenConstants;
+import io.swagger.codegen.CodegenType;
+import io.swagger.codegen.SupportingFile;
+import io.swagger.codegen.languages.AbstractJavaCodegen;
+import io.swagger.codegen.languages.SpringCodegen;
+import io.swagger.codegen.mustache.CamelCaseLambda;
+
+public class ServiceCombProviderCodegen extends AbstractJavaCodegen implements CodegenConfig {
+
+  private static final String DEFAULT_LIBRARY = "SpringMvc";
+
+  private String resourcesFolder = projectFolder + File.separator + "resources";
+
+  private String apiVersion = "1.0.0";
+
+  private String mainClassPackage;
+
+
+  @Override
+  public CodegenType getTag() {
+    return CodegenType.SERVER;
+  }
+
+  @Override
+  public String getName() {
+    return "ServiceCombProvider";
+  }
+
+  @Override
+  public String getHelp() {
+    return "Generates a ServiceComb server library.";
+  }
+
+  public ServiceCombProviderCodegen() {
+    super();
+
+    outputFolder = "generated-code/ServiceCombProvider";
+
+    modelDocTemplateFiles.remove("model_doc.mustache");
+    apiDocTemplateFiles.remove("api_doc.mustache");
+    apiTestTemplateFiles.remove("api_test.mustache");
+
+    embeddedTemplateDir = templateDir = "ServiceCombProvider";
+
+    apiPackage = "servicecomb.example.controller";
+
+    modelPackage = "servicecomb.example.model";
+
+    mainClassPackage = "servicecomb.example";
+
+    groupId = "org.apache.servicecomb";
+    artifactId = "demo";
+
+    supportedLibraries.put(DEFAULT_LIBRARY, "ServiceComb Server application using the springboot programming model.");
+
+    setLibrary(DEFAULT_LIBRARY);
+
+    CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
+    library.setDefault(DEFAULT_LIBRARY);
+    library.setEnum(supportedLibraries);
+    library.setDefault(DEFAULT_LIBRARY);
+    cliOptions.add(library);
+  }
+
+  @Override
+  public void processOpts() {
+
+    super.processOpts();
+
+    importMapping.put("OffsetDateTime", "java.time.OffsetDateTime");
+    additionalProperties.put("dateLibrary", "java8");
+    additionalProperties.put("jackson", "true");
+    additionalProperties.put("apiVersion", apiVersion);
+    additionalProperties.put("mainClassPackage", mainClassPackage);
+    additionalProperties.put("camelcase", new CamelCaseLambda());
+
+    supportingFiles.add(new SupportingFile("pom.mustache",
+        "",
+        "pom.xml")
+    );
+    supportingFiles.add(new SupportingFile("README.mustache",
+        "",
+        "README.md")
+    );
+
+    supportingFiles.add(new SupportingFile("Application.mustache",
+        mainClassFolder(),
+        "Application.java")
+    );
+
+    supportingFiles.add(new SupportingFile("log4j2.mustache",
+        resourcesFolder,
+        "log4j2.xml")
+    );
+    supportingFiles.add(new SupportingFile("microservice.mustache",
+        resourcesFolder,
+        "microservice.yaml")
+    );
+  }
+
+  @Override
+  public Map<String, Object> postProcessModelsEnum(Map<String, Object> objs) {
+    objs = super.postProcessModelsEnum(objs);
+    SpringCodegen springCodegen = new SpringCodegen();
+    return springCodegen.postProcessModelsEnum(objs);
+  }
+
+  @Override
+  public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
+    SpringCodegen springCodegen = new SpringCodegen();
+    return springCodegen.postProcessOperations(objs);
+  }
+
+  @Override
+  public String toApiName(String name) {
+    if (name.length() == 0) {
+      return "DefaultController";
+    }
+
+    String apiName = (String) additionalProperties.get("apiName");
+    if (apiName != null) {
+      return apiName;
+    }
+
+    return initialCaps(name) + "Controller";
+  }
+
+  private String mainClassFolder() {
+    return sourceFolder + File.separator + mainClassPackage.replace(".", File.separator);
+  }
+}
\ No newline at end of file
diff --git a/code-generator/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig b/code-generator/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig
new file mode 100755
index 0000000..9e194db
--- /dev/null
+++ b/code-generator/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+org.apache.servicecomb.toolkit.codegen.ServiceCombProviderCodegen
diff --git a/code-generator/src/main/resources/ServiceCombProvider/README.mustache b/code-generator/src/main/resources/ServiceCombProvider/README.mustache
new file mode 100755
index 0000000..2258a49
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/README.mustache
@@ -0,0 +1,20 @@
+## Welcome to use ServiceComb Java Chassis
+This project(module) is generate by *org.apache.servicecomb.archetypes:business-service-springmvc-archetype*, it use **springmvc provider** to develop service producer.
+
+### More works can be done further:
+1. Modify "HelloImpl", add your business service logic, or create some new producers to provide your services. More details can be found : http://servicecomb.apache.org/users/develop-with-springmvc/
+2. Modify "microservice.yaml", change APPLICATION_ID, service_description.name, version, and service center address, endpoints publish address etc. More details can be found : http://servicecomb.apache.org/users/service-definition/
+3. Modify setting value of "mainClass" in pom.xml for package.
+
+### Package your service
+Under project(module) root folder, run
+```bash
+mvn package
+```
+Then you can get outputs in target folder:
+- lib : contains all dependencies jars
+- xxxxxx-{version}.jar
+```bash
+java -jar xxxxxx-{version}.jar
+```
+*Notice: If you need to modify config setting in "microservice.yaml" like service center address but don't want repackage the executable jar, **you can direct place a new "microservice.yaml" file in same folder, then settings will be overridden.***
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/enumClass.mustache b/code-generator/src/main/resources/ServiceCombProvider/enumClass.mustache
new file mode 100755
index 0000000..dfdada5
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/enumClass.mustache
@@ -0,0 +1,43 @@
+  /**
+   * {{^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
+    public String toString() {
+      return String.valueOf(value);
+    }
+
+    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;
+    }
+  }
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/enumOuterClass.mustache b/code-generator/src/main/resources/ServiceCombProvider/enumOuterClass.mustache
new file mode 100755
index 0000000..a5f0034
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/enumOuterClass.mustache
@@ -0,0 +1,37 @@
+
+/**
+ * {{^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
+  public String toString() {
+    return String.valueOf(value);
+  }
+
+  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;
+  }
+}
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/generatedAnnotation.mustache b/code-generator/src/main/resources/ServiceCombProvider/generatedAnnotation.mustache
new file mode 100755
index 0000000..49110fc
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/generatedAnnotation.mustache
@@ -0,0 +1 @@
+@javax.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}")
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/Application.mustache b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/Application.mustache
new file mode 100755
index 0000000..aef3762
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/Application.mustache
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {{mainClassPackage}};
+
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+
+public class Application {
+
+  public static void main(String[] args) throws Exception {
+    System.setProperty("local.registry.file", "notExistJustForceLocal");
+    BeanUtils.init();
+  }
+}
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/api.mustache b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/api.mustache
new file mode 100755
index 0000000..d303827
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/api.mustache
@@ -0,0 +1,42 @@
+package {{apiPackage}};
+
+import {{modelPackage}}.*;
+
+{{#imports}}import {{import}};
+{{/imports}}
+
+import org.springframework.http.HttpStatus;
+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 org.apache.servicecomb.provider.rest.common.RestSchema;
+import java.util.List;
+import java.util.Map;
+import static org.springframework.http.MediaType.*;
+
+@RestSchema(schemaId = "{{#camelcase}}{{classname}}{{/camelcase}}")
+@RequestMapping(value = "/", produces = {APPLICATION_JSON_VALUE})
+{{>generatedAnnotation}}
+{{#operations}}
+public class {{classname}} {
+  {{#operation}}
+
+  @RequestMapping(value = "{{path}}",
+    {{#hasProduces}}produces = { {{#produces}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }, {{/hasProduces}}
+    {{#hasConsumes}}consumes = { {{#consumes}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} },{{/hasConsumes}}
+    method = RequestMethod.{{httpMethod}})
+  public ResponseEntity<{{>returnTypes}}> {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},
+    {{/hasMore}}{{/allParams}}) {
+      // do some magic!
+      return new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK);
+  }
+
+  {{/operation}}
+}
+{{/operations}}
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/api_test.mustache b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/api_test.mustache
new file mode 100755
index 0000000..1633203
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/api_test.mustache
@@ -0,0 +1,102 @@
+package {{package}};
+{{#imports}}import {{import}};
+{{/imports}}
+import java.util.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import static org.junit.Assert.assertEquals;
+
+public class {{classname}}ContractTest {
+    @Autowired
+    private {{classname}} api;
+
+    private static final String NAME_LARRY_JSON = "{\"name\": \"larry\"}";
+
+    @Rule
+    public TestFailureProviderRule mockTestProvider = new TestFailureProviderRule("{{#camelcase}}{{classname}}{{/camelcase}}Provider", this);
+
+    @Pact(provider="{{#camelcase}}{{classname}}{{/camelcase}}Provider", consumer="{{#camelcase}}{{classname}}{{/camelcase}}Consumer")
+    public RequestResponsePact createFragment(PactDslWithProvider builder) {
+
+{{#operations}}
+    {{#operation}}
+        {{#hasHeaderParams}}
+                Map<String, String> {{operationId}}RequestHeaders = new HashMap<String, String>();
+        {{/hasHeaderParams}}
+    {{/operation}}
+{{/operations}}
+{{#operations}}
+    {{#operation}}
+        {{#responseHeaders}}
+                Map<String, String> {{operationId}}ResponseHeaders = new HashMap<String, String>();
+        {{/responseHeaders}}
+    {{/operation}}
+{{/operations}}
+
+        return builder
+{{#operations}}
+    {{#operation}}
+            .uponReceiving("{{summary}}")
+                .path("{{path}}")
+                .method("{{httpMethod}}")
+                {{#hasHeaderParams}}
+                .headers({{operationId}}RequestHeaders)
+                {{/hasHeaderParams}}
+            .willRespondWith()
+                .status(200)
+                {{#responseHeaders}}
+                .headers({{operationId}}ResponseHeaders)
+                {{/responseHeaders}}
+                .body("{\"responsetest\": true, \"name\": \"harry\"}")
+    {{/operation}}
+{{/operations}}
+            .toPact();
+    }
+
+
+    @Test
+    @PactVerification({"{{#camelcase}}{{classname}}{{/camelcase}}Provider"})
+    public void allPass() throws IOException {
+      mockTestProvider.validateResultWith((result, t) -> {
+        assertThat(t, is(nullValue()));
+        assertThat(result, is(PactVerificationResult.Ok.INSTANCE));
+      });
+      doTest("/", NAME_LARRY_JSON);
+    }
+
+    private void doTest(String path, String json) throws IOException {
+      ConsumerClient consumerClient = new ConsumerClient(mockTestProvider.getUrl());
+      consumerClient.options("/second");
+      try {
+        consumerClient.getAsMap(path, "");
+      } catch (IOException e) {
+      }
+      try {
+        new ConsumerClient(mockTestProvider2.getUrl()).putAsMap("/", json);
+      } catch (IOException e) {
+      }
+    }
+
+/*
+        @Test
+        public void {{operationId}}Test() throws Exception {
+        {{#allParams}}
+        {{^isFile}}
+            {{{dataType}}} {{paramName}} = {{{example}}};
+        {{/isFile}}
+        {{#isFile}}
+            org.springframework.web.multipart.MultipartFile {{paramName}} = null;
+        {{/isFile}}
+        {{/allParams}}
+            ResponseEntity<{{>returnTypes}}> responseEntity = api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
+            assertEquals(HttpStatus.NOT_IMPLEMENTED, responseEntity.getStatusCode());
+        }
+*/
+}
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/bodyParams.mustache b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/bodyParams.mustache
new file mode 100755
index 0000000..5932bd1
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/bodyParams.mustache
@@ -0,0 +1 @@
+{{#isBodyParam}}@RequestBody {{{dataType}}} {{paramName}}{{/isBodyParam}}
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/formParams.mustache b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/formParams.mustache
new file mode 100755
index 0000000..336c14d
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/formParams.mustache
@@ -0,0 +1,2 @@
+{{#isFormParam}}{{#notFile}}
+@RequestPart(value="{{paramName}}"{{#required}}, required=true{{/required}}{{^required}}, required=false{{/required}})  {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}@RequestPart("file") MultipartFile {{baseName}}{{/isFile}}{{/isFormParam}}
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/headerParams.mustache b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/headerParams.mustache
new file mode 100755
index 0000000..7c3018b
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/headerParams.mustache
@@ -0,0 +1 @@
+{{#isHeaderParam}}@RequestHeader(value="{{paramName}}", required={{#required}}true{{/required}}{{^required}}false{{/required}}) {{{dataType}}} {{paramName}}{{/isHeaderParam}}
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/pathParams.mustache b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/pathParams.mustache
new file mode 100755
index 0000000..5152be0
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/pathParams.mustache
@@ -0,0 +1 @@
+{{#isPathParam}}@PathVariable("{{paramName}}") {{{dataType}}} {{paramName}}{{/isPathParam}}
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/pom.mustache b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/pom.mustache
new file mode 100755
index 0000000..c119ee1
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/pom.mustache
@@ -0,0 +1,104 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>{{groupId}}</groupId>
+  <artifactId>{{artifactId}}</artifactId>
+  <packaging>jar</packaging>
+  <name>{{artifactId}}</name>
+  <version>{{artifactVersion}}</version>
+
+  <properties>
+      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+      <java-chassis.version>1.2.0</java-chassis.version>
+  </properties>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.apache.servicecomb</groupId>
+        <artifactId>java-chassis-dependencies</artifactId>
+        <version>${java-chassis.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>transport-rest-vertx</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>transport-highway</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>provider-springmvc</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-slf4j-impl</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+    </dependency>
+
+  </dependencies>
+
+  <!--for package and deploy-->
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <version>2.6</version>
+        <configuration>
+          <archive>
+            <manifest>
+              <addClasspath>true</addClasspath>
+              <classpathPrefix>lib/</classpathPrefix>
+              <!--change to your main class-->
+              <mainClass>${package}.Application</mainClass>
+            </manifest>
+            <manifestEntries>
+              <Class-Path>. </Class-Path>
+            </manifestEntries>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>copy-dependencies</id>
+            <phase>package</phase>
+            <goals>
+              <goal>copy-dependencies</goal>
+            </goals>
+            <configuration>
+              <outputDirectory>target/lib</outputDirectory>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.1</version>
+        <configuration>
+          <source>1.8</source>
+          <target>1.8</target>
+        </configuration>
+      </plugin>
+
+    </plugins>
+  </build>
+
+</project>
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/queryParams.mustache b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/queryParams.mustache
new file mode 100755
index 0000000..6ce8e14
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/libraries/SpringMvc/queryParams.mustache
@@ -0,0 +1 @@
+{{#isQueryParam}}@RequestParam(value = "{{paramName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) {{{dataType}}} {{paramName}}{{/isQueryParam}}
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/log4j2.mustache b/code-generator/src/main/resources/ServiceCombProvider/log4j2.mustache
new file mode 100755
index 0000000..e43e15b
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/log4j2.mustache
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!--this is sample configuration, please modify as your wish-->
+<configuration>
+  <Properties>
+    <Property name="log_path">./target/log</Property>
+  </Properties>
+
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n"/>
+    </Console>
+    <RollingFile name="DailyRollingFile" fileName="${log_path}/output.log"
+      filePattern="${log_path}/%d{yyyy-MM-dd}.log">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n"/>
+      <TimeBasedTriggeringPolicy interval="1"/>
+    </RollingFile>
+  </Appenders>
+  <Loggers>
+    <Root level="info">
+      <AppenderRef ref="Console"/>
+      <AppenderRef ref="DailyRollingFile"/>
+    </Root>
+  </Loggers>
+</configuration>
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/microservice.mustache b/code-generator/src/main/resources/ServiceCombProvider/microservice.mustache
new file mode 100755
index 0000000..67ad88a
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/microservice.mustache
@@ -0,0 +1,43 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+#More details can be found :
+# 1.http://servicecomb.apache.org/users/service-definition/
+# 2.http://servicecomb.apache.org/users/service-configurations/
+# 3.http://servicecomb.apache.org/users/communicate-protocol/
+
+#Indicates an application name
+APPLICATION_ID: business
+service_description:
+#Indicates a microservice name
+#The microservice name should be unique within an application.
+#The name can contain digits, uppercase and lowercase letters, hyphens(-), underscores(_), and periods(.); and can neither start nor end with punctuations.
+#The naming rule is as follows: ^[a-zA-Z0-9]+$|^[a-zA-Z0-9][a-zA-Z0-9_-.]*[a-zA-Z0-9]$.
+  name: business-service
+#Indicates a service version
+  version: 1.0.0
+servicecomb:
+  service:
+  #Specifies the service center IP address.
+    registry:
+      address: http://127.0.0.1:30100
+  #Specifies the rest transport listening IP address.
+  rest:
+    address: 0.0.0.0:8080
+  #Specifies the highway transport listening IP address.
+  highway:
+    address: 0.0.0.0:7070
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/model.mustache b/code-generator/src/main/resources/ServiceCombProvider/model.mustache
new file mode 100755
index 0000000..1923ac6
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/model.mustache
@@ -0,0 +1,27 @@
+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}}
+{{#withXml}}
+import javax.xml.bind.annotation.*;
+{{/withXml}}
+
+{{#models}}
+{{#model}}
+{{#isEnum}}
+{{>enumOuterClass}}
+{{/isEnum}}
+{{^isEnum}}
+{{>pojo}}
+{{/isEnum}}
+{{/model}}
+{{/models}}
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/pojo.mustache b/code-generator/src/main/resources/ServiceCombProvider/pojo.mustache
new file mode 100755
index 0000000..5c3f7f3
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/pojo.mustache
@@ -0,0 +1,134 @@
+/**
+ * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/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}}
+  {{#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}}
+{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}}  public {{{datatypeWithEnum}}} {{#isBoolean}}is{{/isBoolean}}{{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    ");
+  }
+}
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/returnTypes.mustache b/code-generator/src/main/resources/ServiceCombProvider/returnTypes.mustache
new file mode 100755
index 0000000..63acd6f
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/returnTypes.mustache
@@ -0,0 +1 @@
+{{#returnContainer}}{{#isMapContainer}}Map<String, {{{returnType}}}>{{/isMapContainer}}{{#isListContainer}}List<{{returnType}}>{{/isListContainer}}{{/returnContainer}}{{^returnContainer}}{{{returnType}}}{{/returnContainer}}
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/typeInfoAnnotation.mustache b/code-generator/src/main/resources/ServiceCombProvider/typeInfoAnnotation.mustache
new file mode 100755
index 0000000..09be1ca
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/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}}
\ No newline at end of file
diff --git a/code-generator/src/main/resources/ServiceCombProvider/xmlAnnotation.mustache b/code-generator/src/main/resources/ServiceCombProvider/xmlAnnotation.mustache
new file mode 100755
index 0000000..03586da
--- /dev/null
+++ b/code-generator/src/main/resources/ServiceCombProvider/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
new file mode 100755
index 0000000..ca48b94
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.servicecomb</groupId>
+  <artifactId>toolkit</artifactId>
+  <version>0.1.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <name>Microservice development toolkit</name>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <modules>
+    <module>code-generator</module>
+    <module>toolkit-cli</module>
+  </modules>
+
+</project>
diff --git a/toolkit-cli/dependency-reduced-pom.xml b/toolkit-cli/dependency-reduced-pom.xml
new file mode 100644
index 0000000..33bd7aa
--- /dev/null
+++ b/toolkit-cli/dependency-reduced-pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <artifactId>toolkit</artifactId>
+    <groupId>org.apache.servicecomb</groupId>
+    <version>0.1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>toolkit-cli</artifactId>
+  <build>
+    <resources>
+      <resource>
+        <filtering>true</filtering>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.1</version>
+        <configuration>
+          <source>1.8</source>
+          <target>1.8</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-shade-plugin</artifactId>
+        <version>2.4.1</version>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+            <configuration>
+              <filters>
+                <filter>
+                  <artifact>*:*</artifact>
+                  <excludes>
+                    <exclude>META-INF/*.SF</exclude>
+                    <exclude>META-INF/*.DSA</exclude>
+                    <exclude>META-INF/*.RSA</exclude>
+                  </excludes>
+                </filter>
+              </filters>
+              <transformers>
+                <transformer>
+                  <mainClass>org.apache.servicecomb.toolkit.cli.ToolkitMain</mainClass>
+                </transformer>
+                <transformer>
+                  <resource>META-INF/spring.handlers</resource>
+                </transformer>
+                <transformer>
+                  <resource>META-INF/spring.schemas</resource>
+                </transformer>
+              </transformers>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
+
diff --git a/toolkit-cli/pom.xml b/toolkit-cli/pom.xml
new file mode 100755
index 0000000..570dde4
--- /dev/null
+++ b/toolkit-cli/pom.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>toolkit</artifactId>
+    <groupId>org.apache.servicecomb</groupId>
+    <version>0.1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>toolkit-cli</artifactId>
+
+  <dependencies>
+    <dependency>
+      <groupId>io.airlift</groupId>
+      <artifactId>airline</artifactId>
+      <version>0.7</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>code-generator</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.1</version>
+        <configuration>
+          <source>1.8</source>
+          <target>1.8</target>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <version>2.4.1</version>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+            <configuration>
+              <filters>
+                <filter>
+                  <artifact>*:*</artifact>
+                  <excludes>
+                    <exclude>META-INF/*.SF</exclude>
+                    <exclude>META-INF/*.DSA</exclude>
+                    <exclude>META-INF/*.RSA</exclude>
+                  </excludes>
+                </filter>
+              </filters>
+              <transformers>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                  <mainClass>org.apache.servicecomb.toolkit.cli.ToolkitMain</mainClass>
+                </transformer>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                  <resource>META-INF/spring.handlers</resource>
+                </transformer>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                  <resource>META-INF/spring.schemas</resource>
+                </transformer>
+              </transformers>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+        <filtering>true</filtering>
+      </resource>
+    </resources>
+  </build>
+</project>
diff --git a/toolkit-cli/src/main/java/org/apache/servicecomb/toolkit/cli/CodeGenerate.java b/toolkit-cli/src/main/java/org/apache/servicecomb/toolkit/cli/CodeGenerate.java
new file mode 100755
index 0000000..c9506ce
--- /dev/null
+++ b/toolkit-cli/src/main/java/org/apache/servicecomb/toolkit/cli/CodeGenerate.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.toolkit.cli;
+
+import static org.apache.commons.lang3.StringUtils.isNotEmpty;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+
+import org.apache.servicecomb.toolkit.codegen.DefaultCodeGenerator;
+
+import io.airlift.airline.Command;
+import io.airlift.airline.Option;
+import io.swagger.codegen.config.CodegenConfigurator;
+
+@Command(name = "generate", description = "CodeGenerate code with chosen lang")
+public class CodeGenerate implements Runnable {
+
+  @Option(name = {"--programming-model"}, title = "programming model", required = false,
+      description = "programming model, equals to --library")
+  private String programmingModel;
+
+  @Option(name = {"-i", "--input-spec"}, title = "spec file", required = true,
+      description = "location of the swagger spec, as URL or file (required)")
+  private String spec;
+
+  @Option(name = {"-o", "--output"}, title = "output directory",
+      description = "where to write the generated files (current dir by default)")
+  private String output = "";
+
+  @Option(name = {"--group-id"}, title = "group id", description = "groupId in generated pom.xml")
+  private String groupId;
+
+  @Option(name = {"--artifact-id"}, title = "artifact id",
+      description = "artifact version in generated pom.xml")
+  private String artifactId;
+
+  @Option(name = {"--artifact-version"}, title = "artifact version",
+      description = "artifact version in generated pom.xml")
+  private String artifactVersion;
+
+  @Option(name = {"--library"}, title = "library", description = "library template (sub-template)")
+  private String library;
+
+  @Option(name = {"-l", "--lang"}, title = "language",
+      description = "client language to generate (maybe class name in classpath, required)")
+  private String lang = "ServiceCombProvider";
+
+
+  @Override
+  public void run() {
+
+    CodegenConfigurator configurator = new CodegenConfigurator();
+
+    configurator.setOutputDir(output)
+        .setGroupId(groupId)
+        .setArtifactId(artifactId)
+        .setArtifactVersion(artifactVersion)
+        .setLibrary(library)
+        .setLibrary(programmingModel)
+        .setLang(lang);
+
+    if (isNotEmpty(spec)) {
+
+      File contractFile = new File(spec);
+
+      // has many contracts
+      if (contractFile.isDirectory()) {
+
+        try {
+          Files.walkFileTree(Paths.get(contractFile.toURI()), new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+
+              configurator.setInputSpec(file.toFile().getCanonicalPath())
+                  .addAdditionalProperty("apiName", file.toFile().getName().split("\\.")[0]);
+
+              new DefaultCodeGenerator().opts(configurator).generate();
+
+              return super.visitFile(file, attrs);
+            }
+          });
+        } catch (IOException e) {
+          e.printStackTrace();
+        }
+      } else {
+        // one contract
+        configurator.setInputSpec(spec);
+        new DefaultCodeGenerator().opts(configurator).generate();
+      }
+    }
+  }
+}
diff --git a/toolkit-cli/src/main/java/org/apache/servicecomb/toolkit/cli/ToolkitMain.java b/toolkit-cli/src/main/java/org/apache/servicecomb/toolkit/cli/ToolkitMain.java
new file mode 100755
index 0000000..32795ef
--- /dev/null
+++ b/toolkit-cli/src/main/java/org/apache/servicecomb/toolkit/cli/ToolkitMain.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.toolkit.cli;
+
+import java.io.IOException;
+import java.util.Optional;
+import java.util.Properties;
+
+import io.airlift.airline.Cli;
+import io.airlift.airline.Help;
+
+public class ToolkitMain {
+
+  private static String projectVersion;
+
+  @SuppressWarnings("unchecked")
+  public static void main(String[] args) {
+
+    initialProjectVersion();
+
+    Cli.CliBuilder<Runnable> builder = Cli.<Runnable>builder("java -jar assistant-cli-" + projectVersion + ".jar");
+    builder.withDescription(
+        "ServiceComb code generator CLI (version " + projectVersion + "). More info on servicecomb.apache.org");
+    builder.withDefaultCommand(Help.class);
+    builder.withCommands(CodeGenerate.class, Help.class);
+    Runnable cmd = builder.build().parse(args);
+
+    cmd.run();
+  }
+
+  private static void initialProjectVersion() {
+
+    Properties properties = new Properties();
+    try {
+      properties.load(ToolkitMain.class.getClassLoader().getResourceAsStream("application.properties"));
+
+      projectVersion = Optional.ofNullable(properties.getProperty("version"))
+          .orElse("unknown");
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/toolkit-cli/src/main/resources/application.properties b/toolkit-cli/src/main/resources/application.properties
new file mode 100755
index 0000000..e5683df
--- /dev/null
+++ b/toolkit-cli/src/main/resources/application.properties
@@ -0,0 +1 @@
+version=${project.version}
\ No newline at end of file