Skip to content

Commit 0f2272d

Browse files
lwlee2608wing328
authored andcommitted
Implement Server Stub Code for Vert.x Web #115 (#4286)
* InlineResolver to flatten callback operations Signed-off-by: lwlee2608 <[email protected]> * clone from VertxServerCodegen, to new VertxWebServerCodegen * fix compilation error in VertxWebCodegn * Start working on VertxWebServerCodegen, adding support files * add server api handler * add server api and fix yaml spec file generation * link api to apiHandler * convert vertx parameters into API model * add support to multipart/form-data upload files * ability to set http status code from ApiImpl * replace rootPackage with invokerPackage * add readme and sample * fix circleCi error * override file to FileUpload in typeMapping, no need to override from fromOperation(). Also remove unused annotation import from model * remove smartBear software copyright * use {{artifactVersion}} instead of hardcode version in readme * add -t flag in generation script * add generated vertx-web server to master pom for testing
1 parent 4543c21 commit 0f2272d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+3770
-0
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/bin/sh
2+
3+
SCRIPT="$0"
4+
echo "# START SCRIPT: $SCRIPT"
5+
6+
while [ -h "$SCRIPT" ] ; do
7+
ls=`ls -ld "$SCRIPT"`
8+
link=`expr "$ls" : '.*-> \(.*\)$'`
9+
if expr "$link" : '/.*' > /dev/null; then
10+
SCRIPT="$link"
11+
else
12+
SCRIPT=`dirname "$SCRIPT"`/"$link"
13+
fi
14+
done
15+
16+
if [ ! -d "${APP_DIR}" ]; then
17+
APP_DIR=`dirname "$SCRIPT"`/..
18+
APP_DIR=`cd "${APP_DIR}"; pwd`
19+
fi
20+
21+
executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar"
22+
23+
if [ ! -f "$executable" ]
24+
then
25+
mvn -B clean package
26+
fi
27+
28+
SPEC="modules/openapi-generator/src/test/resources/3_0/petstore.yaml"
29+
GENERATOR="java-vertx-web"
30+
TEMPLATE="modules/openapi-generator/src/main/resources/JavaVertXWebServer"
31+
STUB_DIR="samples/server/petstore/java-vertx-web/rx"
32+
33+
# if you've executed sbt assembly previously it will use that instead.
34+
export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties"
35+
ags="generate -i $SPEC -t $TEMPLATE -g $GENERATOR --artifact-id java-vertx-web-rx-server -o $STUB_DIR --additional-properties hideGenerationTimestamp=true $@"
36+
37+
java $JAVA_OPTS -jar $executable $ags

docs/generators.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ The following generators are available:
8888
* [java-play-framework](generators/java-play-framework.md)
8989
* [java-undertow-server](generators/java-undertow-server.md)
9090
* [java-vertx](generators/java-vertx.md)
91+
* [java-vertx-web](generators/java-vertx-web.md)
9192
* [jaxrs-cxf](generators/jaxrs-cxf.md)
9293
* [jaxrs-cxf-cdi](generators/jaxrs-cxf-cdi.md)
9394
* [jaxrs-cxf-extended](generators/jaxrs-cxf-extended.md)

docs/generators/java-vertx-web.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
title: Config Options for java-vertx-web
3+
sidebar_label: java-vertx-web
4+
---
5+
6+
| Option | Description | Values | Default |
7+
| ------ | ----------- | ------ | ------- |
8+
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
9+
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
10+
|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false|
11+
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
12+
|modelPackage|package for generated models| |org.openapitools.vertxweb.server.model|
13+
|apiPackage|package for generated api classes| |org.openapitools.vertxweb.server.api|
14+
|invokerPackage|root package for generated code| |org.openapitools.vertxweb.server|
15+
|groupId|groupId in generated pom.xml| |org.openapitools|
16+
|artifactId|artifactId in generated pom.xml. This also becomes part of the generated library's filename| |openapi-java-vertx-web-server|
17+
|artifactVersion|artifact version in generated pom.xml. This also becomes part of the generated library's filename| |1.0.0-SNAPSHOT|
18+
|artifactUrl|artifact URL in generated pom.xml| |https://github.com/openapitools/openapi-generator|
19+
|artifactDescription|artifact description in generated pom.xml| |OpenAPI Java|
20+
|scmConnection|SCM connection in generated pom.xml| |scm:git:git@github.com:openapitools/openapi-generator.git|
21+
|scmDeveloperConnection|SCM developer connection in generated pom.xml| |scm:git:git@github.com:openapitools/openapi-generator.git|
22+
|scmUrl|SCM URL in generated pom.xml| |https://github.com/openapitools/openapi-generator|
23+
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
24+
|developerEmail|developer email in generated pom.xml| |[email protected]|
25+
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|
26+
|developerOrganizationUrl|developer organization URL in generated pom.xml| |http://openapitools.org|
27+
|licenseName|The name of the license| |Unlicense|
28+
|licenseUrl|The URL of the license| |http://unlicense.org|
29+
|sourceFolder|source folder for generated code| |src/main/java|
30+
|serializableModel|boolean - toggle &quot;implements Serializable&quot; for generated models| |false|
31+
|bigDecimalAsString|Treat BigDecimal values as Strings to avoid precision loss.| |false|
32+
|fullJavaUtil|whether to use fully qualified name for classes under java.util. This option only works for Java API client| |false|
33+
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |false|
34+
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
35+
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date (if you really have a good reason not to use threetenbp</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+) - note: this also sets &quot;java8&quot; to true</dd><dt>**threetenbp**</dt><dd>Backport of JSR310 (preferred for jdk &lt; 1.8)</dd><dl>|java8|
36+
|java8|Option. Use Java8 classes instead of third party equivalents|<dl><dt>**true**</dt><dd>Use Java 8 classes such as Base64</dd><dt>**false**</dt><dd>Various third party libraries as needed</dd><dl>|false|
37+
|disableHtmlEscaping|Disable HTML escaping of JSON strings when using gson (needed to avoid problems with byte[] fields)| |false|
38+
|booleanGetterPrefix|Set booleanGetterPrefix| |get|
39+
|parentGroupId|parent groupId in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
40+
|parentArtifactId|parent artifactId in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
41+
|parentVersion|parent version in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
42+
|snapshotVersion|Uses a SNAPSHOT version.|<dl><dt>**true**</dt><dd>Use a SnapShot Version</dd><dt>**false**</dt><dd>Use a Release Version</dd><dl>|null|
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/*
2+
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.openapitools.codegen.languages;
18+
19+
import io.swagger.v3.oas.models.media.Schema;
20+
import org.openapitools.codegen.CodegenConstants;
21+
import org.openapitools.codegen.CodegenModel;
22+
import org.openapitools.codegen.CodegenOperation;
23+
import org.openapitools.codegen.CodegenProperty;
24+
import org.openapitools.codegen.CodegenType;
25+
import org.openapitools.codegen.SupportingFile;
26+
27+
import java.io.File;
28+
import java.util.List;
29+
import java.util.Locale;
30+
import java.util.Map;
31+
32+
public class JavaVertXWebServerCodegen extends AbstractJavaCodegen {
33+
34+
protected String resourceFolder = "src/main/resources";
35+
protected String apiVersion = "1.0.0-SNAPSHOT";
36+
37+
public JavaVertXWebServerCodegen() {
38+
super();
39+
40+
// set the output folder here
41+
outputFolder = "generated-code" + File.separator + "javaVertXServer";
42+
43+
modelTemplateFiles.clear();
44+
modelTemplateFiles.put("model.mustache", ".java");
45+
46+
apiTemplateFiles.clear();
47+
apiTemplateFiles.put("api.mustache", ".java");
48+
apiTemplateFiles.put("apiImpl.mustache", "Impl.java");
49+
apiTemplateFiles.put("apiHandler.mustache", "Handler.java");
50+
51+
embeddedTemplateDir = templateDir = "JavaVertXWebServer";
52+
53+
invokerPackage = "org.openapitools.vertxweb.server";
54+
apiPackage = invokerPackage + ".api";
55+
modelPackage = invokerPackage + ".model";
56+
artifactId = "openapi-java-vertx-web-server";
57+
artifactVersion = apiVersion;
58+
this.setDateLibrary("java8");
59+
60+
// clioOptions default redifinition need to be updated
61+
updateOption(CodegenConstants.ARTIFACT_ID, this.getArtifactId());
62+
updateOption(CodegenConstants.ARTIFACT_VERSION, this.getArtifactVersion());
63+
updateOption(CodegenConstants.API_PACKAGE, apiPackage);
64+
updateOption(CodegenConstants.MODEL_PACKAGE, modelPackage);
65+
updateOption(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
66+
updateOption(this.DATE_LIBRARY, this.getDateLibrary());
67+
68+
// Override type mapping
69+
typeMapping.put("file", "FileUpload");
70+
}
71+
72+
public CodegenType getTag() {
73+
return CodegenType.SERVER;
74+
}
75+
76+
public String getName() {
77+
return "java-vertx-web";
78+
}
79+
80+
public String getHelp() {
81+
return "Generates a Java Vert.x-Web Server.";
82+
}
83+
84+
@Override
85+
public void processOpts() {
86+
super.processOpts();
87+
88+
apiTestTemplateFiles.clear();
89+
90+
importMapping.remove("JsonCreator");
91+
importMapping.remove("com.fasterxml.jackson.annotation.JsonProperty");
92+
importMapping.put("JsonInclude", "com.fasterxml.jackson.annotation.JsonInclude");
93+
importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty");
94+
importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue");
95+
importMapping.put("FileUpload", "io.vertx.ext.web.FileUpload");
96+
97+
modelDocTemplateFiles.clear();
98+
apiDocTemplateFiles.clear();
99+
100+
String sourcePackageFolder = sourceFolder + File.separator + invokerPackage.replace(".", File.separator);
101+
supportingFiles.clear();
102+
supportingFiles.add(new SupportingFile("supportFiles/openapi.mustache", resourceFolder, "openapi.yaml"));
103+
supportingFiles.add(new SupportingFile("supportFiles/HttpServerVerticle.mustache", sourcePackageFolder, "HttpServerVerticle.java"));
104+
supportingFiles.add(new SupportingFile("supportFiles/MainVerticle.mustache", sourcePackageFolder, "MainVerticle.java"));
105+
supportingFiles.add(new SupportingFile("supportFiles/ApiResponse.mustache", sourcePackageFolder, "ApiResponse.java"));
106+
supportingFiles.add(new SupportingFile("supportFiles/ApiException.mustache", sourcePackageFolder, "ApiException.java"));
107+
supportingFiles.add(new SupportingFile("supportFiles/ParameterCast.mustache", sourcePackageFolder, "ParameterCast.java"));
108+
supportingFiles.add(new SupportingFile("supportFiles/pom.mustache", "", "pom.xml"));
109+
110+
writeOptional(outputFolder, new SupportingFile("README.mustache", "", "README.md"));
111+
}
112+
113+
@Override
114+
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
115+
super.postProcessModelProperty(model, property);
116+
if (!model.isEnum) {
117+
model.imports.add("JsonInclude");
118+
model.imports.add("JsonProperty");
119+
if (model.hasEnums) {
120+
model.imports.add("JsonValue");
121+
}
122+
}
123+
}
124+
125+
@Override
126+
public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> objs, List<Object> allModels) {
127+
Map<String, Object> newObjs = super.postProcessOperationsWithModels(objs, allModels);
128+
Map<String, Object> operations = (Map<String, Object>) newObjs.get("operations");
129+
if (operations != null) {
130+
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
131+
for (CodegenOperation operation : ops) {
132+
operation.httpMethod = operation.httpMethod.toLowerCase(Locale.ROOT);
133+
134+
if (operation.returnType == null) {
135+
operation.returnType = "Void";
136+
}
137+
}
138+
}
139+
return newObjs;
140+
}
141+
142+
@Override
143+
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
144+
generateYAMLSpecFile(objs);
145+
return super.postProcessSupportingFileData(objs);
146+
}
147+
148+
@Override
149+
public CodegenModel fromModel(String name, Schema model) {
150+
CodegenModel codegenModel = super.fromModel(name, model);
151+
codegenModel.imports.remove("ApiModel");
152+
codegenModel.imports.remove("ApiModelProperty");
153+
return codegenModel;
154+
}
155+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{{^hideGenerationTimestamp}}
2+
Project generated on : {{generatedDate}}
3+
{{/hideGenerationTimestamp}}
4+
5+
## Getting Started
6+
7+
This document assumes you have maven available.
8+
9+
To build the project using maven, run:
10+
```bash
11+
mvn package && java -jar target/target/java-vertx-web-rx-server-{{artifactVersion}}-fat.jar
12+
```
13+
14+
If all builds successfully, the server should run on [http://localhost:8080/](http://localhost:8080/)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package {{package}};
2+
3+
{{#imports}}import {{import}};
4+
{{/imports}}
5+
6+
import {{invokerPackage}}.ApiResponse;
7+
8+
import io.reactivex.Single;
9+
10+
import java.util.List;
11+
import java.util.Map;
12+
13+
public interface {{classname}} {
14+
{{#operations}}
15+
{{#operation}}
16+
Single<ApiResponse<{{{returnType}}}>> {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}},{{/hasMore}}{{/allParams}});
17+
{{/operation}}
18+
{{/operations}}
19+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package {{package}};
2+
3+
{{#imports}}import {{import}};
4+
{{/imports}}
5+
6+
import {{invokerPackage}}.ParameterCast;
7+
import {{invokerPackage}}.ApiException;
8+
9+
import com.fasterxml.jackson.core.type.TypeReference;
10+
import io.vertx.core.json.Json;
11+
import io.vertx.core.Handler;
12+
import io.vertx.core.http.HttpServerResponse;
13+
import io.vertx.ext.web.RoutingContext;
14+
import org.slf4j.Logger;
15+
import org.slf4j.LoggerFactory;
16+
17+
import io.reactivex.Single;
18+
19+
import java.util.List;
20+
import java.util.Map;
21+
22+
public class {{classname}}Handler {
23+
24+
private static final Logger logger = LoggerFactory.getLogger({{classname}}Handler.class);
25+
private {{classname}} apiImpl = new {{classname}}Impl();
26+
27+
public {{classname}}Handler(Map<String, Handler<RoutingContext>> operationHandlers) {
28+
{{#operations}}
29+
{{#operation}}
30+
operationHandlers.put("{{operationId}}", this::{{operationId}});
31+
{{/operation}}
32+
{{/operations}}
33+
}
34+
{{#operations}}
35+
{{#operation}}
36+
37+
private void {{operationId}}(RoutingContext routingContext) {
38+
logger.info("{{operationId}}()");
39+
HttpServerResponse response = routingContext.response();
40+
41+
{{#returnType}}Single{{/returnType}}{{^returnType}}Completable{{/returnType}}.defer( () -> {
42+
{{#allParams}}
43+
{{^isBodyParam}}
44+
{{^isListContainer}}
45+
{{#isHeaderParam}}
46+
{{{dataType}}} {{paramName}} = ParameterCast.to{{dataType}}(routingContext.request().getHeader("{{baseName}}"));
47+
{{/isHeaderParam}}
48+
{{#isPathParam}}
49+
{{{dataType}}} {{paramName}} = ParameterCast.to{{dataType}}(routingContext.pathParams().get("{{baseName}}"));
50+
{{/isPathParam}}
51+
{{#isQueryParam}}
52+
{{{dataType}}} {{paramName}} = ParameterCast.to{{dataType}}(routingContext.queryParams().get("{{baseName}}"));
53+
{{/isQueryParam}}
54+
{{#isFormParam}}
55+
{{^isFile}}
56+
{{{dataType}}} {{paramName}} = ParameterCast.to{{dataType}}(routingContext.request().getFormAttribute("{{baseName}}"));
57+
{{/isFile}}
58+
{{#isFile}}
59+
{{{dataType}}} {{paramName}} = routingContext.fileUploads().iterator().next();
60+
{{/isFile}}
61+
{{/isFormParam}}
62+
{{/isListContainer}}
63+
{{#isListContainer}}
64+
{{{dataType}}} {{paramName}} = routingContext.request().params().getAll("{{baseName}}");
65+
{{/isListContainer}}
66+
{{/isBodyParam}}
67+
{{/allParams}}
68+
{{#allParams}}
69+
{{#isBodyParam}}
70+
String jsonString = routingContext.getBodyAsString();
71+
{{{dataType}}} {{paramName}} = jsonString == null ? null : Json.decodeValue(jsonString, new TypeReference<{{{dataType}}}>(){});
72+
{{/isBodyParam}}
73+
{{/allParams}}
74+
{{#allParams}}
75+
logger.info("Parameter {{paramName}} is {}", {{paramName}});
76+
{{/allParams}}
77+
return apiImpl.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
78+
})
79+
.subscribe(
80+
apiResponse -> {
81+
response.setStatusCode(apiResponse.getStatusCode())
82+
.end(Json.encodePrettily(apiResponse.getData()));
83+
}, error -> {
84+
if (error instanceof ApiException) {
85+
ApiException apiException = (ApiException) error;
86+
response.setStatusCode(apiException.getStatusCode()).end(apiException.getMessage());
87+
} else {
88+
response.setStatusCode(500).end(error.getMessage());
89+
}
90+
}).dispose();
91+
}
92+
93+
{{/operation}}
94+
{{/operations}}
95+
}

0 commit comments

Comments
 (0)