Skip to content

Commit 224552a

Browse files
Jacksunweicopybara-github
authored andcommitted
feat: Supports -DextraPlugins in maven_plugin WebMojo to allow start AdkWebServer with extraPlugin for conformance tests
PiperOrigin-RevId: 820950725
1 parent 4b641aa commit 224552a

File tree

2 files changed

+95
-9
lines changed

2 files changed

+95
-9
lines changed

dev/src/main/java/com/google/adk/web/service/RunnerService.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,18 @@
1919
import com.google.adk.agents.BaseAgent;
2020
import com.google.adk.artifacts.BaseArtifactService;
2121
import com.google.adk.memory.BaseMemoryService;
22+
import com.google.adk.plugins.BasePlugin;
2223
import com.google.adk.runner.Runner;
2324
import com.google.adk.sessions.BaseSessionService;
2425
import com.google.adk.web.AgentLoader;
26+
import com.google.common.collect.ImmutableList;
27+
import java.util.List;
2528
import java.util.Map;
2629
import java.util.concurrent.ConcurrentHashMap;
2730
import org.slf4j.Logger;
2831
import org.slf4j.LoggerFactory;
2932
import org.springframework.beans.factory.annotation.Autowired;
33+
import org.springframework.beans.factory.annotation.Qualifier;
3034
import org.springframework.http.HttpStatus;
3135
import org.springframework.stereotype.Component;
3236
import org.springframework.web.server.ResponseStatusException;
@@ -40,18 +44,21 @@ public class RunnerService {
4044
private final BaseArtifactService artifactService;
4145
private final BaseSessionService sessionService;
4246
private final BaseMemoryService memoryService;
47+
private final List<BasePlugin> extraPlugins;
4348
private final Map<String, Runner> runnerCache = new ConcurrentHashMap<>();
4449

45-
@Autowired
4650
public RunnerService(
4751
AgentLoader agentProvider,
4852
BaseArtifactService artifactService,
4953
BaseSessionService sessionService,
50-
BaseMemoryService memoryService) {
54+
BaseMemoryService memoryService,
55+
@Autowired(required = false) @Qualifier("extraPlugins") List<BasePlugin> extraPlugins) {
5156
this.agentProvider = agentProvider;
5257
this.artifactService = artifactService;
5358
this.sessionService = sessionService;
5459
this.memoryService = memoryService;
60+
this.extraPlugins =
61+
extraPlugins != null ? ImmutableList.copyOf(extraPlugins) : ImmutableList.of();
5562
}
5663

5764
/**
@@ -72,7 +79,12 @@ public Runner getRunner(String appName) {
7279
appName,
7380
agent.name());
7481
return new Runner(
75-
agent, appName, this.artifactService, this.sessionService, this.memoryService);
82+
agent,
83+
appName,
84+
this.artifactService,
85+
this.sessionService,
86+
this.memoryService,
87+
this.extraPlugins);
7688
} catch (java.util.NoSuchElementException e) {
7789
log.error(
7890
"Agent/App named '{}' not found in registry. Available apps: {}",

maven_plugin/src/main/java/com/google/adk/maven/WebMojo.java

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@
1616

1717
package com.google.adk.maven;
1818

19+
import autovalue.shaded.com.google.common.collect.ImmutableList;
20+
import com.google.adk.plugins.BasePlugin;
1921
import com.google.adk.utils.ComponentRegistry;
2022
import com.google.adk.web.AdkWebServer;
23+
import com.google.adk.web.AgentLoader;
24+
import com.google.common.base.Strings;
2125
import java.io.IOException;
2226
import java.lang.reflect.Field;
2327
import java.net.MalformedURLException;
@@ -180,6 +184,30 @@ public class WebMojo extends AbstractMojo {
180184
@Parameter(property = "registry")
181185
private String registry;
182186

187+
/**
188+
* Comma-separated list of additional plugin classes to load.
189+
*
190+
* <p>This parameter allows users to specify extra plugins that extend BasePlugin. Plugins provide
191+
* global callbacks for logging, monitoring, replay, caching, or modifying agent behaviors. These
192+
* are additional to any plugins configured by the user's code.
193+
*
194+
* <p>Each plugin reference can be either:
195+
*
196+
* <ul>
197+
* <li><strong>Static field reference:</strong> {@code com.example.MyPlugin.INSTANCE}
198+
* <li><strong>Class name:</strong> {@code com.example.MyPlugin} (requires default constructor)
199+
* </ul>
200+
*
201+
* <p>Example:
202+
*
203+
* <pre>{@code
204+
* mvn google-adk:web -Dagents=... -DextraPlugins=com.google.adk.plugins.ReplayPlugin
205+
* mvn google-adk:web -Dagents=... -DextraPlugins=com.google.adk.plugins.ReplayPlugin,com.example.CustomPlugin
206+
* }</pre>
207+
*/
208+
@Parameter(property = "extraPlugins")
209+
private String extraPlugins;
210+
183211
private ConfigurableApplicationContext applicationContext;
184212
private URLClassLoader projectClassLoader;
185213

@@ -205,18 +233,22 @@ public void execute() throws MojoExecutionException, MojoFailureException {
205233

206234
// Load and instantiate the AgentLoader
207235
getLog().info("Loading agent loader: " + agents);
208-
com.google.adk.web.AgentLoader provider = loadAgentProvider();
236+
AgentLoader provider = loadAgentProvider();
237+
238+
// Load extra plugins if specified
239+
final List<BasePlugin> extraPluginInstances = loadExtraPlugins();
209240

210241
// Set up system properties for Spring Boot
211242
setupSystemProperties();
212243

213244
// Start the Spring Boot application with custom agent provider
214245
SpringApplication app = new SpringApplication(AdkWebServer.class);
215246

216-
// Add the agent provider as a bean
247+
// Add the agent provider and extra plugins as beans
217248
app.addInitializers(
218249
ctx -> {
219250
ctx.getBeanFactory().registerSingleton("agentLoader", provider);
251+
ctx.getBeanFactory().registerSingleton("extraPlugins", extraPluginInstances);
220252
});
221253

222254
getLog().info("Starting Spring Boot application...");
@@ -268,6 +300,7 @@ private void logConfiguration() {
268300
getLog().info(" Server Host: " + host);
269301
getLog().info(" Server Port: " + port);
270302
getLog().info(" Registry: " + (registry != null ? registry : "default"));
303+
getLog().info(" Extra Plugins: " + (extraPlugins != null ? extraPlugins : "none"));
271304
}
272305

273306
private void setupSystemProperties() {
@@ -401,7 +434,7 @@ private <T> T tryLoadFromConstructor(String className, Class<T> expectedType)
401434
}
402435
}
403436

404-
private com.google.adk.web.AgentLoader loadAgentProvider() throws MojoExecutionException {
437+
private AgentLoader loadAgentProvider() throws MojoExecutionException {
405438
// First, check if agents parameter is a directory path
406439
Path agentsPath = Paths.get(agents);
407440
if (Files.isDirectory(agentsPath)) {
@@ -411,15 +444,56 @@ private com.google.adk.web.AgentLoader loadAgentProvider() throws MojoExecutionE
411444

412445
// Next, try to interpret as class.field syntax
413446
if (agents.contains(".")) {
414-
com.google.adk.web.AgentLoader provider =
415-
tryLoadFromStaticField(agents, com.google.adk.web.AgentLoader.class);
447+
AgentLoader provider = tryLoadFromStaticField(agents, AgentLoader.class);
416448
if (provider != null) {
417449
return provider;
418450
}
419451
}
420452

421453
// Fallback to trying the entire string as a class name
422-
return tryLoadFromConstructor(agents, com.google.adk.web.AgentLoader.class);
454+
return tryLoadFromConstructor(agents, AgentLoader.class);
455+
}
456+
457+
/**
458+
* Loads extra plugins from the comma-separated extraPlugins parameter.
459+
*
460+
* @return List of loaded plugin instances
461+
* @throws MojoExecutionException if plugins cannot be loaded
462+
*/
463+
private ImmutableList<BasePlugin> loadExtraPlugins() throws MojoExecutionException {
464+
ImmutableList.Builder<BasePlugin> plugins = ImmutableList.builder();
465+
String[] pluginNames = Strings.nullToEmpty(extraPlugins).split(",");
466+
467+
for (String name : pluginNames) {
468+
name = name.trim();
469+
if (name.isEmpty()) {
470+
continue;
471+
}
472+
473+
getLog().info("Loading plugin: " + name);
474+
475+
// Try to load as static field first
476+
BasePlugin plugin = null;
477+
if (name.contains(".")) {
478+
plugin = tryLoadFromStaticField(name, BasePlugin.class);
479+
}
480+
481+
// Fallback to constructor
482+
if (plugin == null) {
483+
plugin = tryLoadFromConstructor(name, BasePlugin.class);
484+
}
485+
486+
if (plugin == null) {
487+
throw new MojoExecutionException("Failed to load plugin: " + name);
488+
}
489+
490+
plugins.add(plugin);
491+
getLog()
492+
.info(
493+
String.format("Successfully loaded plugin: `%s` from `%s`", plugin.getName(), name));
494+
}
495+
496+
return plugins.build();
423497
}
424498

425499
/** Cleans up all resources including application context, classloader. */

0 commit comments

Comments
 (0)