diff --git a/contrib/spring-boot-starter-adk/pom.xml b/contrib/spring-boot-starter-adk/pom.xml new file mode 100644 index 00000000..af6342b4 --- /dev/null +++ b/contrib/spring-boot-starter-adk/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + + com.google.adk + google-adk-parent + 0.2.1-SNAPSHOT + ../../pom.xml + + + spring-boot-starter-adk + Agent Development Kit - Spring Boot Starter + Spring Boot Starter for the Agent Development Kit. + + + + com.google.adk + google-adk + ${project.version} + + + com.google.adk + google-adk-dev + ${project.version} + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.mockito + mockito-core + test + + + diff --git a/contrib/spring-boot-starter-adk/src/main/java/com/google/adk/starters/springboot/AdkSpringbootAutoConfiguration.java b/contrib/spring-boot-starter-adk/src/main/java/com/google/adk/starters/springboot/AdkSpringbootAutoConfiguration.java new file mode 100644 index 00000000..f53e7637 --- /dev/null +++ b/contrib/spring-boot-starter-adk/src/main/java/com/google/adk/starters/springboot/AdkSpringbootAutoConfiguration.java @@ -0,0 +1,33 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.adk.starters.springboot; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan("com.google.adk") +public class AdkSpringbootAutoConfiguration { + + private static final Logger logger = + LoggerFactory.getLogger(AdkSpringbootAutoConfiguration.class); + + public AdkSpringbootAutoConfiguration() { + logger.info("AdkSpringbootAutoConfiguration initialized."); + } +} diff --git a/contrib/spring-boot-starter-adk/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/contrib/spring-boot-starter-adk/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..a227f10d --- /dev/null +++ b/contrib/spring-boot-starter-adk/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.google.adk.starters.springboot.AdkSpringbootAutoConfiguration diff --git a/contrib/spring-boot-starter-adk/src/test/java/com/google/adk/starters/springboot/AdkSpringbootStarterTest.java b/contrib/spring-boot-starter-adk/src/test/java/com/google/adk/starters/springboot/AdkSpringbootStarterTest.java new file mode 100644 index 00000000..ee0ac879 --- /dev/null +++ b/contrib/spring-boot-starter-adk/src/test/java/com/google/adk/starters/springboot/AdkSpringbootStarterTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.adk.starters.springboot; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.google.adk.agents.BaseAgent; +import com.google.adk.agents.LlmAgent; +import com.google.adk.web.AgentStaticLoader; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.web.servlet.MockMvc; + +/** + * Integration tests for the ADK Spring Boot Starter. + * + *

These tests use MockMvc to simulate HTTP requests and verify the expected responses from the + * ADK API server, ensuring that the Spring Boot autoconfiguration works correctly. + */ +@SpringBootTest(properties = "adk.agents.loader=static") +@AutoConfigureMockMvc +public class AdkSpringbootStarterTest { + + @Autowired private AgentStaticLoader agentStaticLoader; + + @Autowired private MockMvc mockMvc; + + @Test + void testAgentStaticLoaderIsLoaded() throws Exception { + assertNotNull(agentStaticLoader); + mockMvc + .perform(get("/list-apps")) + .andExpect(status().isOk()) + .andExpect(content().json("[\"test_agent\"]")); + } + + @SpringBootApplication + public static class TestApplication { + public static void main(String[] args) { + SpringApplication.run(TestApplication.class, args); + } + } + + @Configuration + public static class AppConfig { + @Bean("agentLoader") + public AgentStaticLoader agentStaticLoader() { + BaseAgent testAgent = + LlmAgent.builder() + .name("test_agent") + .model("gemini-2.0-flash-lite") + .description("Test agent for demonstrating AgentStaticLoader") + .instruction("You are a test agent.") + .build(); + return new AgentStaticLoader(testAgent); + } + } +} diff --git a/dev/src/main/java/com/google/adk/web/AgentStaticLoader.java b/dev/src/main/java/com/google/adk/web/AgentStaticLoader.java index b0bc6bd9..68871877 100644 --- a/dev/src/main/java/com/google/adk/web/AgentStaticLoader.java +++ b/dev/src/main/java/com/google/adk/web/AgentStaticLoader.java @@ -37,7 +37,7 @@ *

This class is not a Spring component by itself - instances are created programmatically and * then registered as beans via factory methods. */ -class AgentStaticLoader implements AgentLoader { +public class AgentStaticLoader implements AgentLoader { private final ImmutableMap agents; diff --git a/pom.xml b/pom.xml index 5e868f45..b6b9816c 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,7 @@ dev maven_plugin contrib/langchain4j + contrib/spring-boot-starter-adk tutorials/city-time-weather