From 14b808a9100e17416fd4fe195e8a9222b800caf0 Mon Sep 17 00:00:00 2001 From: xhh Date: Wed, 29 Jul 2015 17:10:49 +0800 Subject: [PATCH 1/2] Retrofit template: return body string directly when failed to parse response body as JSON, fixing unit test for UserApi#loginUser --- .../main/resources/retrofit/service.mustache | 68 ++++++++++++++++++- .../io/swagger/client/ServiceGenerator.java | 68 ++++++++++++++++++- .../java/io/swagger/client/api/PetApi.java | 4 +- .../java/io/swagger/client/model/Pet.java | 4 +- .../io/swagger/petstore/test/PetApiTest.java | 2 +- 5 files changed, 139 insertions(+), 7 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/retrofit/service.mustache b/modules/swagger-codegen/src/main/resources/retrofit/service.mustache index 218a9304071..5f2a6f48009 100644 --- a/modules/swagger-codegen/src/main/resources/retrofit/service.mustache +++ b/modules/swagger-codegen/src/main/resources/retrofit/service.mustache @@ -2,8 +2,20 @@ package {{invokerPackage}}; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.lang.reflect.Type; + import retrofit.RestAdapter; +import retrofit.converter.ConversionException; +import retrofit.converter.Converter; import retrofit.converter.GsonConverter; +import retrofit.mime.TypedByteArray; +import retrofit.mime.TypedInput; +import retrofit.mime.TypedOutput; public class ServiceGenerator { // No need to instantiate this class. @@ -15,9 +27,63 @@ public class ServiceGenerator { .create(); RestAdapter adapter = new RestAdapter.Builder() .setEndpoint("{{basePath}}") - .setConverter(new GsonConverter(gson)) + .setConverter(new GsonConverterWrapper(gson)) .build(); return adapter.create(serviceClass); } } + +/** + * This wrapper is to take case this case: + * when the deserialization fails due to JsonParseException and the + * expected type is String, then just return the body string. + */ +class GsonConverterWrapper implements Converter { + private GsonConverter converter; + + public GsonConverterWrapper(Gson gson) { + converter = new GsonConverter(gson); + } + + @Override public Object fromBody(TypedInput body, Type type) throws ConversionException { + byte[] bodyBytes = readInBytes(body); + TypedByteArray newBody = new TypedByteArray(body.mimeType(), bodyBytes); + try { + return converter.fromBody(newBody, type); + } catch (ConversionException e) { + if (e.getCause() instanceof JsonParseException && type.equals(String.class)) { + return new String(bodyBytes); + } else { + throw e; + } + } + } + + @Override public TypedOutput toBody(Object object) { + return converter.toBody(object); + } + + private byte[] readInBytes(TypedInput body) throws ConversionException { + InputStream in = null; + try { + in = body.in(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + byte[] buffer = new byte[0xFFFF]; + for (int len; (len = in.read(buffer)) != -1;) + os.write(buffer, 0, len); + os.flush(); + return os.toByteArray(); + } catch (IOException e) { + throw new ConversionException(e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ignored) { + } + } + } + + } +} diff --git a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/ServiceGenerator.java b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/ServiceGenerator.java index e443c984fd0..fde79ce60ea 100644 --- a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/ServiceGenerator.java +++ b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/ServiceGenerator.java @@ -2,8 +2,20 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.lang.reflect.Type; + import retrofit.RestAdapter; +import retrofit.converter.ConversionException; +import retrofit.converter.Converter; import retrofit.converter.GsonConverter; +import retrofit.mime.TypedByteArray; +import retrofit.mime.TypedInput; +import retrofit.mime.TypedOutput; public class ServiceGenerator { // No need to instantiate this class. @@ -15,9 +27,63 @@ public static S createService(Class serviceClass) { .create(); RestAdapter adapter = new RestAdapter.Builder() .setEndpoint("http://petstore.swagger.io/v2") - .setConverter(new GsonConverter(gson)) + .setConverter(new GsonConverterWrapper(gson)) .build(); return adapter.create(serviceClass); } } + +/** + * This wrapper is to take case this case: + * when the deserialization fails due to JsonParseException and the + * expected type is String, then just return the body string. + */ +class GsonConverterWrapper implements Converter { + private GsonConverter converter; + + public GsonConverterWrapper(Gson gson) { + converter = new GsonConverter(gson); + } + + @Override public Object fromBody(TypedInput body, Type type) throws ConversionException { + byte[] bodyBytes = readInBytes(body); + TypedByteArray newBody = new TypedByteArray(body.mimeType(), bodyBytes); + try { + return converter.fromBody(newBody, type); + } catch (ConversionException e) { + if (e.getCause() instanceof JsonParseException && type.equals(String.class)) { + return new String(bodyBytes); + } else { + throw e; + } + } + } + + @Override public TypedOutput toBody(Object object) { + return converter.toBody(object); + } + + private byte[] readInBytes(TypedInput body) throws ConversionException { + InputStream in = null; + try { + in = body.in(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + byte[] buffer = new byte[0xFFFF]; + for (int len; (len = in.read(buffer)) != -1;) + os.write(buffer, 0, len); + os.flush(); + return os.toByteArray(); + } catch (IOException e) { + throw new ConversionException(e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ignored) { + } + } + } + + } +} diff --git a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/PetApi.java b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/PetApi.java index 3d1b0893b61..90611a5cbac 100644 --- a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/PetApi.java +++ b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/PetApi.java @@ -89,14 +89,14 @@ Void updatePetWithForm( /** * Deletes a pet * - * @param apiKey * @param petId Pet id to delete + * @param apiKey * @return Void */ @DELETE("/pet/{petId}") Void deletePet( - @Header("api_key") String apiKey,@Path("petId") Long petId + @Path("petId") Long petId,@Header("api_key") String apiKey ); /** diff --git a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Pet.java b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Pet.java index af9ba8880e0..f74264708e3 100644 --- a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Pet.java +++ b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Pet.java @@ -34,13 +34,13 @@ public class Pet { **/ @ApiModelProperty(required = true, value = "") @SerializedName("photoUrls") - private List photoUrls = new ArrayList() ; + private List photoUrls = null; /** **/ @ApiModelProperty(value = "") @SerializedName("tags") - private List tags = new ArrayList() ; + private List tags = null; public enum StatusEnum { available, pending, sold, }; diff --git a/samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/PetApiTest.java b/samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/PetApiTest.java index 5151c941cd4..e7613f189a3 100644 --- a/samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/PetApiTest.java +++ b/samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/PetApiTest.java @@ -120,7 +120,7 @@ public void testDeletePet() throws Exception { api.addPet(pet); Pet fetched = api.getPetById(pet.getId()); - api.deletePet(null, fetched.getId()); + api.deletePet(fetched.getId(), null); try { fetched = api.getPetById(fetched.getId()); From 2d4c07a474e7f4a0b8033d865efee0b0bec091f6 Mon Sep 17 00:00:00 2001 From: xhh Date: Thu, 30 Jul 2015 15:01:51 +0800 Subject: [PATCH 2/2] Fix typo --- .../src/main/resources/retrofit/service.mustache | 2 +- .../src/main/java/io/swagger/client/ServiceGenerator.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/retrofit/service.mustache b/modules/swagger-codegen/src/main/resources/retrofit/service.mustache index 5f2a6f48009..df6d61b7ab8 100644 --- a/modules/swagger-codegen/src/main/resources/retrofit/service.mustache +++ b/modules/swagger-codegen/src/main/resources/retrofit/service.mustache @@ -35,7 +35,7 @@ public class ServiceGenerator { } /** - * This wrapper is to take case this case: + * This wrapper is to take care of this case: * when the deserialization fails due to JsonParseException and the * expected type is String, then just return the body string. */ diff --git a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/ServiceGenerator.java b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/ServiceGenerator.java index fde79ce60ea..1ffb0c58b0c 100644 --- a/samples/client/petstore/retrofit/src/main/java/io/swagger/client/ServiceGenerator.java +++ b/samples/client/petstore/retrofit/src/main/java/io/swagger/client/ServiceGenerator.java @@ -35,7 +35,7 @@ public static S createService(Class serviceClass) { } /** - * This wrapper is to take case this case: + * This wrapper is to take care of this case: * when the deserialization fails due to JsonParseException and the * expected type is String, then just return the body string. */