Simplified Jersey2 java client by letting Jersey do most serialization

and deserialization
This commit is contained in:
evigeant 2015-12-08 22:23:27 -05:00
parent d51746d7fa
commit 0f67be5590
4 changed files with 79 additions and 66 deletions

View File

@ -6,6 +6,7 @@ import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
@ -29,13 +30,11 @@ import java.util.TimeZone;
import java.net.URLEncoder;
import java.io.IOException;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import {{invokerPackage}}.auth.Authentication;
import {{invokerPackage}}.auth.HttpBasicAuth;
@ -412,18 +411,39 @@ public class ApiClient {
* Serialize the given Java object into string entity according the given
* Content-Type (only JSON is supported for now).
*/
public Entity<String> serialize(Object obj, String contentType) throws ApiException {
if (isJsonMime(contentType)) {
return Entity.json(json.serialize(obj));
public Entity<?> serialize(Object obj, Map<String, Object> formParams, String contentType) throws ApiException {
Entity<?> entity = null;
if (contentType.startsWith("multipart/form-data")) {
MultiPart multiPart = new MultiPart();
for (Entry<String, Object> param: formParams.entrySet()) {
if (param.getValue() instanceof File) {
File file = (File) param.getValue();
FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey())
.fileName(file.getName()).size(file.length()).build();
multiPart.bodyPart(new FormDataBodyPart(contentDisp, file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
} else {
throw new ApiException(400, "can not serialize object into Content-Type: " + contentType);
FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey()).build();
multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(param.getValue())));
}
}
entity = Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE);
} else if (contentType.startsWith("application/x-www-form-urlencoded")) {
Form form = new Form();
for (Entry<String, Object> param: formParams.entrySet()) {
form.param(param.getKey(), parameterToString(param.getValue()));
}
entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE);
} else {
// We let jersey handle the serialization
entity = Entity.entity(obj, contentType);
}
return entity;
}
/**
* Deserialize response body to Java object according to the Content-Type.
*/
public <T> T deserialize(Response response, TypeRef returnType) throws ApiException {
public <T> T deserialize(Response response, GenericType<T> returnType) throws ApiException {
String contentType = null;
List<Object> contentTypes = response.getHeaders().get("Content-Type");
if (contentTypes != null && !contentTypes.isEmpty())
@ -431,24 +451,7 @@ public class ApiClient {
if (contentType == null)
throw new ApiException(500, "missing Content-Type in response");
String body;
if (response.hasEntity())
body = (String) response.readEntity(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()
);
}
return response.readEntity(returnType);
}
/**
@ -466,7 +469,7 @@ public class ApiClient {
* @param returnType The return type into which to deserialize the response
* @return The response body in type of string
*/
public <T> T invokeAPI(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames, TypeRef returnType) throws ApiException {
public <T> T invokeAPI(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames, GenericType<T> returnType) throws ApiException {
updateParamsForAuth(authNames, queryParams, headerParams);
WebTarget target = client.target(this.basePath).path(path);
@ -497,50 +500,16 @@ public class ApiClient {
}
}
Entity<?> formEntity = null;
if (contentType.startsWith("multipart/form-data")) {
MultiPart multiPart = new MultiPart();
for (Entry<String, Object> param: formParams.entrySet()) {
if (param.getValue() instanceof File) {
File file = (File) param.getValue();
FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey())
.fileName(file.getName()).size(file.length()).build();
multiPart.bodyPart(new FormDataBodyPart(contentDisp, file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
} else {
FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey()).build();
multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(param.getValue())));
}
}
formEntity = Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE);
} else if (contentType.startsWith("application/x-www-form-urlencoded")) {
Form form = new Form();
for (Entry<String, Object> param: formParams.entrySet()) {
form.param(param.getKey(), parameterToString(param.getValue()));
}
formEntity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE);
}
Entity<?> entity = serialize(body, formParams, contentType);
Response response = null;
if ("GET".equals(method)) {
response = invocationBuilder.get();
} else if ("POST".equals(method)) {
if (formEntity != null) {
response = invocationBuilder.post(formEntity);
} else if (body == null) {
response = invocationBuilder.post(null);
} else {
response = invocationBuilder.post(serialize(body, contentType));
}
response = invocationBuilder.post(entity);
} else if ("PUT".equals(method)) {
if (formEntity != null) {
response = invocationBuilder.put(formEntity);
} else if (body == null) {
response = invocationBuilder.put(null);
} else {
response = invocationBuilder.put(serialize(body, contentType));
}
response = invocationBuilder.put(entity);
} else if ("DELETE".equals(method)) {
response = invocationBuilder.delete();
} else {
@ -579,6 +548,8 @@ public class ApiClient {
private void buildClient() {
final ClientConfig clientConfig = new ClientConfig();
clientConfig.register(MultiPartFeature.class);
clientConfig.register(json);
clientConfig.register(org.glassfish.jersey.jackson.JacksonFeature.class);
if (debugging) {
clientConfig.register(LoggingFilter.class);
}

View File

@ -0,0 +1,36 @@
package {{invokerPackage}};
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.joda.*;
import java.text.DateFormat;
import javax.ws.rs.ext.ContextResolver;
{{>generatedAnnotation}}
public class JSON implements ContextResolver<ObjectMapper> {
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);
}
@Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}

View File

@ -4,7 +4,8 @@ import {{invokerPackage}}.ApiException;
import {{invokerPackage}}.ApiClient;
import {{invokerPackage}}.Configuration;
import {{invokerPackage}}.Pair;
import {{invokerPackage}}.TypeRef;
import javax.ws.rs.core.GenericType;
{{#imports}}import {{import}};
{{/imports}}
@ -83,7 +84,7 @@ public class {{classname}} {
String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
{{#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);

View File

@ -124,6 +124,11 @@
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.22.1</version>
</dependency>
<!-- JSON processing: jackson -->
<dependency>