Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TransactionDetailsApi.getTransaction "declares multiple JSON fields named next" error #111

Open
DanDodin-SRPMIC opened this issue Jun 30, 2022 · 3 comments

Comments

@DanDodin-SRPMIC
Copy link

DanDodin-SRPMIC commented Jun 30, 2022

When I call TransactionDetailsApi.getTransaction I receive an error. This error can be reproduced using samples.TransactionDetails.RetrieveTransaction from cybersource-rest-samples-java. The error message below is from the rest samples call. I am using cybersource-rest-client-java version 0.0.46.

java.lang.IllegalArgumentException: jdk.internal.ref.PhantomCleanable<?> declares multiple JSON fields named next
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:172)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:102)
at com.google.gson.Gson.getAdapter(Gson.java:489)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:117)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:166)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:102)
at com.google.gson.Gson.getAdapter(Gson.java:489)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:56)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
at com.google.gson.Gson.toJson(Gson.java:735)
at com.google.gson.Gson.toJson(Gson.java:714)
at com.google.gson.Gson.toJson(Gson.java:669)
at com.google.gson.Gson.toJson(Gson.java:649)
at Invokers.JSON.serialize(JSON.java:83)
at Invokers.ApiClient.execute(ApiClient.java:1204)
at Api.TransactionDetailsApi.getTransactionWithHttpInfo(TransactionDetailsApi.java:159)
at Api.TransactionDetailsApi.getTransaction(TransactionDetailsApi.java:144)
at samples.TransactionDetails.RetrieveTransaction.run(RetrieveTransaction.java:42)
at samples.TransactionDetails.RetrieveTransaction.main(RetrieveTransaction.java:26)

@MrForms
Copy link

MrForms commented Jul 26, 2022

Invokers.ApiClient uses a new JSON(this), which in turns creates a GSON instance using a GsonBuilder that does not use 'excludeFieldsWithoutExposeAnnotation'.

At some point it will therefore rely on some form of reflection and hit classes such as collections, or other complex objects that might expose the same method name through out the inheritance hierarchy.

Perhaps the workaround would simply be to add the .excludeFieldsWithoutExposeAnnotation() method to the GsonBuilder line in the JSON constructor class, assuming you can add @expose

@DanDodin-SRPMIC
Copy link
Author

I don't think adding .excludeFieldsWithoutExposeAnnotation() will work. Class TssV2TransactionsGet200Response is autogenerated from swagger. The GSON @expose annotation is not added to fields.

As a work around I am using Jackson instead of GSON to parse the response in my code.
Replaced:
TssV2TransactionsGet200Response resp = apiInstance.getTransaction(transactionNumber);

With:

Call call = apiInstance.getTransactionCall(transactionNumber, null, null);
Response response = call.execute();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
TssV2TransactionsGet200Response resp =
    objectMapper.readValue(response.body().bytes(), TssV2TransactionsGet200Response.class);

@MrForms
Copy link

MrForms commented Jul 26, 2022

@DanDodin-SRPMIC Good point. Was thinking that the @expose could be added, but that would mean updating the definitions of the response objects for swagger.

I ended up hacking the ApiClient to specify my own JSON instance and just overrode the serialize method to use Jackson like you suggested. That worked.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants