[REQ] Java Microprofile REST Client Template (#4713)

* Add a Java Library called microprofile.

* Fix formatting
This commit is contained in:
Paul Gooderham 2019-12-09 22:41:50 -05:00 committed by William Cheng
parent 307f37c7f9
commit a9494ac1a3
33 changed files with 762 additions and 8 deletions

View File

@ -70,7 +70,7 @@ OpenAPI Generator allows generation of API client libraries (SDK generation), se
| | Languages/Frameworks | | | Languages/Frameworks |
|-|-| |-|-|
**API clients** | **ActionScript**, **Ada**, **Apex**, **Bash**, **C**, **C#** (.net 2.0, 3.5 or later, .NET Standard 1.3 - 2.0, .NET Core 2.0), **C++** (cpp-restsdk, Qt5, Tizen), **Clojure**, **Dart (1.x, 2.x)**, **Elixir**, **Elm**, **Eiffel**, **Erlang**, **Go**, **Groovy**, **Haskell** (http-client, Servant), **Java** (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java, Rest-assured, Spring 5 Web Client), **Kotlin**, **Lua**, **Nim**, **Node.js/JavaScript** (ES5, ES6, AngularJS with Google Closure Compiler annotations, Flow types), **Objective-C**, **OCaml**, **Perl**, **PHP**, **PowerShell**, **Python**, **R**, **Ruby**, **Rust** (rust, rust-server), **Scala** (akka, http4s, scalaz, swagger-async-httpclient), **Swift** (2.x, 3.x, 4.x), **Typescript** (AngularJS, Angular (2.x - 8.x), Aurelia, Axios, Fetch, Inversify, jQuery, Node, Rxjs) **API clients** | **ActionScript**, **Ada**, **Apex**, **Bash**, **C**, **C#** (.net 2.0, 3.5 or later, .NET Standard 1.3 - 2.0, .NET Core 2.0), **C++** (cpp-restsdk, Qt5, Tizen), **Clojure**, **Dart (1.x, 2.x)**, **Elixir**, **Elm**, **Eiffel**, **Erlang**, **Go**, **Groovy**, **Haskell** (http-client, Servant), **Java** (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java, Rest-assured, Spring 5 Web Client, MicroProfile Rest Client), **Kotlin**, **Lua**, **Nim**, **Node.js/JavaScript** (ES5, ES6, AngularJS with Google Closure Compiler annotations, Flow types), **Objective-C**, **OCaml**, **Perl**, **PHP**, **PowerShell**, **Python**, **R**, **Ruby**, **Rust** (rust, rust-server), **Scala** (akka, http4s, scalaz, swagger-async-httpclient), **Swift** (2.x, 3.x, 4.x), **Typescript** (AngularJS, Angular (2.x - 8.x), Aurelia, Axios, Fetch, Inversify, jQuery, Node, Rxjs)
**Server stubs** | **Ada**, **C#** (ASP.NET Core, NancyFx), **C++** (Pistache, Restbed, Qt5 QHTTPEngine), **Erlang**, **F#** (Giraffe), **Go** (net/http, Gin), **Haskell** (Servant), **Java** (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, Jersey, RestEasy, Play Framework, [PKMST](https://github.com/ProKarma-Inc/pkmst-getting-started-examples), [Vert.x](https://vertx.io/)), **Kotlin** (Spring Boot, Ktor, Vertx), **PHP** (Laravel, Lumen, Slim, Silex, [Symfony](https://symfony.com/), [Zend Expressive](https://github.com/zendframework/zend-expressive)), **Python** (Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Rust** (rust-server), **Scala** ([Finch](https://github.com/finagle/finch), [Lagom](https://github.com/lagom/lagom), [Play](https://www.playframework.com/), Scalatra) **Server stubs** | **Ada**, **C#** (ASP.NET Core, NancyFx), **C++** (Pistache, Restbed, Qt5 QHTTPEngine), **Erlang**, **F#** (Giraffe), **Go** (net/http, Gin), **Haskell** (Servant), **Java** (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, Jersey, RestEasy, Play Framework, [PKMST](https://github.com/ProKarma-Inc/pkmst-getting-started-examples), [Vert.x](https://vertx.io/)), **Kotlin** (Spring Boot, Ktor, Vertx), **PHP** (Laravel, Lumen, Slim, Silex, [Symfony](https://symfony.com/), [Zend Expressive](https://github.com/zendframework/zend-expressive)), **Python** (Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Rust** (rust-server), **Scala** ([Finch](https://github.com/finagle/finch), [Lagom](https://github.com/lagom/lagom), [Play](https://www.playframework.com/), Scalatra)
**API documentation generators** | **HTML**, **Confluence Wiki**, **Asciidoc** **API documentation generators** | **HTML**, **Confluence Wiki**, **Asciidoc**
**Configuration files** | [**Apache2**](https://httpd.apache.org/) **Configuration files** | [**Apache2**](https://httpd.apache.org/)

View File

@ -7,6 +7,7 @@
./bin/java-petstore-jersey1.sh ./bin/java-petstore-jersey1.sh
./bin/java-petstore-jersey2-java6.sh ./bin/java-petstore-jersey2-java6.sh
./bin/java-petstore-jersey2.sh ./bin/java-petstore-jersey2.sh
./bin/java-petstore-microprofile.sh
./bin/java-petstore-native.sh ./bin/java-petstore-native.sh
./bin/java-petstore-okhttp-gson-parcelable.sh ./bin/java-petstore-okhttp-gson-parcelable.sh
./bin/java-petstore-okhttp-gson.sh ./bin/java-petstore-okhttp-gson.sh

View File

@ -0,0 +1,36 @@
#!/bin/sh
SCRIPT="$0"
echo "# START SCRIPT: $SCRIPT"
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/openapi-generator-cli/target/openapi-generator-cli.jar"
if [ ! -f "$executable" ]
then
mvn -B 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 --artifact-id "microprofile-rest-client" -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g java --library microprofile -o samples/client/petstore/java/microprofile-rest-client $@"
echo "Removing files and folders under samples/client/petstore/java/microprofile-rest-client/src/main"
rm -rf samples/client/petstore/java/microprofile-rest-client/src/main
find samples/client/petstore/java/microprofile-rest-client -maxdepth 1 -type f ! -name "README.md" -exec rm {} +
java $JAVA_OPTS -jar $executable $ags

View File

@ -0,0 +1,10 @@
set executable=.\modules\openapi-generator-cli\target\openapi-generator-cli.jar
If Not Exist %executable% (
mvn clean package
)
REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate --artifact-id "microprofile-rest-client" -i modules\openapi-generator\src\test\resources\2_0\petstore.yaml -g java --library microprofile -o samples\client\petstore\java\microprofile-rest-client
java %JAVA_OPTS% -jar %executable% %ags%

View File

@ -29,6 +29,9 @@ import org.openapitools.codegen.utils.ProcessUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.Schema;
import java.io.File; import java.io.File;
import java.util.*; import java.util.*;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -39,8 +42,7 @@ import static java.util.Collections.sort;
import static org.openapitools.codegen.utils.StringUtils.camelize; import static org.openapitools.codegen.utils.StringUtils.camelize;
public class JavaClientCodegen extends AbstractJavaCodegen public class JavaClientCodegen extends AbstractJavaCodegen
implements BeanValidationFeatures, PerformBeanValidationFeatures, implements BeanValidationFeatures, PerformBeanValidationFeatures, GzipFeatures {
GzipFeatures {
static final String MEDIA_TYPE = "mediaType"; static final String MEDIA_TYPE = "mediaType";
@ -77,6 +79,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
public static final String RETROFIT_1 = "retrofit"; public static final String RETROFIT_1 = "retrofit";
public static final String RETROFIT_2 = "retrofit2"; public static final String RETROFIT_2 = "retrofit2";
public static final String VERTX = "vertx"; public static final String VERTX = "vertx";
public static final String MICROPROFILE = "microprofile";
public static final String SERIALIZATION_LIBRARY_GSON = "gson"; public static final String SERIALIZATION_LIBRARY_GSON = "gson";
public static final String SERIALIZATION_LIBRARY_JACKSON = "jackson"; public static final String SERIALIZATION_LIBRARY_JACKSON = "jackson";
@ -145,6 +148,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
supportedLibraries.put(GOOGLE_API_CLIENT, "HTTP client: Google API client 1.x. JSON processing: Jackson 2.9.x"); supportedLibraries.put(GOOGLE_API_CLIENT, "HTTP client: Google API client 1.x. JSON processing: Jackson 2.9.x");
supportedLibraries.put(REST_ASSURED, "HTTP client: rest-assured : 4.x. JSON processing: Gson 2.x or Jackson 2.9.x. Only for Java8"); supportedLibraries.put(REST_ASSURED, "HTTP client: rest-assured : 4.x. JSON processing: Gson 2.x or Jackson 2.9.x. Only for Java8");
supportedLibraries.put(NATIVE, "HTTP client: Java native HttpClient. JSON processing: Jackson 2.9.x. Only for Java11+"); supportedLibraries.put(NATIVE, "HTTP client: Java native HttpClient. JSON processing: Jackson 2.9.x. Only for Java11+");
supportedLibraries.put(MICROPROFILE, "HTTP client: Microprofile client X.x. JSON processing: Jackson 2.9.x");
CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use"); CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
libraryOption.setEnum(supportedLibraries); libraryOption.setEnum(supportedLibraries);
@ -176,11 +180,22 @@ public class JavaClientCodegen extends AbstractJavaCodegen
return "Generates a Java client library (HTTP lib: Jersey (1.x, 2.x), Retrofit (1.x, 2.x), OpenFeign (9.x, 10.x) and more."; return "Generates a Java client library (HTTP lib: Jersey (1.x, 2.x), Retrofit (1.x, 2.x), OpenFeign (9.x, 10.x) and more.";
} }
@Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
super.addOperationToGroup(tag, resourcePath, operation, co, operations);
if (MICROPROFILE.equals(getLibrary())) {
co.subresourceOperation = !co.path.isEmpty();
}
}
@Override @Override
public void processOpts() { public void processOpts() {
if ((WEBCLIENT.equals(getLibrary()) && "threetenbp".equals(dateLibrary)) || NATIVE.equals(getLibrary())) { if ((WEBCLIENT.equals(getLibrary()) && "threetenbp".equals(dateLibrary)) || NATIVE.equals(getLibrary())) {
dateLibrary = "java8"; dateLibrary = "java8";
} }
else if (MICROPROFILE.equals(getLibrary())) {
dateLibrary = "legacy";
}
super.processOpts(); super.processOpts();
@ -266,12 +281,12 @@ public class JavaClientCodegen extends AbstractJavaCodegen
writeOptional(outputFolder, new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml")); writeOptional(outputFolder, new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
supportingFiles.add(new SupportingFile("travis.mustache", "", ".travis.yml")); supportingFiles.add(new SupportingFile("travis.mustache", "", ".travis.yml"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerFolder, "ApiClient.java")); supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerFolder, "ApiClient.java"));
if (!(RESTTEMPLATE.equals(getLibrary()) || REST_ASSURED.equals(getLibrary()) || NATIVE.equals(getLibrary()))) { if (!(RESTTEMPLATE.equals(getLibrary()) || REST_ASSURED.equals(getLibrary()) || NATIVE.equals(getLibrary()) || MICROPROFILE.equals(getLibrary()))) {
supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java")); supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java"));
} }
// google-api-client doesn't use the OpenAPI auth, because it uses Google Credential directly (HttpRequestInitializer) // google-api-client doesn't use the OpenAPI auth, because it uses Google Credential directly (HttpRequestInitializer)
if (!(GOOGLE_API_CLIENT.equals(getLibrary()) || REST_ASSURED.equals(getLibrary()) || NATIVE.equals(getLibrary()))) { if (!(GOOGLE_API_CLIENT.equals(getLibrary()) || REST_ASSURED.equals(getLibrary()) || NATIVE.equals(getLibrary()) || MICROPROFILE.equals(getLibrary()))) {
supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java")); supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java"));
supportingFiles.add(new SupportingFile("auth/HttpBearerAuth.mustache", authFolder, "HttpBearerAuth.java")); supportingFiles.add(new SupportingFile("auth/HttpBearerAuth.mustache", authFolder, "HttpBearerAuth.java"));
supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.mustache", authFolder, "ApiKeyAuth.java")); supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.mustache", authFolder, "ApiKeyAuth.java"));
@ -303,13 +318,13 @@ public class JavaClientCodegen extends AbstractJavaCodegen
apiDocTemplateFiles.remove("api_doc.mustache"); apiDocTemplateFiles.remove("api_doc.mustache");
} }
if (!(FEIGN.equals(getLibrary()) || RESTTEMPLATE.equals(getLibrary()) || usesAnyRetrofitLibrary() || GOOGLE_API_CLIENT.equals(getLibrary()) || REST_ASSURED.equals(getLibrary()) || WEBCLIENT.equals(getLibrary()))) { if (!(FEIGN.equals(getLibrary()) || RESTTEMPLATE.equals(getLibrary()) || usesAnyRetrofitLibrary() || GOOGLE_API_CLIENT.equals(getLibrary()) || REST_ASSURED.equals(getLibrary()) || WEBCLIENT.equals(getLibrary()) || MICROPROFILE.equals(getLibrary()))) {
supportingFiles.add(new SupportingFile("apiException.mustache", invokerFolder, "ApiException.java")); supportingFiles.add(new SupportingFile("apiException.mustache", invokerFolder, "ApiException.java"));
supportingFiles.add(new SupportingFile("Configuration.mustache", invokerFolder, "Configuration.java")); supportingFiles.add(new SupportingFile("Configuration.mustache", invokerFolder, "Configuration.java"));
supportingFiles.add(new SupportingFile("Pair.mustache", invokerFolder, "Pair.java")); supportingFiles.add(new SupportingFile("Pair.mustache", invokerFolder, "Pair.java"));
} }
if (!(FEIGN.equals(getLibrary()) || RESTTEMPLATE.equals(getLibrary()) || usesAnyRetrofitLibrary() || GOOGLE_API_CLIENT.equals(getLibrary()) || REST_ASSURED.equals(getLibrary()) || NATIVE.equals(getLibrary()))) { if (!(FEIGN.equals(getLibrary()) || RESTTEMPLATE.equals(getLibrary()) || usesAnyRetrofitLibrary() || GOOGLE_API_CLIENT.equals(getLibrary()) || REST_ASSURED.equals(getLibrary()) || NATIVE.equals(getLibrary()) || MICROPROFILE.equals(getLibrary()))) {
supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java")); supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java"));
} }
@ -384,6 +399,15 @@ public class JavaClientCodegen extends AbstractJavaCodegen
additionalProperties.put("convert", new CaseFormatLambda(LOWER_CAMEL, UPPER_UNDERSCORE)); additionalProperties.put("convert", new CaseFormatLambda(LOWER_CAMEL, UPPER_UNDERSCORE));
apiTemplateFiles.put("api.mustache", ".java"); apiTemplateFiles.put("api.mustache", ".java");
supportingFiles.add(new SupportingFile("ResponseSpecBuilders.mustache", invokerFolder, "ResponseSpecBuilders.java")); supportingFiles.add(new SupportingFile("ResponseSpecBuilders.mustache", invokerFolder, "ResponseSpecBuilders.java"));
} else if (MICROPROFILE.equals(getLibrary())) {
supportingFiles.clear(); // Don't need extra files provided by Java Codegen
String apiExceptionFolder = (sourceFolder + File.separator + apiPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar);
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("api_exception.mustache", apiExceptionFolder, "ApiException.java"));
supportingFiles.add(new SupportingFile("api_exception_mapper.mustache", apiExceptionFolder, "ApiExceptionMapper.java"));
importMapping.put("LocalDate", "org.joda.time.LocalDate");
serializationLibrary = "none";
} else { } else {
LOGGER.error("Unknown library option (-l/--library): " + getLibrary()); LOGGER.error("Unknown library option (-l/--library): " + getLibrary());
} }
@ -542,11 +566,15 @@ public class JavaClientCodegen extends AbstractJavaCodegen
} }
// google-api-client doesn't use the OpenAPI auth, because it uses Google Credential directly (HttpRequestInitializer) // google-api-client doesn't use the OpenAPI auth, because it uses Google Credential directly (HttpRequestInitializer)
if ((!(GOOGLE_API_CLIENT.equals(getLibrary()) || REST_ASSURED.equals(getLibrary()) || usePlayWS || NATIVE.equals(getLibrary()))) && ProcessUtils.hasOAuthMethods(objs)) { if ((!(GOOGLE_API_CLIENT.equals(getLibrary()) || REST_ASSURED.equals(getLibrary()) || usePlayWS || NATIVE.equals(getLibrary()) || MICROPROFILE.equals(getLibrary()))) && ProcessUtils.hasOAuthMethods(objs)) {
supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java")); supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java"));
supportingFiles.add(new SupportingFile("auth/OAuthFlow.mustache", authFolder, "OAuthFlow.java")); supportingFiles.add(new SupportingFile("auth/OAuthFlow.mustache", authFolder, "OAuthFlow.java"));
} }
if (MICROPROFILE.equals(getLibrary())) {
objs = AbstractJavaJAXRSServerCodegen.jaxrsPostProcessOperations(objs);
}
return objs; return objs;
} }
@ -636,6 +664,23 @@ public class JavaClientCodegen extends AbstractJavaCodegen
model.imports.add("JsonCreator"); model.imports.add("JsonCreator");
} }
} }
if (MICROPROFILE.equals(getLibrary())) {
model.imports.remove("ApiModelProperty");
model.imports.remove("ApiModel");
model.imports.remove("JsonSerialize");
model.imports.remove("ToStringSerializer");
}
}
@Override
public CodegenModel fromModel(String name, Schema model) {
CodegenModel codegenModel = super.fromModel(name, model);
if (MICROPROFILE.equals(getLibrary())) {
if (codegenModel.imports.contains("ApiModel")) {
// Remove io.swagger.annotations.ApiModel import
codegenModel.imports.remove("ApiModel");
}
}
return codegenModel;
} }
@Override @Override

View File

@ -0,0 +1,10 @@
# {{appName}} - MicroProfile Rest Client
{{#appDescription}}
{{{appDescription}}}
{{/appDescription}}
## Overview
This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project.
[MicroProfile Rest Client](https://github.com/eclipse/microprofile-rest-client) is a type-safe way of calling
REST services. The generated client contains an interface which acts as the client, you can inject it into dependent classes.

View File

@ -0,0 +1,61 @@
{{>licenseInfo}}
package {{package}};
{{#imports}}import {{import}};
{{/imports}}
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import javax.ws.rs.*;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;
{{^disableMultipart}}
import org.apache.cxf.jaxrs.ext.multipart.*;
{{/disableMultipart}}
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
{{#appName}}
/**
* {{{appName}}}
*
{{#appDescription}}
* <p>{{{appDescription}}}
*
{{/appDescription}}
*/
{{/appName}}
@RegisterRestClient
@RegisterProvider(ApiExceptionMapper.class)
@Path("{{^useAnnotatedBasePath}}/{{/useAnnotatedBasePath}}{{#useAnnotatedBasePath}}{{contextPath}}{{/useAnnotatedBasePath}}")
public interface {{classname}} {
{{#operations}}
{{#operation}}
{{#summary}}
/**
* {{summary}}
*
{{#notes}}
* {{notes}}
*
{{/notes}}
*/
{{/summary}}
@{{httpMethod}}
{{#subresourceOperation}}@Path("{{{path}}}"){{/subresourceOperation}}
{{#hasConsumes}}
@Consumes({ {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} })
{{/hasConsumes}}
{{#hasProduces}}
@Produces({ {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} })
{{/hasProduces}}
public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException, ProcessingException;
{{/operation}}
}
{{/operations}}

View File

@ -0,0 +1,23 @@
{{>licenseInfo}}
package {{apiPackage}};
import javax.ws.rs.core.Response;
public class ApiException extends Exception {
private static final long serialVersionUID = 1L;
private Response response;
public ApiException() {
super();
}
public ApiException(Response response) {
super("Api response has status code " + response.getStatus());
this.response = response;
}
public Response getResponse() {
return this.response;
}
}

View File

@ -0,0 +1,22 @@
{{>licenseInfo}}
package {{apiPackage}};
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
@Provider
public class ApiExceptionMapper
implements ResponseExceptionMapper<ApiException> {
@Override
public boolean handles(int status, MultivaluedMap<String, Object> headers) {
return status >= 400;
}
@Override
public ApiException toThrowable(Response response) {
return new ApiException(response);
}
}

View File

@ -0,0 +1,75 @@
{{>licenseInfo}}
package {{package}};
{{#imports}}import {{import}};
{{/imports}}
import org.junit.Test;
import org.junit.Before;
import static org.junit.Assert.*;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import java.net.URL;
import java.net.MalformedURLException;
{{^fullJavaUtil}}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
{{/fullJavaUtil}}
/**
{{#appName}}
* {{{appName}}} Test
*
{{/appName}}
* API tests for {{classname}}
*/
{{#generateSpringBootApplication}}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SpringBootApplication.class)
@WebAppConfiguration
@IntegrationTest("server.port=0")
{{/generateSpringBootApplication}}
public class {{classname}}Test {
private {{classname}} client;
private String baseUrl = "http://localhost:9080";
@Before
public void setup() throws MalformedURLException {
client = RestClientBuilder.newBuilder()
.baseUrl(new URL(baseUrl))
.register(ApiException.class)
.build({{classname}}.class);
}
{{#operations}}{{#operation}}
/**
{{#summary}}
* {{summary}}
*
{{#notes}}
* {{notes}}
*
{{/notes}}
{{/summary}}
* @throws ApiException
* if the Api call fails
*/
@Test
public void {{operationId}}Test() {
// TODO: test validations
{{#allParams}}
{{^isFile}}{{{dataType}}} {{paramName}} = null;{{/isFile}}{{#isFile}}org.apache.cxf.jaxrs.ext.multipart.Attachment {{paramName}} = null;{{/isFile}}
{{/allParams}}
//{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
//{{#returnType}}assertNotNull(response);{{/returnType}}
}
{{/operation}}{{/operations}}
}

View File

@ -0,0 +1,4 @@
{{#required}}
@NotNull
{{/required}}
{{>beanValidationCore}}

View File

@ -0,0 +1,20 @@
{{#pattern}} @Pattern(regexp="{{{pattern}}}"){{/pattern}}{{!
minLength && maxLength set
}}{{#minLength}}{{#maxLength}} @Size(min={{minLength}},max={{maxLength}}){{/maxLength}}{{/minLength}}{{!
minLength set, maxLength not
}}{{#minLength}}{{^maxLength}} @Size(min={{minLength}}){{/maxLength}}{{/minLength}}{{!
minLength not set, maxLength set
}}{{^minLength}}{{#maxLength}} @Size(max={{maxLength}}){{/maxLength}}{{/minLength}}{{!
@Size: minItems && maxItems set
}}{{#minItems}}{{#maxItems}} @Size(min={{minItems}},max={{maxItems}}){{/maxItems}}{{/minItems}}{{!
@Size: minItems set, maxItems not
}}{{#minItems}}{{^maxItems}} @Size(min={{minItems}}){{/maxItems}}{{/minItems}}{{!
@Size: minItems not set && maxItems set
}}{{^minItems}}{{#maxItems}} @Size(max={{maxItems}}){{/maxItems}}{{/minItems}}{{!
check for integer or long / all others=decimal type with @Decimal*
isInteger set
}}{{#isInteger}}{{#minimum}} @Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}){{/maximum}}{{/isInteger}}{{!
isLong set
}}{{#isLong}}{{#minimum}} @Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L){{/maximum}}{{/isLong}}{{!
Not Integer, not Long => we have a decimal value!
}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin("{{minimum}}"){{/minimum}}{{#maximum}} @DecimalMax("{{maximum}}"){{/maximum}}{{/isLong}}{{/isInteger}}

View File

@ -0,0 +1 @@
{{#required}} @NotNull{{/required}}{{>beanValidationCore}}

View File

@ -0,0 +1 @@
{{! PathParam is always required, no @NotNull necessary }}{{>beanValidationCore}}

View File

@ -0,0 +1 @@
{{#required}} @NotNull{{/required}}{{>beanValidationCore}}

View File

@ -0,0 +1 @@
{{#isBodyParam}}{{#useBeanValidation}}@Valid {{/useBeanValidation}}{{{dataType}}} {{paramName}}{{/isBodyParam}}

View File

@ -0,0 +1 @@
{{#isBodyParam}}{{{dataType}}} {{paramName}}{{/isBodyParam}}

View File

@ -0,0 +1,33 @@
@XmlType(name="{{datatypeWithEnum}}")
@XmlEnum({{dataType}}.class)
public enum {{datatypeWithEnum}} {
{{#allowableValues}}
{{#enumVars}}@XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) {{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}
{{/allowableValues}}
private {{dataType}} value;
{{datatypeWithEnum}} ({{dataType}} v) {
value = v;
}
public {{dataType}} value() {
return value;
}
@Override
public String toString() {
return String.valueOf(value);
}
public static {{datatypeWithEnum}} fromValue(String v) {
for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
if (String.valueOf(b.value).equals(v)) {
return b;
}
}
{{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + v + "'");{{/useNullForUnknownEnumValue}}
}
}

View File

@ -0,0 +1,48 @@
{{#jackson}}
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
{{/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
{{#jackson}}
@JsonValue
{{/jackson}}
public String toString() {
return String.valueOf(value);
}
{{#jackson}}
@JsonCreator
{{/jackson}}
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;
}
}
{{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + text + "'");{{/useNullForUnknownEnumValue}}
}
}

View File

@ -0,0 +1 @@
{{#isFormParam}}{{^isFile}}@Multipart(value = "{{baseName}}"{{^required}}, required = false{{/required}}) {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}} @Multipart(value = "{{baseName}}" {{^required}}, required = false{{/required}}) Attachment {{paramName}}Detail{{/isFile}}{{/isFormParam}}

View File

@ -0,0 +1 @@
{{#isFormParam}}{{^isFile}}{{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}} Attachment {{paramName}}Detail{{/isFile}}{{/isFormParam}}

View File

@ -0,0 +1 @@
@javax.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}")

View File

@ -0,0 +1 @@
{{#isHeaderParam}}@HeaderParam("{{baseName}}") {{#useBeanValidation}}{{>beanValidationHeaderParams}}{{/useBeanValidation}} {{{dataType}}} {{paramName}}{{/isHeaderParam}}

View File

@ -0,0 +1 @@
{{#isHeaderParam}}{{{dataType}}} {{paramName}}{{/isHeaderParam}}

View File

@ -0,0 +1,23 @@
/**
* {{{appName}}}
* {{{appDescription}}}
*
* {{#version}}The version of the OpenAPI document: {{{version}}}{{/version}}
* {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}}
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*
* Licensed 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.
*/

View File

@ -0,0 +1,23 @@
{{>licenseInfo}}
package {{package}};
{{#imports}}import {{import}};
{{/imports}}
{{#serializableModel}}
import java.io.Serializable;
{{/serializableModel}}
{{#useBeanValidation}}
import javax.validation.constraints.*;
import javax.validation.Valid;
{{/useBeanValidation}}
{{#models}}
{{#model}}
{{#isEnum}}
{{>enumOuterClass}}
{{/isEnum}}
{{^isEnum}}
{{>pojo}}
{{/isEnum}}
{{/model}}
{{/models}}

View File

@ -0,0 +1 @@
{{#isPathParam}}@PathParam("{{baseName}}"){{#useBeanValidation}}{{>beanValidationPathParams}}{{/useBeanValidation}} {{{dataType}}} {{paramName}}{{/isPathParam}}

View File

@ -0,0 +1 @@
{{#isPathParam}}{{{dataType}}} {{paramName}}{{/isPathParam}}

View File

@ -0,0 +1,129 @@
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlEnum;
import javax.xml.bind.annotation.XmlEnumValue;
import javax.json.bind.annotation.JsonbProperty;
{{#withXml}}
@XmlAccessorType(XmlAccessType.FIELD)
{{#hasVars}} @XmlType(name = "{{classname}}", propOrder =
{ {{#vars}}"{{name}}"{{^-last}}, {{/-last}}{{/vars}}
}){{/hasVars}}
{{^hasVars}}@XmlType(name = "{{classname}}"){{/hasVars}}
{{^parent}}@XmlRootElement(name="{{classname}}"){{/parent}}
{{/withXml}}
{{#description}}
/**
* {{{description}}}
**/
{{/description}}
public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializableModel}} implements Serializable{{/serializableModel}} {
{{#vars}}{{#isEnum}}{{^isContainer}}
{{>enumClass}}{{/isContainer}}{{#isContainer}}{{#mostInnerItems}}
{{>enumClass}}{{/mostInnerItems}}{{/isContainer}}{{/isEnum}}
{{#withXml}}
@XmlElement(name="{{baseName}}"{{#required}}, required = {{required}}{{/required}})
{{/withXml}}
{{#description}}
/**
* {{{description}}}
**/
{{/description}}
{{#isContainer}}
private {{{datatypeWithEnum}}} {{name}}{{#required}} = {{{defaultValue}}}{{/required}}{{^required}} = null{{/required}};
{{/isContainer}}
{{^isContainer}}
private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
{{/isContainer}}
{{/vars}}
{{#vars}}
/**
{{#description}}
* {{description}}
{{/description}}
{{^description}}
* Get {{name}}
{{/description}}
{{#minimum}}
* minimum: {{minimum}}
{{/minimum}}
{{#maximum}}
* maximum: {{maximum}}
{{/maximum}}
* @return {{name}}
**/
@JsonbProperty("{{baseName}}")
{{#vendorExtensions.extraAnnotation}}
{{{vendorExtensions.extraAnnotation}}}
{{/vendorExtensions.extraAnnotation}}
{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#isEnum}}{{^isListContainer}}{{^isMapContainer}}public {{dataType}} {{getter}}() {
if ({{name}} == null) {
return null;
}
return {{name}}.value();
}{{/isMapContainer}}{{/isListContainer}}{{/isEnum}}{{#isEnum}}{{#isListContainer}}public {{{datatypeWithEnum}}} {{getter}}() {
return {{name}};
}{{/isListContainer}}{{/isEnum}}{{#isEnum}}{{#isMapContainer}}public {{{datatypeWithEnum}}} {{getter}}() {
return {{name}};
}{{/isMapContainer}}{{/isEnum}}{{^isEnum}}public {{{datatypeWithEnum}}} {{getter}}() {
return {{name}};
}{{/isEnum}}
{{^isReadOnly}}
/**
* Set {{name}}
**/
public void {{setter}}({{{datatypeWithEnum}}} {{name}}) {
this.{{name}} = {{name}};
}
public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) {
this.{{name}} = {{name}};
return this;
}
{{#isListContainer}}
public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
this.{{name}}.add({{name}}Item);
return this;
}
{{/isListContainer}}
{{#isMapContainer}}
public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) {
this.{{name}}.put(key, {{name}}Item);
return this;
}
{{/isMapContainer}}
{{/isReadOnly}}
{{/vars}}
/**
* Create a string representation of this pojo.
**/
@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 static String toIndentedString(java.lang.Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}

View File

@ -0,0 +1,173 @@
<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>
{{#appDescription}}
<description>{{appDescription}}</description>
{{/appDescription}}
<version>{{artifactVersion}}</version>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/gen/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit-version}</version>
<scope>test</scope>
</dependency>
{{#useBeanValidation}}
<!-- Bean Validation API support -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>${beanvalidation-version}</version>
<scope>provided</scope>
</dependency>
{{/useBeanValidation}}
<!-- Eclipse MicroProfile Rest Client -->
<dependency>
<groupId>org.eclipse.microprofile.rest.client</groupId>
<artifactId>microprofile-rest-client-api</artifactId>
<version>1.2.1</version>
</dependency>
<!-- JAX-RS -->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.smallrye</groupId>
<artifactId>smallrye-rest-client</artifactId>
<version>1.2.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.smallrye</groupId>
<artifactId>smallrye-config</artifactId>
<version>1.3.5</version>
<scope>test</scope>
</dependency>
{{^disableMultipart}}
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-extension-providers</artifactId>
<version>3.2.6</version>
</dependency>
{{/disableMultipart}}
<dependency>
<groupId>javax.json.bind</groupId>
<artifactId>javax.json.bind-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.11</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.2.11</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.11</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
{{#java8}}
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson-jaxrs-version}</version>
</dependency>
{{/java8}}
{{^java8}}
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>${jackson-jaxrs-version}</version>
</dependency>
{{/java8}}
{{#useBeanValidationFeature}}
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.2.Final</version>
</dependency>
{{/useBeanValidationFeature}}
</dependencies>
<repositories>
<repository>
<id>sonatype-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<swagger-core-version>1.5.18</swagger-core-version>
<jetty-version>9.2.9.v20150224</jetty-version>
<junit-version>4.12</junit-version>
<logback-version>1.1.7</logback-version>
<servlet-api-version>2.5</servlet-api-version>
{{#useBeanValidation}}
<beanvalidation-version>1.1.0.Final</beanvalidation-version>
{{/useBeanValidation}}
<cxf-version>3.2.7</cxf-version>
<jackson-jaxrs-version>2.9.7</jackson-jaxrs-version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -0,0 +1 @@
{{#isQueryParam}}@QueryParam("{{baseName}}"){{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}} {{^isContainer}}{{#defaultValue}}@DefaultValue({{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}) {{/defaultValue}}{{/isContainer}}{{{dataType}}} {{paramName}}{{/isQueryParam}}

View File

@ -0,0 +1 @@
{{#isQueryParam}}{{{dataType}}} {{paramName}}{{/isQueryParam}}

View File

@ -0,0 +1,4 @@
{{#useGenericResponse}}Response{{/useGenericResponse}}{{! non-generic response:
}}{{^useGenericResponse}}{{!
}}{{{returnType}}}{{!
}}{{/useGenericResponse}}