Skip to content

Commit ba9616f

Browse files
committed
fix: Fix A2AServerRoutes streaming handling and test JSON format
Fixed two issues in the JSON-RPC reference implementation: 1. A2AServerRoutes.java (lines 101-106): - Removed invalid cast of streaming requests to NonStreamingJSONRPCRequest - Added streaming = true flag for proper streaming request routing - This was causing ClassCastException for streaming requests 2. A2AServerRoutesTest.java: - Updated all test JSON from domain format to protobuf JSON format - Changed Message parts from {"kind": "text", "text": "..."} to {"text": "..."} - Changed role from "user" to "ROLE_USER" (protobuf enum format) - Updated all request params to use protobuf field names: * GetTask/CancelTask/SubscribeToTask: "id" -> "name" (resource name format) * SetTaskPushNotificationConfig: restructured to use parent/configId/config * GetTaskPushNotificationConfig: full resource name format * ListTaskPushNotificationConfig: "id" -> "parent" * DeleteTaskPushNotificationConfig: full resource name format All 10 tests in A2AServerRoutesTest now pass.
1 parent 08f4e20 commit ba9616f

File tree

2 files changed

+39
-41
lines changed

2 files changed

+39
-41
lines changed

reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/A2AServerRoutes.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ public class A2AServerRoutes {
8989
@Route(path = "/", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING)
9090
@Authenticated
9191
public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) {
92-
9392
boolean streaming = false;
9493
ServerCallContext context = createCallContext(rc);
9594
JSONRPCResponse<?> nonStreamingResponse = null;
@@ -101,8 +100,8 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) {
101100
if (request instanceof NonStreamingJSONRPCRequest nonStreamingRequest) {
102101
nonStreamingResponse = processNonStreamingRequest(nonStreamingRequest, context);
103102
} else {
103+
streaming = true;
104104
streamingResponse = processStreamingRequest(request, context);
105-
nonStreamingResponse = processNonStreamingRequest((NonStreamingJSONRPCRequest<?>) request, context);
106105
}
107106
} catch (JsonProcessingException e) {
108107
error = handleError(e);

reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2AServerRoutesTest.java

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -95,28 +95,27 @@ public void setUp() {
9595

9696
@Test
9797
public void testSendMessage_MethodNameSetInContext() {
98-
// Arrange - using valid JSON from JsonMessages test file
98+
// Arrange - using protobuf JSON format
9999
String jsonRpcRequest = """
100100
{
101101
"jsonrpc": "2.0",
102102
"method": "SendMessage",
103103
"params": {
104104
"message": {
105-
"role": "user",
105+
"messageId": "message-1234",
106+
"contextId": "context-1234",
107+
"role": "ROLE_USER",
106108
"parts": [
107109
{
108-
"kind": "text",
109110
"text": "tell me a joke"
110111
}
111112
],
112-
"messageId": "message-1234",
113-
"contextId": "context-1234",
114-
"kind": "message"
113+
"metadata": {}
115114
},
116115
"configuration": {
117-
"acceptedOutputModes": ["text"],
118-
"blocking": true
119-
}
116+
"acceptedOutputModes": ["text"]
117+
},
118+
"metadata": {}
120119
}
121120
}""";
122121
when(mockRequestBody.asString()).thenReturn(jsonRpcRequest);
@@ -139,28 +138,27 @@ public void testSendMessage_MethodNameSetInContext() {
139138

140139
@Test
141140
public void testSendStreamingMessage_MethodNameSetInContext() {
142-
// Arrange - using the same valid format as testSendMessage
141+
// Arrange - using protobuf JSON format
143142
String jsonRpcRequest = """
144143
{
145144
"jsonrpc": "2.0",
146145
"method": "SendStreamingMessage",
147146
"params": {
148147
"message": {
149-
"role": "user",
148+
"messageId": "message-1234",
149+
"contextId": "context-1234",
150+
"role": "ROLE_USER",
150151
"parts": [
151152
{
152-
"kind": "text",
153153
"text": "tell me a joke"
154154
}
155155
],
156-
"messageId": "message-1234",
157-
"contextId": "context-1234",
158-
"kind": "message"
156+
"metadata": {}
159157
},
160158
"configuration": {
161-
"acceptedOutputModes": ["text"],
162-
"blocking": true
163-
}
159+
"acceptedOutputModes": ["text"]
160+
},
161+
"metadata": {}
164162
}
165163
}""";
166164
when(mockRequestBody.asString()).thenReturn(jsonRpcRequest);
@@ -185,13 +183,13 @@ public void testSendStreamingMessage_MethodNameSetInContext() {
185183

186184
@Test
187185
public void testGetTask_MethodNameSetInContext() {
188-
// Arrange - based on GET_TASK_TEST_REQUEST from JsonMessages
186+
// Arrange - using protobuf JSON format
189187
String jsonRpcRequest = """
190188
{
191189
"jsonrpc": "2.0",
192190
"method": "GetTask",
193191
"params": {
194-
"id": "de38c76d-d54c-436c-8b9f-4c2703648d64",
192+
"name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64",
195193
"historyLength": 10
196194
}
197195
}""";
@@ -215,14 +213,13 @@ public void testGetTask_MethodNameSetInContext() {
215213

216214
@Test
217215
public void testCancelTask_MethodNameSetInContext() {
218-
// Arrange - based on CANCEL_TASK_TEST_REQUEST from JsonMessages
216+
// Arrange - using protobuf JSON format
219217
String jsonRpcRequest = """
220218
{
221219
"jsonrpc": "2.0",
222220
"method": "CancelTask",
223221
"params": {
224-
"id": "de38c76d-d54c-436c-8b9f-4c2703648d64",
225-
"metadata": {}
222+
"name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64"
226223
}
227224
}""";
228225
when(mockRequestBody.asString()).thenReturn(jsonRpcRequest);
@@ -245,13 +242,13 @@ public void testCancelTask_MethodNameSetInContext() {
245242

246243
@Test
247244
public void testTaskResubscription_MethodNameSetInContext() {
248-
// Arrange - minimal valid JSON for task resubscription
245+
// Arrange - using protobuf JSON format
249246
String jsonRpcRequest = """
250247
{
251248
"jsonrpc": "2.0",
252249
"method": "SubscribeToTask",
253250
"params": {
254-
"id": "de38c76d-d54c-436c-8b9f-4c2703648d64"
251+
"name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64"
255252
}
256253
}""";
257254
when(mockRequestBody.asString()).thenReturn(jsonRpcRequest);
@@ -276,17 +273,21 @@ public void testTaskResubscription_MethodNameSetInContext() {
276273

277274
@Test
278275
public void testSetTaskPushNotificationConfig_MethodNameSetInContext() {
279-
// Arrange - based on SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST from JsonMessages
276+
// Arrange - using protobuf JSON format
280277
String jsonRpcRequest = """
281278
{
282279
"jsonrpc": "2.0",
283280
"method": "SetTaskPushNotificationConfig",
284281
"params": {
285-
"taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64",
286-
"pushNotificationConfig": {
287-
"url": "https://example.com/callback",
288-
"authentication": {
289-
"schemes": ["jwt"]
282+
"parent": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64",
283+
"configId": "config-123",
284+
"config": {
285+
"name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/config-123",
286+
"pushNotificationConfig": {
287+
"url": "https://example.com/callback",
288+
"authentication": {
289+
"schemes": ["jwt"]
290+
}
290291
}
291292
}
292293
}
@@ -312,14 +313,13 @@ public void testSetTaskPushNotificationConfig_MethodNameSetInContext() {
312313

313314
@Test
314315
public void testGetTaskPushNotificationConfig_MethodNameSetInContext() {
315-
// Arrange - based on GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST from JsonMessages
316+
// Arrange - using protobuf JSON format
316317
String jsonRpcRequest = """
317318
{
318319
"jsonrpc": "2.0",
319320
"method": "GetTaskPushNotificationConfig",
320321
"params": {
321-
"id": "de38c76d-d54c-436c-8b9f-4c2703648d64",
322-
"metadata": {}
322+
"name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/config-456"
323323
}
324324
}""";
325325
when(mockRequestBody.asString()).thenReturn(jsonRpcRequest);
@@ -343,13 +343,13 @@ public void testGetTaskPushNotificationConfig_MethodNameSetInContext() {
343343

344344
@Test
345345
public void testListTaskPushNotificationConfig_MethodNameSetInContext() {
346-
// Arrange - minimal valid JSON for list task push notification config
346+
// Arrange - using protobuf JSON format
347347
String jsonRpcRequest = """
348348
{
349349
"jsonrpc": "2.0",
350350
"method": "ListTaskPushNotificationConfig",
351351
"params": {
352-
"id": "de38c76d-d54c-436c-8b9f-4c2703648d64"
352+
"parent": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64"
353353
}
354354
}""";
355355
when(mockRequestBody.asString()).thenReturn(jsonRpcRequest);
@@ -373,14 +373,13 @@ public void testListTaskPushNotificationConfig_MethodNameSetInContext() {
373373

374374
@Test
375375
public void testDeleteTaskPushNotificationConfig_MethodNameSetInContext() {
376-
// Arrange - minimal valid JSON for delete task push notification config
376+
// Arrange - using protobuf JSON format
377377
String jsonRpcRequest = """
378378
{
379379
"jsonrpc": "2.0",
380380
"method": "DeleteTaskPushNotificationConfig",
381381
"params": {
382-
"id": "de38c76d-d54c-436c-8b9f-4c2703648d64",
383-
"pushNotificationConfigId": "config-456"
382+
"name": "tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/config-456"
384383
}
385384
}""";
386385
when(mockRequestBody.asString()).thenReturn(jsonRpcRequest);

0 commit comments

Comments
 (0)