JavaHostingExtensions Methods
Hosting.IDistributedApplicationBuilder. AddJavaApp(IDistributedApplicationBuilder, string, string)Section titled AddJavaApp(IDistributedApplicationBuilder, string, string)extensionIResourceBuilder<JavaAppResource>java. public static class JavaHostingExtensions{ public static IResourceBuilder<JavaAppResource> AddJavaApp( this IDistributedApplicationBuilder builder, string name, string appDirectory) { // ... }}Parameters
builderIDistributedApplicationBuilderThe Hosting.IDistributedApplicationBuilder to add the resource to.namestringThe name of the resource.appDirectorystringThe application directory. Relative paths are resolved against the AppHost directory.Returns
IResourceBuilder<JavaAppResource>A reference to the ApplicationModel.IResourceBuilder`1.Exceptions
ArgumentNullExceptionbuilder is null.ArgumentExceptionname or appDirectory is null, empty, or whitespace.InvalidOperationExceptionNo launch mode was configured. Raised when the resource starts, not when this is called.Remarks
JavaHostingExtensions.WithMavenGoal or JavaHostingExtensions.WithGradleTask to run the application through a build tool, or use the overload that accepts a jarPath to run a prebuilt JAR with java -jar. Exactly one of those three launch modes must be configured. Examples
Run a Spring Boot application through the Maven wrapper:
var builder = DistributedApplication.CreateBuilder(args);
builder.AddJavaApp("catalog", "../catalog") .WithMavenGoal("spring-boot:run") .WithHttpEndpoint(env: "SERVER_PORT") .WithHttpHealthCheck("/actuator/health");
builder.Build().Run();AddJavaApp(IDistributedApplicationBuilder, string, string, string, string[])Section titled AddJavaApp(IDistributedApplicationBuilder, string, string, string, string[])extensionIResourceBuilder<JavaAppResource>java -jar. public static class JavaHostingExtensions{ public static IResourceBuilder<JavaAppResource> AddJavaApp( this IDistributedApplicationBuilder builder, string name, string appDirectory, string jarPath, params string[] args) { // ... }}Parameters
builderIDistributedApplicationBuilderThe Hosting.IDistributedApplicationBuilder to add the resource to.namestringThe name of the resource.appDirectorystringThe application directory. Relative paths are resolved against the AppHost directory.jarPathstringThe path to the JAR file to execute. Relative paths are resolved against appDirectory.argsstring[]Arguments passed to the Java application after the JAR path.Returns
IResourceBuilder<JavaAppResource>A reference to the ApplicationModel.IResourceBuilder`1.Exceptions
ArgumentNullExceptionbuilder or args is null.ArgumentExceptionname, appDirectory, or jarPath is null, empty, or whitespace.Examples
Build the JAR with Maven, then run it:
builder.AddJavaApp("worker", "../worker", "target/worker.jar") .WithMavenBuild();AddJavaContainer(IDistributedApplicationBuilder, string, string, string?)Section titled AddJavaContainer(IDistributedApplicationBuilder, string, string, string?)extensionIResourceBuilder<JavaContainerResource>public static class JavaHostingExtensions{ public static IResourceBuilder<JavaContainerResource> AddJavaContainer( this IDistributedApplicationBuilder builder, string name, string image, string? tag = null) { // ... }}Parameters
builderIDistributedApplicationBuilderThe Hosting.IDistributedApplicationBuilder to add the resource to.namestringThe name of the resource.imagestringThe container image that runs the application, for example mycompany/catalog.tagstring?optionalThe image tag. Defaults to the image's latest tag.Returns
IResourceBuilder<JavaContainerResource>A reference to the ApplicationModel.IResourceBuilder`1.Exceptions
ArgumentNullExceptionbuilder is null.ArgumentExceptionname or image is null, empty, or whitespace.Remarks
JavaHostingExtensions.AddJavaApp instead when Aspire should build and run the application from source. No endpoint is declared, because the port the image listens on is a property of the image. Add one with WithHttpEndpoint(targetPort: 8080), using whichever port the application binds — 8080 for a default Spring Boot or Quarkus image.
Examples
Run a published Spring Boot image and give it a database:
var builder = DistributedApplication.CreateBuilder(args);
var db = builder.AddPostgres("pg").AddDatabase("catalogdb");
builder.AddJavaContainer("catalog", "mycompany/catalog", "1.4.0") .WithHttpEndpoint(targetPort: 8080) .WithReference(db) .WithJvmArgs("-Xmx512m");
builder.Build().Run();AddQuarkusApp(IDistributedApplicationBuilder, string, string)Section titled AddQuarkusApp(IDistributedApplicationBuilder, string, string)extensionIResourceBuilder<JavaAppResource>public static class JavaHostingExtensions{ public static IResourceBuilder<JavaAppResource> AddQuarkusApp( this IDistributedApplicationBuilder builder, string name, string appDirectory) { // ... }}Parameters
builderIDistributedApplicationBuilderThe Hosting.IDistributedApplicationBuilder to add the resource to.namestringThe name of the resource.appDirectorystringThe application directory, containing pom.xml, build.gradle, build.gradle.kts, settings.gradle, or settings.gradle.kts. Relative paths are resolved against the AppHost directory.Returns
IResourceBuilder<JavaAppResource>A reference to the ApplicationModel.IResourceBuilder`1.Exceptions
ArgumentNullExceptionbuilder is null.ArgumentExceptionname or appDirectory is null, empty, or whitespace.InvalidOperationExceptionThe directory contains neither a Maven nor a Gradle build file, or contains both.Remarks
quarkus:dev or quarkusDev) so live coding works, and an HTTP endpoint is declared through QUARKUS_HTTP_PORT, the environment variable Quarkus reads for its listening port. Everything else behaves like JavaHostingExtensions.AddJavaApp. The dev-mode goal compiles the application itself, so Aspire does not add a separate build resource before it. There are two exceptions. JavaHostingExtensions.WithOtelAgent with a build-produced agent cannot be loaded until a build has written it, and a debug session launches the packaged fast JAR rather than the dev-mode wrapper, which no build has written on a clean checkout. Quarkus Dev Services are left enabled but do not activate for anything Aspire supplies: Dev Services only start a container when the corresponding configuration is missing, and a WithReference to a database or broker provides it. That means Aspire's resources are used rather than a second set started underneath.
QUARKUS_PROFILE is set to dev in run mode. Dev mode already selects that profile; setting it explicitly means a debugger, which launches the packaged application rather than the dev-mode wrapper, resolves the same %dev. configuration the application would see when run normally.
In run mode the application is bound to all interfaces. Quarkus enables Host header validation whenever it binds a localhost name, and that filter rejects the hostname Aspire publishes, which makes the endpoint link in the dashboard return 400. Published output is left alone, where the application already binds all interfaces.
No health check is added. /q/health only exists when the application depends on quarkus-smallrye-health, and adding it unconditionally would leave applications without that extension permanently unhealthy and silently stall every WaitFor on them. Add WithHttpHealthCheck("/q/health") when the extension is present.
Examples
A Quarkus service backed by a database Aspire provides:
var builder = DistributedApplication.CreateBuilder(args);
var db = builder.AddPostgres("pg").AddDatabase("inventorydb");
builder.AddQuarkusApp("inventory", "../inventory") .WithReference(db) .WaitFor(db);
builder.Build().Run();AddSpringBootApp(IDistributedApplicationBuilder, string, string)Section titled AddSpringBootApp(IDistributedApplicationBuilder, string, string)extensionIResourceBuilder<JavaAppResource>public static class JavaHostingExtensions{ public static IResourceBuilder<JavaAppResource> AddSpringBootApp( this IDistributedApplicationBuilder builder, string name, string appDirectory) { // ... }}Parameters
builderIDistributedApplicationBuilderThe Hosting.IDistributedApplicationBuilder to add the resource to.namestringThe name of the resource.appDirectorystringThe application directory, containing pom.xml, build.gradle, build.gradle.kts, settings.gradle, or settings.gradle.kts. Relative paths are resolved against the AppHost directory.Returns
IResourceBuilder<JavaAppResource>A reference to the ApplicationModel.IResourceBuilder`1.Exceptions
ArgumentNullExceptionbuilder is null.ArgumentExceptionname or appDirectory is null, empty, or whitespace.InvalidOperationExceptionThe directory contains neither a Maven nor a Gradle build file, or contains both.Remarks
JavaHostingExtensions.AddJavaApp with the common Spring Boot configuration already applied: the build tool is detected when the resource starts, the application is launched through that tool's Spring Boot plugin ( spring-boot:run or bootRun), and an HTTP endpoint is declared through SERVER_PORT, which is the environment variable Spring Boot reads for its listening port. Everything else is the same, so any With… method that works on JavaHostingExtensions.AddJavaApp works here too. The launch goal compiles the application itself, so Aspire does not add a separate build resource before it. Publishing still packages the application with tests skipped ( -DskipTests for Maven, -x test for Gradle). Call JavaHostingExtensions.WithMavenBuild or JavaHostingExtensions.WithGradleBuild afterwards to customize those package arguments. The one thing that does add a build resource is JavaHostingExtensions.WithOtelAgent with a build-produced agent, which cannot be loaded until a build has written it.
No health check is added. /actuator/health only exists when the application depends on spring-boot-starter-actuator, and adding it unconditionally would leave applications without that dependency permanently unhealthy and silently stall every WaitFor on them. Add WithHttpHealthCheck("/actuator/health") when the actuator is present.
Examples
Two Spring Boot services and a database:
var builder = DistributedApplication.CreateBuilder(args);
var db = builder.AddPostgres("pg").AddDatabase("catalogdb");
var catalog = builder.AddSpringBootApp("catalog", "../catalog") .WithReference(db);
builder.AddSpringBootApp("orders", "../orders") .WithReference(catalog) .WaitFor(catalog);
builder.Build().Run();WithGradleBuild(IResourceBuilder<T>, string[])Section titled WithGradleBuild(IResourceBuilder<T>, string[])extensionIResourceBuilder<T>public static class JavaHostingExtensions{ public static IResourceBuilder<T> WithGradleBuild<T>( this IResourceBuilder<T> builder, params string[] args) { // ... }}Parameters
builderIResourceBuilder<T>The resource builder for the Java application.argsstring[]Arguments passed to the Gradle wrapper. Defaults to clean build.Returns
IResourceBuilder<T>A reference to the ApplicationModel.IResourceBuilder`1.Exceptions
ArgumentNullExceptionbuilder or args is null.InvalidOperationExceptionThe application is already configured to build with Maven.Remarks
JavaHostingExtensions.WithGradleTask, that task performs the local compilation, so these arguments normally configure publishing without adding a second run-mode build. Otherwise, the build step is a child resource that the application waits for. No child is created when publishing because the generated container image performs the build. This runs a build before the application starts. To launch the application through Gradle, use JavaHostingExtensions.WithGradleTask instead.
WithGradleTask(IResourceBuilder<T>, string, string[])Section titled WithGradleTask(IResourceBuilder<T>, string, string[])extensionIResourceBuilder<T>java, for example bootRun. public static class JavaHostingExtensions{ public static IResourceBuilder<T> WithGradleTask<T>( this IResourceBuilder<T> builder, string task, params string[] args) { // ... }}Parameters
builderIResourceBuilder<T>The resource builder for the Java application.taskstringThe Gradle task to execute.argsstring[]Additional arguments passed to the Gradle wrapper after the task.Returns
IResourceBuilder<T>A reference to the ApplicationModel.IResourceBuilder`1.Exceptions
ArgumentNullExceptionbuilder or args is null.ArgumentExceptiontask is null, empty, or whitespace.InvalidOperationExceptionThe application is already configured to run a prebuilt JAR or a Maven goal.Remarks
gradlew ( gradlew.bat on Windows) in the resource's working directory and can be overridden with JavaHostingExtensions.WithWrapperPath. WithJarArtifact(IResourceBuilder<T>, string)Section titled WithJarArtifact(IResourceBuilder<T>, string)extensionIResourceBuilder<T>public static class JavaHostingExtensions{ public static IResourceBuilder<T> WithJarArtifact<T>( this IResourceBuilder<T> builder, string jarPath) { // ... }}Parameters
builderIResourceBuilder<T>The resource builder for the Java application.jarPathstringThe path to the JAR produced by the build, relative to the application directory, for example target/app.jar.Returns
IResourceBuilder<T>A reference to the ApplicationModel.IResourceBuilder`1.Exceptions
ArgumentNullExceptionbuilder is null.ArgumentExceptionjarPath is null, empty, or whitespace.Remarks
-plain, -sources, or -javadoc artifact, and fails the build if that is ambiguous. This takes precedence over the JAR named by the jarPath overload of JavaHostingExtensions.AddJavaApp, so a resource can run one JAR locally and publish another. It has no effect on an application published from a prebuilt JAR, because nothing is built in the image for it to select from.
WithJvmArgs(IResourceBuilder<T>, string[])Section titled WithJvmArgs(IResourceBuilder<T>, string[])extensionIResourceBuilder<T>public static class JavaHostingExtensions{ public static IResourceBuilder<T> WithJvmArgs<T>( this IResourceBuilder<T> builder, params string[] args) { // ... }}Parameters
builderIResourceBuilder<T>The resource builder.argsstring[]The JVM arguments, for example -Xmx512m.Returns
IResourceBuilder<T>A reference to the ApplicationModel.IResourceBuilder`1.Exceptions
ArgumentNullExceptionbuilder or args is null.Remarks
JAVA_TOOL_OPTIONS environment variable, which the JVM reads however it was started — java -jar, a Maven goal, a Gradle task, or a container image's own entrypoint, including the JVM those build tools fork. Values containing spaces are quoted, because the JVM splits this variable on whitespace. This is also how a container image that already carries the OpenTelemetry Java agent turns it on, since JavaHostingExtensions.WithOtelAgent copies an agent from the build context and so applies only to applications Aspire itself launches or builds: WithJvmArgs("-javaagent:/app/opentelemetry-javaagent.jar").
WithMainClass(IResourceBuilder<T>, string)Section titled WithMainClass(IResourceBuilder<T>, string)extensionIResourceBuilder<T>public static class JavaHostingExtensions{ public static IResourceBuilder<T> WithMainClass<T>( this IResourceBuilder<T> builder, string mainClass) { // ... }}Parameters
builderIResourceBuilder<T>The resource builder for the Java application.mainClassstringThe fully qualified name of the class declaring main, for example com.example.Application.Returns
IResourceBuilder<T>A reference to the ApplicationModel.IResourceBuilder`1.Exceptions
ArgumentNullExceptionbuilder is null.ArgumentExceptionmainClass is null, empty, or whitespace.Remarks
main method. WithMavenBuild(IResourceBuilder<T>, string[])Section titled WithMavenBuild(IResourceBuilder<T>, string[])extensionIResourceBuilder<T>public static class JavaHostingExtensions{ public static IResourceBuilder<T> WithMavenBuild<T>( this IResourceBuilder<T> builder, params string[] args) { // ... }}Parameters
builderIResourceBuilder<T>The resource builder for the Java application.argsstring[]Arguments passed to the Maven wrapper. Defaults to clean package.Returns
IResourceBuilder<T>A reference to the ApplicationModel.IResourceBuilder`1.Exceptions
ArgumentNullExceptionbuilder or args is null.InvalidOperationExceptionThe application is already configured to build with Gradle.Remarks
JavaHostingExtensions.WithMavenGoal, that goal performs the local compilation, so these arguments normally configure publishing without adding a second run-mode build. Otherwise, the build step is a child resource that the application waits for. No child is created when publishing because the generated container image performs the build. This runs a build before the application starts. To launch the application through Maven, use JavaHostingExtensions.WithMavenGoal instead.
WithMavenGoal(IResourceBuilder<T>, string, string[])Section titled WithMavenGoal(IResourceBuilder<T>, string, string[])extensionIResourceBuilder<T>java, for example spring-boot:run. public static class JavaHostingExtensions{ public static IResourceBuilder<T> WithMavenGoal<T>( this IResourceBuilder<T> builder, string goal, params string[] args) { // ... }}Parameters
builderIResourceBuilder<T>The resource builder for the Java application.goalstringThe Maven goal to execute.argsstring[]Additional arguments passed to the Maven wrapper after the goal.Returns
IResourceBuilder<T>A reference to the ApplicationModel.IResourceBuilder`1.Exceptions
ArgumentNullExceptionbuilder or args is null.ArgumentExceptiongoal is null, empty, or whitespace.InvalidOperationExceptionThe application is already configured to run a prebuilt JAR or a Gradle task.Remarks
mvnw ( mvnw.cmd on Windows) in the resource's working directory and can be overridden with JavaHostingExtensions.WithWrapperPath. WithOtelAgent(IResourceBuilder<T>)Section titled WithOtelAgent(IResourceBuilder<T>)extensionIResourceBuilder<T>public static class JavaHostingExtensions{ public static IResourceBuilder<T> WithOtelAgent<T>( this IResourceBuilder<T> builder) { // ... }}Parameters
builderIResourceBuilder<T>The resource builder.Returns
IResourceBuilder<T>A reference to the ApplicationModel.IResourceBuilder`1.Exceptions
ArgumentNullExceptionbuilder is null.InvalidOperationExceptionThe resource has no Maven or Gradle build configured, so the agent location cannot be inferred. Raised when the application model is built, not when this is called.Remarks
target/agent/opentelemetry-javaagent.jar for Maven and build/agent/opentelemetry-javaagent.jar for Gradle — the conventional output directory of each tool with an agent subdirectory. The build has to put it there; nothing is downloaded. With Maven, copy it with maven-dependency-plugin 's copy goal bound to process-resources; with Gradle, declare the agent in its own configuration and add a Copy task that compileJava depends on. May be called before or after the build tool is configured: which directory the agent is read from is decided when the application model is built, so the result does not depend on the order of builder calls.
Because the build writes the agent, Aspire runs that build as its own resource in run mode and holds the application until it finishes — including for Spring Boot and Quarkus, whose launch goals would otherwise be the only build. This is required rather than an optimization: JAVA_TOOL_OPTIONS is read by every JVM started beneath the resource, and the first of those is the wrapper's own, so an agent the build has not written yet kills that JVM during VM initialization with "Error opening zip file or JAR manifest missing" before the launch goal runs.
Use JavaHostingExtensions.WithOtelAgent when the agent lives anywhere else, including when it is committed to the repository or supplied by the container base image.
WithOtelAgent(IResourceBuilder<T>, string)Section titled WithOtelAgent(IResourceBuilder<T>, string)extensionIResourceBuilder<T>public static class JavaHostingExtensions{ public static IResourceBuilder<T> WithOtelAgent<T>( this IResourceBuilder<T> builder, string agentPath) { // ... }}Parameters
builderIResourceBuilder<T>The resource builder.agentPathstringThe path to the opentelemetry-javaagent.jar file.Returns
IResourceBuilder<T>A reference to the ApplicationModel.IResourceBuilder`1.Exceptions
ArgumentNullExceptionbuilder is null.ArgumentExceptionagentPath is null, empty, or whitespace.Remarks
AddJavaApp regardless of whether an agent is used, so call this only when you want the agent's automatic instrumentation. A relative agentPath is resolved against the application directory and made absolute when running locally. This is required, not cosmetic: JAVA_TOOL_OPTIONS is inherited by every JVM started beneath the resource, and build tools start JVMs whose working directory is not the application directory. The Gradle daemon, for example, starts from its own distribution directory, so a relative -javaagent: path fails to resolve and the daemon dies during VM initialization with "Error opening zip file or JAR manifest missing".
A relative path names a file the build produces, so Aspire runs that build as its own resource in run mode and holds the application until it finishes. An absolute path names a file that exists independently of the build, so no build resource is added.
In publish mode a relative path is rewritten to the location the generated Dockerfile copies the agent to, because the path has to be interpreted inside the container rather than on the build machine. An absolute path is emitted unchanged, since it cannot have come from the build context and must be supplied by the base image or a mount.
WithWrapperPath(IResourceBuilder<T>, string)Section titled WithWrapperPath(IResourceBuilder<T>, string)extensionIResourceBuilder<T>public static class JavaHostingExtensions{ public static IResourceBuilder<T> WithWrapperPath<T>( this IResourceBuilder<T> builder, string wrapperPath) { // ... }}Parameters
builderIResourceBuilder<T>The ApplicationModel.IResourceBuilder`1 to configure.wrapperPathstringThe path to the wrapper script, absolute or relative to the resource's working directory.Returns
IResourceBuilder<T>A reference to the ApplicationModel.IResourceBuilder`1.Exceptions
ArgumentNullExceptionbuilder is null.ArgumentExceptionwrapperPath is null, empty, or whitespace.Remarks