diff --git a/src/frontend/src/content/docs/integrations/frameworks/java.mdx b/src/frontend/src/content/docs/integrations/frameworks/java.mdx
index 37a1ed816..7a9a70a83 100644
--- a/src/frontend/src/content/docs/integrations/frameworks/java.mdx
+++ b/src/frontend/src/content/docs/integrations/frameworks/java.mdx
@@ -1,9 +1,9 @@
---
title: Java integration
-description: Learn how to use the Aspire Java hosting integration from the Community Toolkit to run Spring Boot and other Java applications alongside your Aspire projects.
+description: Learn how to use the Aspire Java hosting integration from the Community Toolkit to run Java applications from Maven, Gradle, executable JARs, or containers in your AppHost.
---
-import { Badge } from '@astrojs/starlight/components';
+import { Badge, TabItem, Tabs } from '@astrojs/starlight/components';
import InstallPackage from '@components/InstallPackage.astro';
import { Image } from 'astro:assets';
import javaIcon from '@assets/icons/java-icon.png';
@@ -19,123 +19,404 @@ import javaIcon from '@assets/icons/java-icon.png';
data-zoom-off
/>
-This article is the reference for the Aspire Java hosting integration from the [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire). It enumerates the AppHost APIs you use to model Java applications — including Spring Boot apps — in your [`AppHost`](/get-started/app-host/) project.
-
-:::note
-TypeScript AppHost support for this integration is not yet available. All AppHost examples on this page are in C#.
-:::
+This article is the reference for the Aspire Java hosting integration from the [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire). Use it to model Java applications in your [`AppHost`](/get-started/app-host/) project whether you run them from Maven, Gradle, an executable JAR, or a container image.
## Hosting integration
-:::note
-This integration requires the OpenTelemetry Java agent for observability support. Download the agent JAR and place it in the `./agents` directory relative to your AppHost project. Download from: [OpenTelemetry Java Agent releases](https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases).
-:::
+Use the Java integration to run a Java application with Maven or Gradle, from an executable JAR, or from a container image.
-### Add Spring Boot app
+### Run with Maven
-To add a Spring Boot application to your AppHost, use the `AddSpringApp` extension method:
+
+
-```csharp title="C# — AppHost.cs"
+```csharp title="C# — AppHost.cs" "WithMavenGoal"
var builder = DistributedApplication.CreateBuilder(args);
-var javaApp = builder.AddSpringApp(
- name: "spring-api",
- workingDirectory: "../spring-app",
- otelAgentPath: "../agents/opentelemetry-javaagent.jar")
- .WithHttpEndpoint(port: 8080);
+var javaApp = builder.AddJavaApp("spring-api", "../spring-app")
+ .WithMavenGoal("spring-boot:run")
+ .WithHttpEndpoint(env: "SERVER_PORT");
+
+builder.Build().Run();
+```
+
+
+
+
+```typescript title="apphost.ts" "withMavenGoal"
+import { createBuilder } from './.modules/aspire.js';
+
+const builder = await createBuilder();
+
+const javaApp = await builder.addJavaApp('spring-api', '../spring-app');
+await javaApp.withMavenGoal('spring-boot:run', []);
+await javaApp.withHttpEndpoint({ env: 'SERVER_PORT' });
+
+await builder.build().run();
+```
+
+
+
+
+### Run with Gradle
+
+
+
+
+```csharp title="C# — AppHost.cs" "WithGradleTask"
+var builder = DistributedApplication.CreateBuilder(args);
-builder.AddProject("apiservice")
- .WithReference(javaApp);
+var javaApp = builder.AddJavaApp("spring-api", "../spring-app")
+ .WithGradleTask("bootRun")
+ .WithHttpEndpoint(env: "SERVER_PORT");
builder.Build().Run();
```
-The `AddSpringApp` method accepts:
-- **name**: The resource name shown in the Aspire dashboard.
-- **workingDirectory**: The path to the directory containing your Spring Boot application.
-- **otelAgentPath**: The path to the OpenTelemetry Java agent JAR file.
+
+
-### Container hosting
+```typescript title="apphost.ts" "withGradleTask"
+import { createBuilder } from './.modules/aspire.js';
-For production scenarios, host Java applications in containers using `JavaAppContainerResourceOptions`:
+const builder = await createBuilder();
+
+const javaApp = await builder.addJavaApp('spring-api', '../spring-app');
+await javaApp.withGradleTask('bootRun', []);
+await javaApp.withHttpEndpoint({ env: 'SERVER_PORT' });
+
+await builder.build().run();
+```
+
+
+
+
+### Run an executable JAR
+
+To run a pre-built JAR, pass the JAR path as the third argument to `AddJavaApp` / `addJavaAppWithJar`:
+
+
+
```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);
-var javaApp = builder.AddSpringApp(
- name: "spring-api",
- new JavaAppContainerResourceOptions
- {
- OtelAgentPath = "../agents/opentelemetry-javaagent.jar",
- ContainerImageName = "my-spring-app:latest",
- ContainerRegistry = "myregistry.azurecr.io"
- })
- .WithHttpEndpoint(port: 8080);
-
-// After adding all resources, run the app...
+var javaApp = builder.AddJavaApp(
+ "java-api",
+ "../java-app",
+ "target/app.jar")
+ .WithHttpEndpoint(env: "SERVER_PORT");
+
builder.Build().Run();
```
-### Executable hosting
+
+
-For local development, run Java applications as executables using `JavaAppExecutableResourceOptions`:
+```typescript title="apphost.ts"
+import { createBuilder } from './.modules/aspire.js';
-```csharp title="C# — AppHost.cs"
+const builder = await createBuilder();
+
+const javaApp = await builder.addJavaAppWithJar(
+ 'java-api',
+ '../java-app',
+ 'target/app.jar'
+);
+await javaApp.withHttpEndpoint({ env: 'SERVER_PORT' });
+
+await builder.build().run();
+```
+
+
+
+
+### Build with Maven
+
+Use `WithMavenBuild` to compile an executable JAR before Aspire starts the application.
+
+
+
+
+```csharp title="C# — AppHost.cs" "WithMavenBuild"
var builder = DistributedApplication.CreateBuilder(args);
-var javaApp = builder.AddSpringApp(
- name: "spring-api",
- new JavaAppExecutableResourceOptions
- {
- ApplicationName = "spring-app",
- OtelAgentPath = "../agents/opentelemetry-javaagent.jar",
- WorkingDirectory = "../spring-app"
- })
- .WithHttpEndpoint(port: 8080);
-
-// After adding all resources, run the app...
+var javaApp = builder.AddJavaApp("spring-api", "../spring-app", "target/app.jar")
+ .WithMavenBuild()
+ .WithHttpEndpoint(env: "SERVER_PORT");
+
builder.Build().Run();
```
-### Configure endpoints
+
+
+
+```typescript title="apphost.ts" "withMavenBuild"
+import { createBuilder } from './.modules/aspire.js';
+
+const builder = await createBuilder();
+
+const javaApp = await builder.addJavaAppWithJar(
+ 'spring-api',
+ '../spring-app',
+ 'target/app.jar'
+);
+await javaApp.withMavenBuild();
+await javaApp.withHttpEndpoint({ env: 'SERVER_PORT' });
+
+await builder.build().run();
+```
+
+
+
-Spring Boot applications use the `server.port` property to configure the port. Use `WithHttpEndpoint` to expose the endpoint to other resources in the AppHost:
+### Build with Gradle
+
+Use `WithGradleBuild` to compile an executable JAR before Aspire starts the application.
+
+
+
+
+```csharp title="C# — AppHost.cs" "WithGradleBuild"
+var builder = DistributedApplication.CreateBuilder(args);
+
+var javaApp = builder.AddJavaApp("spring-api", "../spring-app", "build/libs/app.jar")
+ .WithGradleBuild()
+ .WithHttpEndpoint(env: "SERVER_PORT");
+
+builder.Build().Run();
+```
+
+
+
+
+```typescript title="apphost.ts" "withGradleBuild"
+import { createBuilder } from './.modules/aspire.js';
+
+const builder = await createBuilder();
+
+const javaApp = await builder.addJavaAppWithJar(
+ 'spring-api',
+ '../spring-app',
+ 'build/libs/app.jar'
+);
+await javaApp.withGradleBuild();
+await javaApp.withHttpEndpoint({ env: 'SERVER_PORT' });
+
+await builder.build().run();
+```
+
+
+
+
+### Run a container image
+
+
+
```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);
-var javaApp = builder.AddSpringApp(
- "spring-api",
- "../spring-app",
- "../agents/opentelemetry-javaagent.jar")
- .WithHttpEndpoint(port: 8080);
+var javaApp = builder.AddJavaContainerApp(
+ name: "java-api",
+ image: "docker.io/example/spring-api",
+ imageTag: "latest")
+ .WithHttpEndpoint(env: "SERVER_PORT");
-// After adding all resources, run the app...
builder.Build().Run();
```
-### Certificate trust (Linux and macOS)
+
+
+
+```typescript title="apphost.ts"
+import { createBuilder } from './.modules/aspire.js';
-On Linux and macOS, add the following to your Spring Boot application's `application.properties` to trust the Aspire development certificates:
+const builder = await createBuilder();
-```properties title="application.properties"
-server.ssl.trust-store=/path/to/aspire/dev/certificate.p12
-server.ssl.trust-store-password=p@ssw0rd1
+const javaApp = await builder.addJavaContainerApp(
+ 'java-api',
+ 'docker.io/example/spring-api',
+ { imageTag: 'latest' }
+);
+await javaApp.withHttpEndpoint({ env: 'SERVER_PORT' });
+
+await builder.build().run();
```
-For more information, see the [Spring Boot SSL documentation](https://docs.spring.io/spring-boot/reference/features/ssl.html).
+
+
+
+### Pass environment variables
-## Observability
+Use `WithEnvironment` to pass configuration to your Java application. Aspire resources expose typed expressions you can inject directly — for example, `JdbcConnectionString` on a PostgreSQL database resource produces a `jdbc:postgresql://` URL ready for Spring Boot's `SPRING_DATASOURCE_URL`:
+
+
+
+
+```csharp title="C# — AppHost.cs" "WithEnvironment" "JdbcConnectionString"
+var builder = DistributedApplication.CreateBuilder(args);
+
+var postgres = builder.AddPostgres("postgres");
+var db = postgres.AddDatabase("mydb");
+
+var javaApp = builder.AddJavaApp("spring-api", "../spring-app")
+ .WithMavenGoal("spring-boot:run")
+ .WithEnvironment("SPRING_DATASOURCE_URL", db.Resource.JdbcConnectionString)
+ .WithEnvironment("SPRING_DATASOURCE_USERNAME", postgres.Resource.UserNameReference)
+ .WithEnvironment(ctx => ctx.EnvironmentVariables["SPRING_DATASOURCE_PASSWORD"] = postgres.Resource.PasswordParameter)
+ .WithHttpEndpoint(env: "SERVER_PORT");
+
+builder.Build().Run();
+```
+
+
+
+
+```typescript title="apphost.ts" "withEnvironment" "jdbcConnectionString"
+import { createBuilder } from './.modules/aspire.js';
+
+const builder = await createBuilder();
+
+const postgres = await builder.addPostgres('postgres');
+const db = await postgres.addDatabase('mydb');
+
+const javaApp = await builder.addJavaApp('spring-api', '../spring-app');
+await javaApp.withMavenGoal('spring-boot:run', []);
+await javaApp.withEnvironment('SPRING_DATASOURCE_URL', await db.jdbcConnectionString());
+await javaApp.withEnvironment('SPRING_DATASOURCE_USERNAME', await postgres.userNameReference());
+await javaApp.withEnvironment('SPRING_DATASOURCE_PASSWORD', await postgres.passwordParameter());
+await javaApp.withHttpEndpoint({ env: 'SERVER_PORT' });
+
+await builder.build().run();
+```
+
+
+
+
+### Health checks
+
+Declare an HTTP health-check path so Aspire knows when the application is ready:
+
+
+
+
+```csharp title="C# — AppHost.cs" "WithHttpHealthCheck"
+var builder = DistributedApplication.CreateBuilder(args);
+
+var javaApp = builder.AddJavaApp("spring-api", "../spring-app")
+ .WithMavenGoal("spring-boot:run")
+ .WithHttpEndpoint(env: "SERVER_PORT")
+ .WithHttpHealthCheck("/actuator/health");
+
+builder.Build().Run();
+```
+
+
+
+
+```typescript title="apphost.ts" "withHttpHealthCheck"
+import { createBuilder } from './.modules/aspire.js';
+
+const builder = await createBuilder();
+
+const javaApp = await builder.addJavaApp('spring-api', '../spring-app');
+await javaApp.withMavenGoal('spring-boot:run', []);
+await javaApp.withHttpEndpoint({ env: 'SERVER_PORT' });
+await javaApp.withHttpHealthCheck('/actuator/health');
+
+await builder.build().run();
+```
+
+
+
+
+Spring Boot Actuator exposes `/actuator/health` when `spring-boot-starter-actuator` is on the classpath.
+
+### Configure JVM arguments
+
+Use `WithJvmArgs` / `withJvmArgs` to pass JVM arguments such as heap limits or system properties to the Java process:
+
+
+
+
+```csharp title="C# — AppHost.cs" "WithJvmArgs"
+var builder = DistributedApplication.CreateBuilder(args);
+
+var javaApp = builder.AddJavaApp("spring-api", "../spring-app")
+ .WithMavenGoal("spring-boot:run")
+ .WithJvmArgs(["-Xmx512m", "-Xms256m"])
+ .WithHttpEndpoint(env: "SERVER_PORT");
+
+builder.Build().Run();
+```
+
+
+
+
+```typescript title="apphost.ts" "withJvmArgs"
+import { createBuilder } from './.modules/aspire.js';
+
+const builder = await createBuilder();
+
+const javaApp = await builder.addJavaApp('spring-api', '../spring-app');
+await javaApp.withMavenGoal('spring-boot:run', []);
+await javaApp.withJvmArgs(['-Xmx512m', '-Xms256m']);
+await javaApp.withHttpEndpoint({ env: 'SERVER_PORT' });
+
+await builder.build().run();
+```
+
+
+
+
+### Configure OpenTelemetry
+
+Download the OpenTelemetry Java agent and point the Java resource at the agent JAR.
+
+
+
+
+```csharp title="C# — AppHost.cs"
+var builder = DistributedApplication.CreateBuilder(args);
+
+var javaApp = builder.AddJavaApp("java-api", "../java-app", "target/app.jar")
+ .WithOtelAgent("../agents/opentelemetry-javaagent.jar")
+ .WithHttpEndpoint(env: "SERVER_PORT");
+
+builder.Build().Run();
+```
+
+
+
+
+```typescript title="apphost.ts"
+import { createBuilder } from './.modules/aspire.js';
+
+const builder = await createBuilder();
+
+const javaApp = await builder.addJavaAppWithJar(
+ 'java-api',
+ '../java-app',
+ 'target/app.jar'
+);
+await javaApp.withOtelAgent('../agents/opentelemetry-javaagent.jar');
+await javaApp.withHttpEndpoint({ env: 'SERVER_PORT' });
+
+await builder.build().run();
+```
-The Java integration uses the OpenTelemetry Java agent to automatically instrument your application and export telemetry to the Aspire dashboard.
+
+
-Download the OpenTelemetry Java agent and specify its path when calling `AddSpringApp`. For more information, see [OpenTelemetry Java instrumentation](https://opentelemetry.io/docs/languages/java/).
+For more information on the agent, see [OpenTelemetry Java instrumentation](https://opentelemetry.io/docs/languages/java/). For executable apps, the agent path is typically relative to the AppHost project. For container apps, the agent path must exist inside the image or a mounted volume.
## See also
- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire)
+- [CommunityToolkit.Aspire.Hosting.Java README](https://github.com/CommunityToolkit/Aspire/tree/main/src/CommunityToolkit.Aspire.Hosting.Java)
- [Spring Boot documentation](https://spring.io/projects/spring-boot)
-- [OpenTelemetry Java](https://opentelemetry.io/docs/languages/java/)
+- [OpenTelemetry Java instrumentation](https://opentelemetry.io/docs/languages/java/)
- [Aspire integrations overview](/integrations/overview/)