diff --git a/src/Aspire.CommunityToolkit.Hosting.Java/JavaAppHostingExtension.cs b/src/Aspire.CommunityToolkit.Hosting.Java/JavaAppHostingExtension.cs
index 29e61e58..ab06304e 100644
--- a/src/Aspire.CommunityToolkit.Hosting.Java/JavaAppHostingExtension.cs
+++ b/src/Aspire.CommunityToolkit.Hosting.Java/JavaAppHostingExtension.cs
@@ -19,27 +19,21 @@ public static class JavaAppHostingExtension
/// A reference to the .
public static IResourceBuilder AddJavaApp(this IDistributedApplicationBuilder builder, string name, JavaAppContainerResourceOptions options)
{
- if (string.IsNullOrWhiteSpace(options.ContainerImageName) == true)
- {
- throw new ArgumentException("Container image name must be specified.", nameof(options));
- }
+ ArgumentNullException.ThrowIfNull(builder, nameof(builder));
+ ArgumentNullException.ThrowIfNull(options, nameof(options));
+ ArgumentException.ThrowIfNullOrWhiteSpace(name, nameof(name));
+ ArgumentException.ThrowIfNullOrWhiteSpace(options.ContainerImageName, nameof(options.ContainerImageName));
var resource = new JavaAppContainerResource(name);
- var rb = builder.AddResource(resource);
- if (string.IsNullOrWhiteSpace(options.ContainerRegistry) == false)
- {
- rb.WithImageRegistry(options.ContainerRegistry);
- }
- rb.WithImage(options.ContainerImageName)
- .WithImageTag(options.ContainerImageTag)
+ var rb = builder.AddResource(resource)
+ .WithAnnotation(new ContainerImageAnnotation { Image = options.ContainerImageName, Tag = options.ContainerImageTag, Registry = options.ContainerRegistry })
.WithHttpEndpoint(port: options.Port, targetPort: options.TargetPort, name: JavaAppContainerResource.HttpEndpointName)
.WithJavaDefaults(options);
+
if (options.Args is { Length: > 0 })
{
-#pragma warning disable CS8604 // Possible null reference argument.
rb.WithArgs(options.Args);
-#pragma warning restore CS8604 // Possible null reference argument.
}
return rb;
@@ -52,10 +46,8 @@ public static IResourceBuilder AddJavaApp(this IDistri
/// The name of the resource.
/// The to configure the Java application."
/// A reference to the .
- public static IResourceBuilder AddSpringApp(this IDistributedApplicationBuilder builder, string name, JavaAppContainerResourceOptions options)
- {
- return builder.AddJavaApp(name, options);
- }
+ public static IResourceBuilder AddSpringApp(this IDistributedApplicationBuilder builder, string name, JavaAppContainerResourceOptions options) =>
+ builder.AddJavaApp(name, options);
///
/// Adds a Java application to the application model. Executes the executable Java app.
@@ -67,6 +59,11 @@ public static IResourceBuilder AddSpringApp(this IDist
/// A reference to the .
public static IResourceBuilder AddJavaApp(this IDistributedApplicationBuilder builder, string name, string workingDirectory, JavaAppExecutableResourceOptions options)
{
+ ArgumentNullException.ThrowIfNull(builder, nameof(builder));
+ ArgumentNullException.ThrowIfNull(options, nameof(options));
+ ArgumentException.ThrowIfNullOrWhiteSpace(name, nameof(name));
+ ArgumentException.ThrowIfNullOrWhiteSpace(workingDirectory, nameof(workingDirectory));
+
#pragma warning disable CS8601 // Possible null reference assignment.
string[] allArgs = options.Args is { Length: > 0 }
? ["-jar", options.ApplicationName, .. options.Args]
@@ -90,10 +87,8 @@ public static IResourceBuilder AddJavaApp(this IDistr
/// The working directory to use for the command. If null, the working directory of the current process is used.
/// The to configure the Java application."
/// A reference to the .
- public static IResourceBuilder AddSpringApp(this IDistributedApplicationBuilder builder, string name, string workingDirectory, JavaAppExecutableResourceOptions options)
- {
- return builder.AddJavaApp(name, workingDirectory, options);
- }
+ public static IResourceBuilder AddSpringApp(this IDistributedApplicationBuilder builder, string name, string workingDirectory, JavaAppExecutableResourceOptions options) =>
+ builder.AddJavaApp(name, workingDirectory, options);
private static IResourceBuilder WithJavaDefaults(
this IResourceBuilder builder,
diff --git a/tests/Aspire.CommunityToolkit.Hosting.Java.Tests/ContainerResourceCreationTests.cs b/tests/Aspire.CommunityToolkit.Hosting.Java.Tests/ContainerResourceCreationTests.cs
new file mode 100644
index 00000000..b29ba492
--- /dev/null
+++ b/tests/Aspire.CommunityToolkit.Hosting.Java.Tests/ContainerResourceCreationTests.cs
@@ -0,0 +1,104 @@
+namespace Aspire.CommunityToolkit.Hosting.Java.Tests;
+public class ContainerResourceCreationTests
+{
+ [Fact]
+ public void AddJavaAppBuilderShouldNotBeNull()
+ {
+ IDistributedApplicationBuilder builder = null!;
+
+ Assert.Throws(() => builder.AddJavaApp("java", new JavaAppContainerResourceOptions()));
+ }
+
+ [Fact]
+ public void AddSpringAppBuilderShouldNotBeNull()
+ {
+ IDistributedApplicationBuilder builder = null!;
+
+ Assert.Throws(() => builder.AddSpringApp("spring", new JavaAppContainerResourceOptions()));
+ }
+
+ [Fact]
+ public void AddJavaAppNameShouldNotBeNullOrWhiteSpace()
+ {
+ IDistributedApplicationBuilder builder = DistributedApplication.CreateBuilder();
+
+ Assert.Throws(() => builder.AddJavaApp(null!, new JavaAppContainerResourceOptions()));
+ Assert.Throws(() => builder.AddJavaApp("", new JavaAppContainerResourceOptions()));
+ }
+
+ [Fact]
+ public void AddSpringAppNameShouldNotBeNullOrWhiteSpace()
+ {
+ IDistributedApplicationBuilder builder = DistributedApplication.CreateBuilder();
+
+ Assert.Throws(() => builder.AddSpringApp(null!, new JavaAppContainerResourceOptions()));
+ Assert.Throws(() => builder.AddSpringApp("", new JavaAppContainerResourceOptions()));
+ }
+
+ [Fact]
+ public void AddJavaAppContainerImageNameShouldNotBeNullOrWhiteSpace()
+ {
+ IDistributedApplicationBuilder builder = DistributedApplication.CreateBuilder();
+
+ Assert.Throws(() => builder.AddJavaApp("java", new JavaAppContainerResourceOptions { ContainerImageName = null! }));
+ Assert.Throws(() => builder.AddJavaApp("java", new JavaAppContainerResourceOptions { ContainerImageName = "" }));
+ }
+
+ [Fact]
+ public void AddJavaAppContainerResourceOptionsShouldNotBeNull()
+ {
+ IDistributedApplicationBuilder builder = DistributedApplication.CreateBuilder();
+
+ Assert.Throws(() => builder.AddJavaApp("java", null!));
+ }
+
+ [Fact]
+ public void AddSpringAppContainerResourceOptionsShouldNotBeNull()
+ {
+ IDistributedApplicationBuilder builder = DistributedApplication.CreateBuilder();
+
+ Assert.Throws(() => builder.AddSpringApp("spring", null!));
+ }
+
+ [Fact]
+ public async Task AddJavaAppContainerDetailsSetOnResource()
+ {
+ IDistributedApplicationBuilder builder = DistributedApplication.CreateBuilder();
+
+ var options = new JavaAppContainerResourceOptions
+ {
+ ContainerImageName = "java-app",
+ ContainerRegistry = "docker.io",
+ ContainerImageTag = "latest",
+ Port = 8080,
+ TargetPort = 8080,
+ OtelAgentPath = "path/to/otel",
+ Args = ["arg1", "arg2"]
+ };
+
+ builder.AddJavaApp("java", options);
+
+ using var app = builder.Build();
+
+ var appModel = app.Services.GetRequiredService();
+
+ var resource = appModel.Resources.OfType().SingleOrDefault();
+
+ Assert.NotNull(resource);
+ Assert.Equal("java", resource.Name);
+
+ Assert.True(resource.TryGetLastAnnotation(out ContainerImageAnnotation? imageAnnotations));
+ Assert.Equal(options.ContainerImageName, imageAnnotations.Image);
+ Assert.Equal(options.ContainerRegistry, imageAnnotations.Registry);
+ Assert.Equal(options.ContainerImageTag, imageAnnotations.Tag);
+
+ Assert.True(resource.TryGetLastAnnotation(out EndpointAnnotation? httpEndpointAnnotations));
+ Assert.Equal(options.Port, httpEndpointAnnotations.Port);
+ Assert.Equal(options.TargetPort, httpEndpointAnnotations.TargetPort);
+
+ Assert.True(resource.TryGetLastAnnotation(out CommandLineArgsCallbackAnnotation? argsAnnotations));
+ CommandLineArgsCallbackContext context = new([]);
+ await argsAnnotations.Callback(context);
+ Assert.All(options.Args, arg => Assert.Contains(arg, context.Args));
+ }
+}
diff --git a/tests/Aspire.CommunityToolkit.Hosting.Java.Tests/ExecutableResourceCreationTests.cs b/tests/Aspire.CommunityToolkit.Hosting.Java.Tests/ExecutableResourceCreationTests.cs
new file mode 100644
index 00000000..f4825540
--- /dev/null
+++ b/tests/Aspire.CommunityToolkit.Hosting.Java.Tests/ExecutableResourceCreationTests.cs
@@ -0,0 +1,101 @@
+namespace Aspire.CommunityToolkit.Hosting.Java.Tests;
+
+public class ExecutableResourceCreationTests
+{
+ [Fact]
+ public void AddJavaAppBuilderShouldNotBeNull()
+ {
+ IDistributedApplicationBuilder builder = null!;
+
+ Assert.Throws(() => builder.AddJavaApp("java", Environment.CurrentDirectory, new JavaAppExecutableResourceOptions()));
+ }
+
+ [Fact]
+ public void AddSpringAppBuilderShouldNotBeNull()
+ {
+ IDistributedApplicationBuilder builder = null!;
+
+ Assert.Throws(() => builder.AddSpringApp("spring", Environment.CurrentDirectory, new JavaAppExecutableResourceOptions()));
+ }
+
+ [Fact]
+ public void AddJavaAppNameShouldNotBeNullOrWhiteSpace()
+ {
+ IDistributedApplicationBuilder builder = DistributedApplication.CreateBuilder();
+
+ Assert.Throws(() => builder.AddJavaApp(null!, Environment.CurrentDirectory, new JavaAppExecutableResourceOptions()));
+ Assert.Throws(() => builder.AddJavaApp("", Environment.CurrentDirectory, new JavaAppExecutableResourceOptions()));
+ }
+
+ [Fact]
+ public void AddSpringAppNameShouldNotBeNullOrWhiteSpace()
+ {
+ IDistributedApplicationBuilder builder = DistributedApplication.CreateBuilder();
+
+ Assert.Throws(() => builder.AddSpringApp(null!, Environment.CurrentDirectory, new JavaAppExecutableResourceOptions()));
+ Assert.Throws(() => builder.AddSpringApp("", Environment.CurrentDirectory, new JavaAppExecutableResourceOptions()));
+ }
+
+ [Fact]
+ public void AddJavaAppWorkingDirectoryShouldNotBeNullOrWhiteSpace()
+ {
+ IDistributedApplicationBuilder builder = DistributedApplication.CreateBuilder();
+
+ Assert.Throws(() => builder.AddJavaApp("java", null!, new JavaAppExecutableResourceOptions()));
+ Assert.Throws(() => builder.AddJavaApp("java", "", new JavaAppExecutableResourceOptions()));
+ }
+
+ [Fact]
+ public void AddJavaAppExecutableResourceOptionsShouldNotBeNull()
+ {
+ IDistributedApplicationBuilder builder = DistributedApplication.CreateBuilder();
+
+ Assert.Throws(() => builder.AddJavaApp("java", Environment.CurrentDirectory, null!));
+ }
+
+ [Fact]
+ public void AddSpringAppContainerResourceOptionsShouldNotBeNull()
+ {
+ IDistributedApplicationBuilder builder = DistributedApplication.CreateBuilder();
+
+ Assert.Throws(() => builder.AddSpringApp("spring", Environment.CurrentDirectory, null!));
+ }
+
+ [Fact]
+ public async Task AddJavaAppContainerDetailsSetOnResource()
+ {
+ IDistributedApplicationBuilder builder = DistributedApplication.CreateBuilder();
+
+ var options = new JavaAppExecutableResourceOptions
+ {
+ ApplicationName = "test.jar",
+ Args = ["--test"],
+ OtelAgentPath = "otel-agent",
+ Port = 8080
+ };
+
+ builder.AddJavaApp("java", Environment.CurrentDirectory, options);
+
+ using var app = builder.Build();
+
+ var appModel = app.Services.GetRequiredService();
+
+ var resource = appModel.Resources.OfType().SingleOrDefault();
+
+ Assert.NotNull(resource);
+ Assert.Equal("java", resource.Name);
+
+ Assert.Equal(Environment.CurrentDirectory, resource.WorkingDirectory);
+ Assert.Equal("java", resource.Command);
+
+ Assert.True(resource.TryGetLastAnnotation(out EndpointAnnotation? httpEndpointAnnotations));
+ Assert.Equal(options.Port, httpEndpointAnnotations.Port);
+
+ Assert.True(resource.TryGetLastAnnotation(out CommandLineArgsCallbackAnnotation? argsAnnotations));
+ CommandLineArgsCallbackContext context = new([]);
+ await argsAnnotations.Callback(context);
+ Assert.All(options.Args, arg => Assert.Contains(arg, context.Args));
+ Assert.Contains("-jar", context.Args);
+ Assert.Contains(options.ApplicationName, context.Args);
+ }
+}