Repository navigation
Description
Brief Summary
Since the Jakarta Agentic AI module was merged (#8331, on main since 2026-08-10, shipped in Server Full/Web, Micro and Embedded), application deployment has become noticeably slower (roughly 3–5 extra seconds) per typical deployment on typical hardware. The cause is fish.payara.ai.agent.extension.AgenticAIExtension (appserver/agentic-ai/agentic-ai-core), a server-wide CDI portable extension that is loaded into every CDI deployment and does work proportional to the application size, plus expensive fixed-cost bootstrapping, regardless of whether the application contains any @Agent class.
Three concrete problems in AgenticAIExtension.java:
-
Unfiltered
ProcessAnnotatedTypeobserver (line 113)<X> void processAgent(@Observes ProcessAnnotatedType<X> processAnnotatedType) { var annotatedType = processAnnotatedType.getAnnotatedType(); if (!annotatedType.isAnnotationPresent(Agent.class)) { return; }
There is no
@WithAnnotations(Agent.class). Weld can only use its fast PAT resolution path (skipping event dispatch for types that do not carry the requested annotations) when all PAT observers are filtered. A single unfiltered observer forces Weld to construct and fire aProcessAnnotatedTypeevent for every class in every bean archive of every application. This is the only unfiltered PAT observer in the whole server; all other server-wide extensions filter correctly:web-sse/.../ServerSentEventCdiExtension.java:188→@WithAnnotations(ServerSentEvent.class)microprofile/config/.../ConfigCdiExtension.java:121→@WithAnnotations(ConfigProperties.class)payara-micro-cdi/.../PayaraMicroCDIExtension.java:77→@WithAnnotations(Clustered.class)gf-jms-injection/.../JMSCDIExtension.java:104→@WithAnnotations(Void.class)
-
Eager Bean Validation bootstrap on every deployment (lines 167 and 283)
void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) { ... WorkflowEngine workflowEngine = new WorkflowEngine(beanManager, workflowScopeManager, resolveExecutableValidator()); ... private ExecutableValidator resolveExecutableValidator() { return Validation.buildDefaultValidatorFactory().getValidator().forExecutables();
Validation.buildDefaultValidatorFactory()performs a full Hibernate Validator bootstrap (provider resolution viaServiceLoaderagainst the application class loader,META-INF/validation.xmlparsing, message interpolator / EL setup, constraint validator discovery). It runs unconditionally, even whenagentClassesis empty — and the resultingValidatorFactoryis never closed. It is also a second, separate factory from the one the container already manages for the application. -
Eager MicroProfile Config resolution on every deployment (line 184)
if (!appProvidesLlm) { LlmBackend backend = LlmBackendFactory.create(ConfigProvider.getConfig()); afterBeanDiscovery.addBean()...
ConfigProvider.getConfig()forces construction of the application's MPConfig(including scanning the app class loader forMETA-INF/microprofile-config.properties) for every deployment, and registers a syntheticLargeLanguageModelbean in every application whether or not the application has anything to do with Agentic AI.
Expected Outcome
Applications that do not use Jakarta Agentic AI should pay no measurable deployment-time cost for the module. Specifically:
- The
ProcessAnnotatedTypeobserver should be restricted with@WithAnnotations(Agent.class)so Weld's fast path remains available and the observer is only invoked for actual@Agenttypes. - Bean Validation (
Validation.buildDefaultValidatorFactory()), MP Config lookup and the synthetic defaultLargeLanguageModelbean should only be set up when at least one@Agentclass was discovered (!agentClasses.isEmpty()), or lazily on first workflow execution. - Any
ValidatorFactorythe extension creates should be closed on shutdown (BeforeShutdown) or the container-managed one should be reused.
Deployment times should return to pre‑#8331 levels for non-Agentic-AI applications.
Current Outcome
Every CDI application deployment on Payara ≥ 7.2026.9 (where appserver/agentic-ai is bundled):
- fires a
ProcessAnnotatedTypeevent for every class in the application (Weld fast PAT resolver disabled), - bootstraps a full, never-closed Hibernate Validator
ValidatorFactory, - builds the application's MP
Config, - gets a synthetic
LargeLanguageModelbean registered.
The result is roughly 3–5 seconds of additional deployment time per typical application on typical developer hardware, compared with 7.2026.8 and earlier. The overhead scales with application size (number of classes), so large applications (thousands of classes, many bean archives) are affected the most.
Reproducer
- Take any CDI web application with a large number of classes (e.g. a few thousand) and no
@Agentclass. A simple way to amplify the effect is a WAR with abeans.xmlusingbean-discovery-mode="all"and a few thousand trivial classes, or any sizeable real-world application. - Deploy on Payara Community 7.2026.8 (before FISH-14066 Jakarta Agentic AI: use released API 1.0.0-M1 and EE11 TCK branch #8331) and measure deployment time (e.g.
asadmin deploywall-clock time, or theDeploymentTracingoutput). - Deploy the same application on 7.2026.9 / 7.2026.10 / current
mainand measure again. Deployment takes roughly 3–5 seconds longer for a typical application. - To confirm the attribution, remove
agentic-ai-core.jar(or thejakarta.agentic-ai-api+agentic-ai-corebundles) fromglassfish/modulesand redeploy — deployment time returns to the 7.2026.8 level. - Alternatively, rebuild
agentic-ai-corewith@WithAnnotations(Agent.class)onprocessAgentand guard theafterBeanDiscoverywork behind!agentClasses.isEmpty(); the regression disappears.
Code evidence (current main): appserver/agentic-ai/agentic-ai-core/src/main/java/fish/payara/ai/agent/extension/AgenticAIExtension.java lines 113, 167, 184, 283.
Operating System
Any
JDK Version
Any Supported
Payara Distribution
- Payara Server Full Profile
- Payara Server Web Profile
- Payara Micro
- Payara Embedded All
- Payara Embedded Web
Suggested fix
<X> void processAgent(@Observes @WithAnnotations(Agent.class) ProcessAnnotatedType<X> processAnnotatedType) { ... }
void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) {
if (agentClasses.isEmpty()) {
return; // nothing to do for applications without agents
}
...
}plus closing the ValidatorFactory on BeforeShutdown. Happy to submit a PR for this.
Activity
[-]Bug Report: AgenticAIExtension adds unconditional per-deployment overhead to every CDI application (unfiltered ProcessAnnotatedType observer, eager Bean Validation bootstrap)[/-][+]Bug Report: [Performance Regression] AgenticAIExtension adds unconditional per-deployment overhead to every CDI application[/+]