Skip to content

Commit 8c6591b

Browse files
google-genai-botcopybara-github
authored andcommitted
fix: prepare JSON serialization for Jackson 2.20.2 and Spring Boot 4.0.2 upgrades
PiperOrigin-RevId: 879016658
1 parent 5b23d03 commit 8c6591b

3 files changed

Lines changed: 37 additions & 5 deletions

File tree

dev/src/main/java/com/google/adk/web/AdkWebServer.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
import org.springframework.context.ApplicationContextInitializer;
3636
import org.springframework.context.ConfigurableApplicationContext;
3737
import org.springframework.context.annotation.Bean;
38+
import org.springframework.context.annotation.Primary;
39+
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
3840
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
3941
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
4042
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@@ -87,10 +89,25 @@ public BaseMemoryService memoryService() {
8789
* @return Configured ObjectMapper instance
8890
*/
8991
@Bean
92+
@Primary
9093
public ObjectMapper objectMapper() {
9194
return JsonBaseModel.getMapper();
9295
}
9396

97+
/**
98+
* Configures the message converter to use the custom ADK ObjectMapper. This ensures that Spring
99+
* Web uses the correct JSON serialization settings (like omitting absent optional fields) and
100+
* prevents double-serialization issues, particularly for Server-Sent Events (SSE).
101+
*
102+
* @param objectMapper The primary ObjectMapper configured for the ADK.
103+
* @return A configured MappingJackson2HttpMessageConverter.
104+
*/
105+
@Bean
106+
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(
107+
ObjectMapper objectMapper) {
108+
return new MappingJackson2HttpMessageConverter(objectMapper);
109+
}
110+
94111
/**
95112
* Configures resource handlers for serving static content (like the Dev UI). Maps requests
96113
* starting with "/dev-ui/" to the directory specified by the 'adk.web.ui.dir' system property.

dev/src/main/java/com/google/adk/web/controller/ExecutionController.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,11 @@ public List<Event> agentRun(@RequestBody AgentRunRequest request) {
8181
RunConfig runConfig = RunConfig.builder().setStreamingMode(StreamingMode.NONE).build();
8282
Flowable<Event> eventStream =
8383
runner.runAsync(
84-
request.userId, request.sessionId, request.newMessage, runConfig, request.stateDelta);
84+
request.userId,
85+
request.sessionId,
86+
request.getNewMessage(),
87+
runConfig,
88+
request.stateDelta);
8589

8690
List<Event> events = Lists.newArrayList(eventStream.blockingIterable());
8791
log.info("Agent run for session {} generated {} events.", request.sessionId, events.size());
@@ -155,7 +159,7 @@ public SseEmitter agentRunSse(@RequestBody AgentRunRequest request) {
155159
runner.runAsync(
156160
request.userId,
157161
request.sessionId,
158-
request.newMessage,
162+
request.getNewMessage(),
159163
runConfig,
160164
request.stateDelta);
161165

@@ -167,7 +171,7 @@ public SseEmitter agentRunSse(@RequestBody AgentRunRequest request) {
167171
try {
168172
log.debug(
169173
"SseEmitter: Sending event {} for session {}", event.id(), sessionId);
170-
emitter.send(SseEmitter.event().data(event.toJson()));
174+
emitter.send(SseEmitter.event().data(event));
171175
} catch (IOException e) {
172176
log.error(
173177
"SseEmitter: IOException sending event for session {}: {}",

dev/src/main/java/com/google/adk/web/dto/AgentRunRequest.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.google.adk.web.dto;
1818

1919
import com.fasterxml.jackson.annotation.JsonProperty;
20+
import com.google.adk.JsonBaseModel;
2021
import com.google.genai.types.Content;
2122
import java.util.Map;
2223
import javax.annotation.Nullable;
@@ -36,7 +37,7 @@ public class AgentRunRequest {
3637
public String sessionId;
3738

3839
@JsonProperty("newMessage")
39-
public Content newMessage;
40+
public Object newMessage;
4041

4142
@JsonProperty("streaming")
4243
public boolean streaming = false;
@@ -65,7 +66,17 @@ public String getSessionId() {
6566
}
6667

6768
public Content getNewMessage() {
68-
return newMessage;
69+
if (newMessage instanceof Content) {
70+
return (Content) newMessage;
71+
}
72+
if (newMessage != null) {
73+
try {
74+
return JsonBaseModel.getMapper().convertValue(newMessage, Content.class);
75+
} catch (IllegalArgumentException e) {
76+
throw new IllegalStateException("Failed to parse newMessage into Content", e);
77+
}
78+
}
79+
return null;
6980
}
7081

7182
public boolean getStreaming() {

0 commit comments

Comments
 (0)