Return OkHttp异步结果有问题
Return OkHttp Asynchronous result has some problem
我有一个 java SDK
,它使用 OkHttp
客户端(4.0.0)从 IAM
server and return token to application.The relation may like this:Applicaiton Sync call SDK
,SDK
Async call IAM
.Refer to this answer, 代码如:
异步Class:
class BaseAsyncResult<T> {
private final CompletableFuture<T> future = new CompletableFuture<>();
T getResult() {
try {
return future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return null;
}
void onFailure(IOException e) {
future.completeExceptionally(e);
}
void onResponse(Response response) throws IOException {
String bodyString = Objects.requireNonNull(response.body()).string();
future.complete(IasClientJsonUtil.json2Pojo(bodyString, new TypeReference<T>() {}));
}
}
Okhttp 调用如下:
public void invoke(Request request, BaseAsyncResult result) {
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
result.onFailure(e);
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
result.onResponse(response);
}
});
}
应用程序使用 sdk 代码,iasClient 是 okhttp 客户端的包装器:
BaseAsyncResult<AuthenticationResponse> iasAsyncResult = new BaseAsyncResult();
iasClient.invoke(request, iasAsyncResult);
AuthenticationResponse result = iasAsyncResult.getResult();
错误信息:
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to x.x.x.AuthenticationResponse
我错过了什么?
您需要确保 jackson 知道哪个 class 将值反序列化为 。在这种情况下,您要求 Jackson 将响应反序列化为 TypeReference ,默认情况下它将解析为 Map 除非您指定 class (在本例中为 AuthenticationResponse )。因此,Future 解析为 linkedHashMap 并导致 class 强制转换。
尝试替换下面的行。
future.complete(IasClientJsonUtil.json2Pojo(bodyString, new TypeReference<T>() {}));
和
future.complete(IasClientJsonUtil.json2Pojo(bodyString, new TypeReference<AuthenticationResponse>() {}));
@Arpan Kanthal 的一种方法是向 BaseAsyncResult 添加一个私有 Class 类型变量,然后在您的 json2Pojo 函数中使用该 class,然后 BaseAsyncResult 可能如下所示:
public class BaseAsyncResult<T> {
private final CompletableFuture<T> future = new CompletableFuture<>();
private Class<T> classType;
public BaseAsyncResult(Class<T> classType) {
this.classType = classType;
}
public T getResult() {
try {
return future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return null;
}
void onFailure(IOException e) {
future.completeExceptionally(e);
}
void onResponse(Response response) throws IOException {
future.complete(JacksonUtil.json2Pojo(response.body().string(), classType));
}
}
我有一个 java SDK
,它使用 OkHttp
客户端(4.0.0)从 IAM
server and return token to application.The relation may like this:Applicaiton Sync call SDK
,SDK
Async call IAM
.Refer to this answer
异步Class:
class BaseAsyncResult<T> {
private final CompletableFuture<T> future = new CompletableFuture<>();
T getResult() {
try {
return future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return null;
}
void onFailure(IOException e) {
future.completeExceptionally(e);
}
void onResponse(Response response) throws IOException {
String bodyString = Objects.requireNonNull(response.body()).string();
future.complete(IasClientJsonUtil.json2Pojo(bodyString, new TypeReference<T>() {}));
}
}
Okhttp 调用如下:
public void invoke(Request request, BaseAsyncResult result) {
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
result.onFailure(e);
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
result.onResponse(response);
}
});
}
应用程序使用 sdk 代码,iasClient 是 okhttp 客户端的包装器:
BaseAsyncResult<AuthenticationResponse> iasAsyncResult = new BaseAsyncResult();
iasClient.invoke(request, iasAsyncResult);
AuthenticationResponse result = iasAsyncResult.getResult();
错误信息:
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to x.x.x.AuthenticationResponse
我错过了什么?
您需要确保 jackson 知道哪个 class 将值反序列化为 。在这种情况下,您要求 Jackson 将响应反序列化为 TypeReference ,默认情况下它将解析为 Map 除非您指定 class (在本例中为 AuthenticationResponse )。因此,Future 解析为 linkedHashMap 并导致 class 强制转换。 尝试替换下面的行。
future.complete(IasClientJsonUtil.json2Pojo(bodyString, new TypeReference<T>() {}));
和
future.complete(IasClientJsonUtil.json2Pojo(bodyString, new TypeReference<AuthenticationResponse>() {}));
@Arpan Kanthal 的一种方法是向 BaseAsyncResult 添加一个私有 Class 类型变量,然后在您的 json2Pojo 函数中使用该 class,然后 BaseAsyncResult 可能如下所示:
public class BaseAsyncResult<T> {
private final CompletableFuture<T> future = new CompletableFuture<>();
private Class<T> classType;
public BaseAsyncResult(Class<T> classType) {
this.classType = classType;
}
public T getResult() {
try {
return future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return null;
}
void onFailure(IOException e) {
future.completeExceptionally(e);
}
void onResponse(Response response) throws IOException {
future.complete(JacksonUtil.json2Pojo(response.body().string(), classType));
}
}