Skip to content

Commit 57b5967

Browse files
committed
Fix: Making unmarshalResponse type-safe
Signed-off-by: Emmanuel Hugonnet <[email protected]>
1 parent f820ca2 commit 57b5967

File tree

1 file changed

+30
-12
lines changed

1 file changed

+30
-12
lines changed

client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransport.java

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import io.a2a.spec.CancelTaskResponse;
2626

2727
import io.a2a.spec.DeleteTaskPushNotificationConfigParams;
28+
import io.a2a.spec.DeleteTaskPushNotificationConfigRequest;
29+
import io.a2a.spec.DeleteTaskPushNotificationConfigResponse;
2830
import io.a2a.spec.EventKind;
2931
import io.a2a.spec.GetAuthenticatedExtendedCardRequest;
3032
import io.a2a.spec.GetAuthenticatedExtendedCardResponse;
@@ -43,7 +45,6 @@
4345
import io.a2a.spec.ListTasksRequest;
4446
import io.a2a.spec.ListTasksResponse;
4547
import io.a2a.spec.ListTasksResult;
46-
import io.a2a.spec.DeleteTaskPushNotificationConfigRequest;
4748
import io.a2a.spec.MessageSendParams;
4849
import io.a2a.spec.SendMessageResponse;
4950
import io.a2a.spec.SendStreamingMessageRequest;
@@ -96,7 +97,7 @@ public EventKind sendMessage(MessageSendParams request, @Nullable ClientCallCont
9697

9798
try {
9899
String httpResponseBody = sendPostRequest(payloadAndHeaders,io.a2a.spec.SendMessageRequest.METHOD);
99-
SendMessageResponse response = (SendMessageResponse) unmarshalResponse(httpResponseBody, io.a2a.spec.SendMessageRequest.METHOD);
100+
SendMessageResponse response = unmarshalResponse(httpResponseBody, io.a2a.spec.SendMessageRequest.METHOD);
100101
return response.getResult();
101102
} catch (A2AClientException e) {
102103
throw e;
@@ -140,7 +141,7 @@ public Task getTask(TaskQueryParams request, @Nullable ClientCallContext context
140141

141142
try {
142143
String httpResponseBody = sendPostRequest(payloadAndHeaders, io.a2a.spec.GetTaskRequest.METHOD);
143-
GetTaskResponse response = (GetTaskResponse) unmarshalResponse(httpResponseBody, io.a2a.spec.GetTaskRequest.METHOD);
144+
GetTaskResponse response = unmarshalResponse(httpResponseBody, io.a2a.spec.GetTaskRequest.METHOD);
144145
return response.getResult();
145146
} catch (A2AClientException e) {
146147
throw e;
@@ -157,7 +158,7 @@ public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context
157158

158159
try {
159160
String httpResponseBody = sendPostRequest(payloadAndHeaders, CancelTaskRequest.METHOD);
160-
CancelTaskResponse response = (CancelTaskResponse) unmarshalResponse(httpResponseBody, CancelTaskRequest.METHOD);
161+
CancelTaskResponse response = unmarshalResponse(httpResponseBody, CancelTaskRequest.METHOD);
161162
return response.getResult();
162163
} catch (A2AClientException e) {
163164
throw e;
@@ -173,7 +174,7 @@ public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallCo
173174
agentCard, context);
174175
try {
175176
String httpResponseBody = sendPostRequest(payloadAndHeaders, ListTasksRequest.METHOD);
176-
ListTasksResponse response = (ListTasksResponse) unmarshalResponse(httpResponseBody, ListTasksRequest.METHOD);
177+
ListTasksResponse response = unmarshalResponse(httpResponseBody, ListTasksRequest.METHOD);
177178
return response.getResult();
178179
} catch (IOException | InterruptedException e) {
179180
throw new A2AClientException("Failed to list tasks: " + e, e);
@@ -189,7 +190,7 @@ public TaskPushNotificationConfig setTaskPushNotificationConfiguration(TaskPushN
189190

190191
try {
191192
String httpResponseBody = sendPostRequest(payloadAndHeaders, SetTaskPushNotificationConfigRequest.METHOD);
192-
SetTaskPushNotificationConfigResponse response = (SetTaskPushNotificationConfigResponse) unmarshalResponse(httpResponseBody,
193+
SetTaskPushNotificationConfigResponse response = unmarshalResponse(httpResponseBody,
193194
SetTaskPushNotificationConfigRequest.METHOD);
194195
return response.getResult();
195196
} catch (A2AClientException e) {
@@ -208,7 +209,7 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPu
208209

209210
try {
210211
String httpResponseBody = sendPostRequest(payloadAndHeaders,GetTaskPushNotificationConfigRequest.METHOD);
211-
GetTaskPushNotificationConfigResponse response = (GetTaskPushNotificationConfigResponse) unmarshalResponse(httpResponseBody,
212+
GetTaskPushNotificationConfigResponse response = unmarshalResponse(httpResponseBody,
212213
GetTaskPushNotificationConfigRequest.METHOD);
213214
return response.getResult();
214215
} catch (A2AClientException e) {
@@ -228,7 +229,7 @@ public List<TaskPushNotificationConfig> listTaskPushNotificationConfigurations(
228229

229230
try {
230231
String httpResponseBody = sendPostRequest(payloadAndHeaders, ListTaskPushNotificationConfigRequest.METHOD);
231-
ListTaskPushNotificationConfigResponse response = (ListTaskPushNotificationConfigResponse) unmarshalResponse(httpResponseBody,
232+
ListTaskPushNotificationConfigResponse response = unmarshalResponse(httpResponseBody,
232233
ListTaskPushNotificationConfigRequest.METHOD);
233234
return response.getResult();
234235
} catch (A2AClientException e) {
@@ -247,7 +248,8 @@ public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationC
247248

248249
try {
249250
String httpResponseBody = sendPostRequest(payloadAndHeaders,DeleteTaskPushNotificationConfigRequest.METHOD);
250-
unmarshalResponse(httpResponseBody, DeleteTaskPushNotificationConfigRequest.METHOD);
251+
DeleteTaskPushNotificationConfigResponse response = unmarshalResponse(httpResponseBody, DeleteTaskPushNotificationConfigRequest.METHOD);
252+
// Response validated (no error), but no result to return
251253
} catch (A2AClientException e) {
252254
throw e;
253255
} catch (IOException | InterruptedException e) {
@@ -306,7 +308,7 @@ public AgentCard getAgentCard(@Nullable ClientCallContext context) throws A2ACli
306308

307309
try {
308310
String httpResponseBody = sendPostRequest(payloadAndHeaders,GetAuthenticatedExtendedCardRequest.METHOD);
309-
GetAuthenticatedExtendedCardResponse response = (GetAuthenticatedExtendedCardResponse) unmarshalResponse(httpResponseBody,
311+
GetAuthenticatedExtendedCardResponse response = unmarshalResponse(httpResponseBody,
310312
GetAuthenticatedExtendedCardRequest.METHOD);
311313
agentCard = response.getResult();
312314
needsExtendedCard = false;
@@ -360,14 +362,30 @@ private A2AHttpClient.PostBuilder createPostBuilder(PayloadAndHeaders payloadAnd
360362
return postBuilder;
361363
}
362364

363-
private JSONRPCResponse<?> unmarshalResponse(String response, String method)
365+
/**
366+
* Unmarshals a JSON-RPC response string into a type-safe response object.
367+
* <p>
368+
* This method parses the JSON-RPC response body and returns the appropriate
369+
* response type based on the method parameter. If the response contains an error,
370+
* an A2AClientException is thrown.
371+
*
372+
* @param <T> the expected response type, must extend JSONRPCResponse
373+
* @param response the JSON-RPC response body as a string
374+
* @param method the method name used to determine the response type
375+
* @return the parsed response object of type T
376+
* @throws A2AClientException if the response contains an error or parsing fails
377+
* @throws JsonProcessingException if the JSON cannot be processed
378+
*/
379+
@SuppressWarnings("unchecked")
380+
private <T extends JSONRPCResponse<?>> T unmarshalResponse(String response, String method)
364381
throws A2AClientException, JsonProcessingException {
365382
JSONRPCResponse<?> value = JSONRPCUtils.parseResponseBody(response, method);
366383
JSONRPCError error = value.getError();
367384
if (error != null) {
368385
throw new A2AClientException(error.getMessage() + (error.getData() != null ? ": " + error.getData() : ""), error);
369386
}
370-
return value;
387+
// Safe cast: JSONRPCUtils.parseResponseBody returns the correct concrete type based on method
388+
return (T) value;
371389
}
372390

373391
private @Nullable Map<String, String> getHttpHeaders(@Nullable ClientCallContext context) {

0 commit comments

Comments
 (0)