Skip to content

Commit

Permalink
Introduction of maven archetype for bootstrapping apphosts
Browse files Browse the repository at this point in the history
  • Loading branch information
JonathanGiles committed Jul 1, 2024
1 parent 61c0a9f commit 9c15904
Show file tree
Hide file tree
Showing 9 changed files with 264 additions and 17 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ build/

### mvn ###
**/.mvn/
/temp/*
28 changes: 28 additions & 0 deletions aspire4j-maven-archetype/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.microsoft.aspire</groupId>
<artifactId>aspire4j-maven-tools</artifactId>
<version>1.0-SNAPSHOT</version>

<name>Tools for creating Aspire projects</name>

<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven-plugin-tools.version>3.13.1</maven-plugin-tools.version>
</properties>

<dependencies>
<!-- Apache velocity for templating support -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
dir = new File(new File(request.outputDirectory), request.artifactId)

def run(String cmd) {
def process = cmd.execute(null, dir)
process.waitForProcessOutput((Appendable)System.out, System.err)
if (process.exitValue() != 0) {
throw new Exception("Command '$cmd' exited with code: ${process.exitValue()}")
}
}
def mvnFileName = System.properties['os.name'].toLowerCase().contains('windows') ? 'mvn.cmd' : 'mvn'

run("echo 'Updating to latest versions...'")
run("$mvnFileName versions:update-properties -DincludeProperties=bom.version -DgenerateBackupPoms=false")
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<archetype-descriptor name="aspire4j-maven-archetype">
<requiredProperties>
<requiredProperty key="moduleId">
<defaultValue>${artifactId.replaceAll("-", "")}</defaultValue>
</requiredProperty>
<requiredProperty key="includeAzure">
<defaultValue>true</defaultValue>
</requiredProperty>
<requiredProperty key="includeSpring">
<defaultValue>true</defaultValue>
</requiredProperty>
</requiredProperties>
<fileSets>
<fileSet filtered="true" packaged="true" encoding="UTF-8">
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
</includes>
<excludes>
<exclude>**/module-info.java</exclude>
</excludes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>src/main/java</directory>
<includes>
<include>module-info.java</include>
</includes>
</fileSet>
</fileSets>
</archetype-descriptor>
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>

<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mainClass>${package}.AspireAppHost</mainClass>

<!-- This is the property that azd init looks for -->
<aspire.isAppHost>true</aspire.isAppHost>
</properties>

<dependencies>
<!-- dependency on aspire4j -->
<dependency>
<groupId>com.microsoft.aspire</groupId>
<artifactId>aspire4j</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

#if ($includeAzure == "true")
<dependency>
<groupId>com.microsoft.aspire</groupId>
<artifactId>aspire4j-extensions-azure-storage</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
#end

#if ($includeSpring == "true")
<dependency>
<groupId>com.microsoft.aspire</groupId>
<artifactId>aspire4j-extensions-spring</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
#end
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>${mainClass}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<mainClass>${mainClass}</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package ${package};

import com.microsoft.aspire.AppHost;
import com.microsoft.aspire.DistributedApplication;

#if ($includeAzure == "true")
import com.microsoft.aspire.extensions.azure.storage.AzureStorageExtension;
#end
#if ($includeSpring== "true")
import com.microsoft.aspire.extensions.spring.SpringExtension;
#end

public class AspireAppHost implements AppHost {

@Override public void configureApplication(DistributedApplication app) {
app.printExtensions();

#if ($includeAzure == "true")
var azureStorage = app.withExtension(AzureStorageExtension.class)
.addAzureStorage("storage");

var blobStorage = azureStorage.addBlobs("storage-explorer-blobs");
#end

#if ($includeSpring == "true")
var dateService = app.withExtension(SpringExtension.class)
.addSpringProject("date-service-spring")
.withPath("date-service")
.withExternalHttpEndpoints();

var storageExplorer = app.withExtension(SpringExtension.class)
.addSpringProject("storage-explorer-spring")
.withPath("storage-explorer")
.withExternalHttpEndpoints()
.withReference(blobStorage)
.withReference(dateService);
#end
}

public static void main(String[] args) {
new AspireAppHost().boot(args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module ${moduleId} {
exports ${package};

requires com.microsoft.aspire;
requires java.logging;

#if ($includeAzure == "true") requires com.microsoft.aspire.extensions.azure.storage;
#end
#if ($includeSpring == "true") requires com.microsoft.aspire.extensions.spring;
#end
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.microsoft.aspire.resources.properties;

/*
https://learn.microsoft.com/en-us/dotnet/api/aspire.hosting.applicationmodel.endpointreference?view=dotnet-aspire-8.0.1
ContainerHost
Gets the container host for this endpoint.
EndpointName
Gets the name of the endpoint associated with the endpoint reference.
Exists
Gets a value indicating whether the endpoint exists.
Host
Gets the host for this endpoint.
IsAllocated
Gets a value indicating whether the endpoint is allocated.
Port
Gets the port for this endpoint.
Resource
Gets the resource owner of the endpoint reference.
Scheme
Gets the scheme for this endpoint.
TargetPort
Gets the target port for this endpoint. If the port is dynamically allocated, this will return null.
Url
Gets the URL for this endpoint.
*/

/**
* Represents an endpoint reference for a resource with endpoints.
*/
public class EndpointReference {
}
42 changes: 25 additions & 17 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,45 @@
# Aspire4J

This is a proof of concept project, which introduces a minimal example of a Java implementation of the Aspire framework.
It aims to provide a Java-idiomatic developer experience that mimics the concepts introduced by the Aspire framework
for .net. In particular, it introduces the concept of the AppHost, allowing for Java developers to define infrastructure
as code, whilst continuing to rely on the existing Java ecosystem frameworks such as Spring, Micronaut, and Quarkus.
This is a proof of concept project, which introduces a minimal example of a Java implementation of the Aspire framework. It aims to provide a Java-idiomatic developer experience that mimics the concepts introduced by the Aspire framework for .net. In particular, it introduces the concept of the AppHost, allowing for Java developers to define infrastructure as code, whilst continuing to rely on the existing Java ecosystem frameworks such as Spring, Micronaut, and Quarkus.

This GitHub repository is split into six sub-projects:

* `aspire4j`: The core library that provides the AppHost and the ability to define infrastructure as code.
* `aspire4j-extensions-azure-storage`: An extension to the core library that provides the ability to configure Azure Storage resources.
* `aspire4j-extensions-azure`: A wrapper project that developers could use to bring in all Azure extensions at once.
* `storage-explorer`: A sample Spring application that is designed to work with Azure Services. It does not have any
specific knowledge of the Aspire4J framework or how to deploy to Azure.
* `storage-explorer`: A sample Spring application that is designed to work with Azure Services. It does not have any specific knowledge of the Aspire4J framework or how to deploy to Azure.
* `date-service`: A simple Spring application that provides a date microservice. It is used by the `storage-explorer`.
* `storage-explorer-apphost`: The infrastructure as code project that defines how the `storage-explorer` application,
using the Aspire4J framework, should be deployed to Azure.
* `storage-explorer-apphost`: The infrastructure as code project that defines how the `storage-explorer` application, using the Aspire4J framework, should be deployed to Azure.

In this way, the file of most interest is the
[StorageExplorerAppHost file](https://github.com/JonathanGiles/aspire4j/blob/main/storage-explorer-apphost/src/main/java/com/microsoft/aspire/springsample/StorageExplorerAppHost.java),
which defines the infrastructure as code.
In this way, the file of most interest is the [StorageExplorerAppHost file](https://github.com/JonathanGiles/aspire4j/blob/main/storage-explorer-apphost/src/main/java/com/microsoft/aspire/springsample/StorageExplorerAppHost.java), which defines the infrastructure as code.

## Getting Started

> [!IMPORTANT]
> Because this project is a very early proof of concept, `azd` does not know how to work with Aspire4J projects yet. To
work around this, we have developed a fork of `azd` that can be used to work with Aspire4J projects. Instructions on
how to work with this fork should [be followed here](https://github.com/Azure/azure-dev-pr/pull/1670).
> Because this project is a very early proof of concept, `azd` does not know how to work with Aspire4J projects yet. To work around this, we have developed a fork of `azd` that can be used to work with Aspire4J projects. Instructions on how to work with this fork should [be followed here](https://github.com/Azure/azure-dev-pr/pull/1670).
With the new `azd` installed, you can proceed with running this project locally, and having it be deployed into Azure
by following these instructions:
With the new `azd` installed, you can proceed with running this project locally, and having it be deployed into Azure by following these instructions:

1. Clone this repository onto your machine.
2. Open a terminal and navigate to the root of the repository.
3. Run `azd init`, followed by `azd up`.

Feedback is welcome!
Feedback is welcome!

## Using Aspire4J

If you want to use Aspire4J in your Java microservice projects, you can! Here's how you can create your own Aspire App Host:

1. Clone this repository onto your machine.
2. From the root of the repository, run `mvn -f aspire4j-maven-archetype clean install`.
3. Go to your existing Java project and run the following:

```shell
mvn archetype:generate \
-DarchetypeGroupId=com.microsoft.aspire \
-DarchetypeArtifactId=aspire4j-maven-archetype \
-DarchetypeVersion=1.0-SNAPSHOT
```

4. Follow the prompts to create your new Aspire4J project.
5. You will see a new directory created in your project with the name you provided in the prompt. Inside this directory you will find a new `AspireAppHost` Java class that you can use to define your infrastructure as code.

0 comments on commit 9c15904

Please sign in to comment.