From ee3997772680721b8cd15e8968a66dae48c85140 Mon Sep 17 00:00:00 2001 From: evigeant Date: Wed, 2 Dec 2015 14:20:29 -0500 Subject: [PATCH] Let Jersey do the serialization and deserialization (including JSON) --- .../codegen/languages/JavaClientCodegen.java | 4 +- .../main/resources/Java/ApiClient.mustache | 141 ++++-------------- .../src/main/resources/Java/JSON.mustache | 64 -------- .../src/main/resources/Java/TypeRef.mustache | 26 ---- .../src/main/resources/Java/api.mustache | 15 +- .../src/main/resources/Java/pom.mustache | 5 + 6 files changed, 39 insertions(+), 216 deletions(-) delete mode 100644 modules/swagger-codegen/src/main/resources/Java/JSON.mustache delete mode 100644 modules/swagger-codegen/src/main/resources/Java/TypeRef.mustache diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java index 2f77a4178378..06326d1e4dd2 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java @@ -234,7 +234,6 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { if (!("feign".equals(getLibrary()) || "retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary()))) { supportingFiles.add(new SupportingFile("apiException.mustache", invokerFolder, "ApiException.java")); supportingFiles.add(new SupportingFile("Configuration.mustache", invokerFolder, "Configuration.java")); - supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java")); supportingFiles.add(new SupportingFile("Pair.mustache", invokerFolder, "Pair.java")); supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java")); } @@ -244,6 +243,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { // the "okhttp-gson" library template requires "ApiCallback.mustache" for async call supportingFiles.add(new SupportingFile("ApiCallback.mustache", invokerFolder, "ApiCallback.java")); supportingFiles.add(new SupportingFile("ApiResponse.mustache", invokerFolder, "ApiResponse.java")); + supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java")); supportingFiles.add(new SupportingFile("ProgressRequestBody.mustache", invokerFolder, "ProgressRequestBody.java")); supportingFiles.add(new SupportingFile("ProgressResponseBody.mustache", invokerFolder, "ProgressResponseBody.java")); // "build.sbt" is for development with SBT @@ -251,8 +251,6 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { } else if ("retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary())) { supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java")); supportingFiles.add(new SupportingFile("CollectionFormats.mustache", invokerFolder, "CollectionFormats.java")); - } else if (!"feign".equals(getLibrary())) { - supportingFiles.add(new SupportingFile("TypeRef.mustache", invokerFolder, "TypeRef.java")); } } diff --git a/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache index 679297f033f4..ef31058d5619 100644 --- a/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache @@ -1,8 +1,13 @@ package {{invokerPackage}}; +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.datatype.joda.*; +import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; + import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.config.ClientConfig; +import com.sun.jersey.api.client.GenericType; import com.sun.jersey.api.client.config.DefaultClientConfig; import com.sun.jersey.api.client.filter.LoggingFilter; import com.sun.jersey.api.client.WebResource.Builder; @@ -25,14 +30,11 @@ import java.util.TimeZone; import java.net.URLEncoder; -import java.io.IOException; import java.io.File; import java.io.UnsupportedEncodingException; -import java.io.DataInputStream; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.text.ParseException; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; @@ -45,7 +47,7 @@ public class ApiClient { private Map defaultHeaderMap = new HashMap(); private boolean debugging = false; private String basePath = "{{basePath}}"; - private JSON json = new JSON(); + private ObjectMapper mapper; private Map authentications; @@ -55,6 +57,14 @@ public class ApiClient { private DateFormat dateFormat; public ApiClient() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.registerModule(new JodaModule()); + // Use RFC3339 format for date and datetime. // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); @@ -62,7 +72,7 @@ public class ApiClient { // Use UTC as the default time zone. this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - this.json.setDateFormat((DateFormat) dateFormat.clone()); + this.mapper.setDateFormat((DateFormat) dateFormat.clone()); // Set default User-Agent. setUserAgent("Java-Swagger"); @@ -76,13 +86,6 @@ public class ApiClient { authentications = Collections.unmodifiableMap(authentications); } - /** - * Gets the JSON instance to do JSON serialization and deserialization. - */ - public JSON getJSON() { - return json; - } - public String getBasePath() { return basePath; } @@ -237,7 +240,7 @@ public class ApiClient { public ApiClient setDateFormat(DateFormat dateFormat) { this.dateFormat = dateFormat; // also set the date format for model (de)serialization with Date properties - this.json.setDateFormat((DateFormat) dateFormat.clone()); + this.mapper.setDateFormat((DateFormat) dateFormat.clone()); return this; } @@ -269,7 +272,7 @@ public class ApiClient { return formatDate((Date) param); } else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); - for(Object o : (Collection)param) { + for(Object o : (Collection)param) { if(b.length() > 0) { b.append(","); } @@ -290,9 +293,9 @@ public class ApiClient { // preconditions if (name == null || name.isEmpty() || value == null) return params; - Collection valueCollection = null; - if (value instanceof Collection) { - valueCollection = (Collection) value; + Collection valueCollection = null; + if (value instanceof Collection) { + valueCollection = (Collection) value; } else { params.add(new Pair(name, parameterToString(value))); return params; @@ -406,9 +409,7 @@ public class ApiClient { * Content-Type (only JSON is supported for now). */ public Object serialize(Object obj, String contentType, Map formParams) throws ApiException { - if (isJsonMime(contentType)) { - return json.serialize(obj); - } else if (contentType.startsWith("multipart/form-data")) { + if (contentType.startsWith("multipart/form-data")) { FormDataMultiPart mp = new FormDataMultiPart(); for (Entry param: formParams.entrySet()) { if (param.getValue() instanceof File) { @@ -424,38 +425,6 @@ public class ApiClient { } else { // We let Jersey attempt to serialize the body return obj; - //throw new ApiException(400, "can not serialize object into Content-Type: " + contentType); - } - } - - /** - * Deserialize response body to Java object according to the Content-Type. - */ - public T deserialize(ClientResponse response, TypeRef returnType) throws ApiException { - String contentType = null; - List contentTypes = response.getHeaders().get("Content-Type"); - if (contentTypes != null && !contentTypes.isEmpty()) - contentType = contentTypes.get(0); - if (contentType == null) - throw new ApiException(500, "missing Content-Type in response"); - - String body; - if (response.hasEntity()) - body = (String) response.getEntity(String.class); - else - body = ""; - - if (isJsonMime(contentType)) { - return json.deserialize(body, returnType); - } else if (returnType.getType().equals(String.class)) { - // Expecting string, return the raw response body. - return (T) body; - } else { - throw new ApiException( - 500, - "Content type \"" + contentType + "\" is not supported for type: " - + returnType.getType() - ); } } @@ -522,7 +491,6 @@ public class ApiClient { * @param method The request method, one of "GET", "POST", "PUT", and "DELETE" * @param queryParams The query parameters * @param body The request body object - if it is not binary, otherwise null - * @param binaryBody The request body object - if it is binary, otherwise null * @param headerParams The header parameters * @param formParams The form parameters * @param accept The request's Accept header @@ -530,7 +498,7 @@ public class ApiClient { * @param authNames The authentications to apply * @return The response body in type of string */ - public T invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames, TypeRef returnType) throws ApiException { + public T invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { ClientResponse response = getAPIResponse(path, method, queryParams, body, headerParams, formParams, accept, contentType, authNames); @@ -543,13 +511,13 @@ public class ApiClient { if (returnType == null) return null; else - return deserialize(response, returnType); + return response.getEntity(returnType); } else { String message = "error"; String respBody = null; if (response.hasEntity()) { try { - respBody = String.valueOf(response.getEntity(String.class)); + respBody = response.getEntity(String.class); message = respBody; } catch (RuntimeException e) { // e.printStackTrace(); @@ -562,58 +530,6 @@ public class ApiClient { respBody); } } - /** - * Invoke API by sending HTTP request with the given options - return binary result - * - * @param path The sub-path of the HTTP URL - * @param method The request method, one of "GET", "POST", "PUT", and "DELETE" - * @param queryParams The query parameters - * @param body The request body object - if it is not binary, otherwise null - * @param binaryBody The request body object - if it is binary, otherwise null - * @param headerParams The header parameters - * @param formParams The form parameters - * @param accept The request's Accept header - * @param contentType The request's Content-Type header - * @param authNames The authentications to apply - * @return The response body in type of string - */ - public byte[] invokeBinaryAPI(String path, String method, List queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[]authNames) throws ApiException { - - ClientResponse response = getAPIResponse(path, method, queryParams, body, headerParams, formParams, accept, contentType, authNames); - - if(response.getStatusInfo() == ClientResponse.Status.NO_CONTENT) { - return null; - } - else if(response.getStatusInfo().getFamily() == Family.SUCCESSFUL) { - if(response.hasEntity()) { - DataInputStream stream = new DataInputStream(response.getEntityInputStream()); - byte[] data = new byte[response.getLength()]; - try { - stream.readFully(data); - } catch (IOException ex) { - throw new ApiException(500, "Error obtaining binary response data"); - } - return data; - } - else { - return new byte[0]; - } - } - else { - String message = "error"; - if(response.hasEntity()) { - try{ - message = String.valueOf(response.getEntity(String.class)); - } - catch (RuntimeException e) { - // e.printStackTrace(); - } - } - throw new ApiException( - response.getStatusInfo().getStatusCode(), - message); - } - } /** * Update query and header parameters based on authentication settings. @@ -635,7 +551,6 @@ public class ApiClient { StringBuilder formParamBuilder = new StringBuilder(); for (Entry param : formParams.entrySet()) { - String keyStr = param.getKey(); String valueStr = parameterToString(param.getValue()); try { formParamBuilder.append(URLEncoder.encode(param.getKey(), "utf8")) @@ -660,7 +575,11 @@ public class ApiClient { */ private Client getClient() { if(!hostMap.containsKey(basePath)) { - Client client = Client.create(); + // Add the JSON serialization support to Jersey + JacksonJsonProvider jsonProvider = new JacksonJsonProvider(mapper); + DefaultClientConfig conf = new DefaultClientConfig(); + conf.getSingletons().add(jsonProvider); + Client client = Client.create(conf); if (debugging) client.addFilter(new LoggingFilter()); hostMap.put(basePath, client); diff --git a/modules/swagger-codegen/src/main/resources/Java/JSON.mustache b/modules/swagger-codegen/src/main/resources/Java/JSON.mustache deleted file mode 100644 index 54faed8dcb38..000000000000 --- a/modules/swagger-codegen/src/main/resources/Java/JSON.mustache +++ /dev/null @@ -1,64 +0,0 @@ -package {{invokerPackage}}; - -import com.fasterxml.jackson.annotation.*; -import com.fasterxml.jackson.databind.*; -import com.fasterxml.jackson.datatype.joda.*; - -import java.text.DateFormat; - -import java.io.IOException; - -{{>generatedAnnotation}} -public class JSON { - private ObjectMapper mapper; - - public JSON() { - mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); - mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); - mapper.registerModule(new JodaModule()); - } - - /** - * Set the date format for JSON (de)serialization with Date properties. - */ - public void setDateFormat(DateFormat dateFormat) { - mapper.setDateFormat(dateFormat); - } - - /** - * Serialize the given Java object into JSON string. - */ - public String serialize(Object obj) throws ApiException { - try { - if (obj != null) - return mapper.writeValueAsString(obj); - else - return null; - } catch (Exception e) { - throw new ApiException(400, e.getMessage()); - } - } - - /** - * Deserialize the given JSON string to Java object. - * - * @param body The JSON string - * @param returnType The type to deserialize inot - * @return The deserialized Java object - */ - public T deserialize(String body, TypeRef returnType) throws ApiException { - JavaType javaType = mapper.constructType(returnType.getType()); - try { - return mapper.readValue(body, javaType); - } catch (IOException e) { - if (returnType.getType().equals(String.class)) - return (T) body; - else - throw new ApiException(500, e.getMessage(), null, body); - } - } -} diff --git a/modules/swagger-codegen/src/main/resources/Java/TypeRef.mustache b/modules/swagger-codegen/src/main/resources/Java/TypeRef.mustache deleted file mode 100644 index 9e9ba5f88956..000000000000 --- a/modules/swagger-codegen/src/main/resources/Java/TypeRef.mustache +++ /dev/null @@ -1,26 +0,0 @@ -package {{invokerPackage}}; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; - -{{>generatedAnnotation}} -public class TypeRef { - private final Type type; - - public TypeRef() { - this.type = getGenericType(getClass()); - } - - private static Type getGenericType(Class klass) { - Type superclass = klass.getGenericSuperclass(); - if (superclass instanceof Class) { - throw new RuntimeException("No type parameter provided"); - } - ParameterizedType parameterized = (ParameterizedType) superclass; - return parameterized.getActualTypeArguments()[0]; - } - - public Type getType() { - return type; - } -} diff --git a/modules/swagger-codegen/src/main/resources/Java/api.mustache b/modules/swagger-codegen/src/main/resources/Java/api.mustache index fbdcc3d25e71..fc441df954a7 100644 --- a/modules/swagger-codegen/src/main/resources/Java/api.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/api.mustache @@ -1,10 +1,11 @@ package {{package}}; +import com.sun.jersey.api.client.GenericType; + import {{invokerPackage}}.ApiException; import {{invokerPackage}}.ApiClient; import {{invokerPackage}}.Configuration; import {{invokerPackage}}.Pair; -import {{invokerPackage}}.TypeRef; {{#imports}}import {{import}}; {{/imports}} @@ -82,22 +83,12 @@ public class {{classname}} { String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; - {{#isResponseBinary}} - byte[] {{localVariablePrefix}}response = null; - {{localVariablePrefix}}response = {{localVariablePrefix}}apiClient.invokeBinaryAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams,{{localVariablePrefix}} postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames); - return {{localVariablePrefix}}response; - {{/isResponseBinary}} - - {{^isResponseBinary}} {{#returnType}} - TypeRef {{localVariablePrefix}}returnType = new TypeRef<{{{returnType}}}>() {}; + GenericType<{{{returnType}}}> {{localVariablePrefix}}returnType = new GenericType<{{{returnType}}}>() {}; return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, {{localVariablePrefix}}returnType); {{/returnType}}{{^returnType}} {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, null); {{/returnType}} - {{/isResponseBinary}} - - } {{/operation}} } diff --git a/modules/swagger-codegen/src/main/resources/Java/pom.mustache b/modules/swagger-codegen/src/main/resources/Java/pom.mustache index c5bfbc65b746..f2c20a96740b 100644 --- a/modules/swagger-codegen/src/main/resources/Java/pom.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/pom.mustache @@ -137,6 +137,11 @@ jackson-databind ${jackson-version} + + com.fasterxml.jackson.jaxrs + jackson-jaxrs-json-provider + ${jackson-version} + com.fasterxml.jackson.datatype jackson-datatype-joda