Flange Cloud™ Quick Start

Flange Cloud initially supports the Amazon Web Services cloud platform.

Requisites

Development

Service interfaces (e.g. CalendarService) and service implementations (e.g. CalendarServiceImpl) must be in separate Maven projects. This allows cloud components to access services without being tightly coupled to service implementations, which may be deployed independently. Otherwise individual Maven projects may be built together as aggregatess of a composite project, or may be developed independently as separate projects. Flange doesn't care if you store your entire application in a single source code repository or in multiple repositories.

Service Interface

@CloudFunctionApi
public interface CalendarService {

  CompletableFuture<Optional<String>> findHolidayName(LocalDate date);
…

Service Implementation

@CloudFunctionService
@ServiceConsumer(OtherService.class)
public class CalendarServiceImpl implements CalendarService {

  private final OtherService otherService;

  public CalendarServiceImpl(OtherService otherService) {
    this.otherService = requireNonNull(otherService);
  }

  @Override
  public CompletableFuture<Optional<String>> findHolidayName(LocalDate date) {
    if(date.getDayOfYear() == 1) {
      return CompletableFuture.completedFuture(Optional.of("New Year"));
    }
    //TODO check for other holidays
    return CompletableFuture.completedFuture(Optional.empty());
…

Flange Cloud Application (optional)

You can create an application “driver” program to invoke your functions for testing locally or invoking functions in the cloud. Flange Cloud provides an extremely lightweight FlangeCloudApplication interface to facility creating an application that recognizes command-line arguments for invoking deployed cloud functions, just as deployed Flange services invoke other Flange services in the cloud. The interface provides a convenient FlangeCloudApplication.start(…) method to execute your application from the main(…) entrypoint. The following example shows a simple application that implements FlangeCloudApplication and uses a CalendarService that may be local or in the cloud.

@ServiceConsumer(CalendarService.class)
public class HolidayApp implements FlangeCloudApplication {

  private final CalendarService calendarService;

  public HolidayApp(CalendarService calendarService) {
    this.calendarService = requireNonNull(calendarService);
  }

  @Override
  public void run() {
    //TODO access `calendarService`
  }

  public static void main(String[] args) {
    FlangeCloudApplication.start(HolidayApp.class, args);
  }

}

Executing the application locally or in the cloud is explained in a section below.

Declare Local Dependency Implementations (optional)

If you intend to run your application locally, for example from a local application “driver” program as explained in the previous section, you must prepare a flange-dependencies.lst file in the application project (typically in src/main/resources/), indicating the full path and class name of each service implementation as in the example below. Flange currently does no classpath scanning, which allows for faster cold start times. Classpath scanning may be provided as a configurable option in a future version of Flange.

com.example.calendar.service.impl.CalendarServiceImpl
com.example.other.service.impl.OtherServiceImpl

Build

Dependency Management

Before including specific Flange dependencies in individual projects as needed, it is easiest to place the entire Flange bill of materials (BOM) under dependency management. Add the following to a parent POM, setting flange.version appropriately:

<dependencyManagement>
  <dependencies>
    …
    <dependency>
      <groupId>dev.flange</groupId>
      <artifactId>flange-bom</artifactId>
      <version>${flange.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

Annotation Processing

Turn on Flange Cloud annotation processing in your Maven project(s) for the Maven Compiler Plugin. It is recommended to simply add the following to a parent POM, setting flange.version appropriately:

<build>
  <pluginManagement>
    <plugins>
      …
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <annotationProcessorPaths>
            <annotationProcessorPath>
              <groupId>dev.flange</groupId>
              <artifactId>flange-build</artifactId>
              <version>${flange.version}</version>
            </annotationProcessorPath>
          </annotationProcessorPaths>
          <annotationProcessors>
            <annotationProcessor>dev.flange.build.cloud.FlangeCloudAnnotationProcessor</annotationProcessor>
          </annotationProcessors>
        </configuration>
      </plugin>
    </plugins>
  </pluginManagement>
</build>

Flange Cloud Dependency

Each component using Flange Cloud interface (primarily annotations and exceptions) must include the Flange Cloud API dependency, dev.flange:flange-cloud:

<dependencies>
  …
  <dependency>
    <groupId>dev.flange</groupId>
    <artifactId>flange-cloud</artifactId>
  </dependency>
</dependencies>

Service Implementation Runtime Dependency

Each project containing one or more service implementations must declare the dev.flange:flange-cloud-aws-runtime dependency to provide the necessary runtime support when deployed to the cloud. Declare the dependency with provided scope so that this cloud-related code will not be included when executing locally; the Flange Cloud assembly (see below) will know how to include the runtime appropriately when deploying to the cloud, as long as it is declared in the POM as so:

<dependencies>
  …
  <dependency>
    <groupId>dev.flange</groupId>
    <artifactId>flange-cloud-aws-runtime</artifactId>
    <scope>provided</scope>
  </dependency>
</dependencies>

Service Implementation Assembly Configuration

For each service implementation to deployed as a cloud flunction, configure the Maven Assembly Plugin in the project POM for the service using the following form. Replace ServiceImpl with the name of your service implementation class, such as CalenderServiceImpl from the example above.

<build>
  <plugins>
    …
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-assembly-plugin</artifactId>
      <executions>
        <execution>
          <phase>package</phase>
          <goals>
            <goal>single</goal>
          </goals>
          <configuration>
            <finalName>ServiceImpl</finalName>
            <appendAssemblyId>true</appendAssemblyId>
            <descriptors>
              <descriptor>${project.build.directory}/generated-sources/annotations/assembly-ServiceImpl-aws-lambda.xml</descriptor>
            </descriptors>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Performing a Build

Performing a build and preparing for deploying is done in typical Maven fashion:

mvn clean package

A full clean build is required before deploying to the cloud.

Deployment

CloudFormation Environment Stack

Flange Cloud requires that you have a CloudFormation stack to serve as your deployment environment such as dev, test-jdoe, or prod. Multiple deployment environments can be set up on the same AWS account.

The CloudFormation stack name must be in the form flange-environment, where environment is the identifier of the development environment the stack defines. (🚧 Future versions of Flange will allow more flexibility in the stack name.) The stack must export the following outputs:

flange-environment:FlangeStage
The deployment stage, such as def, qa, or prod
flange-environment:FlangeProfilesActive
The comma-separated list of active profiles, such as dev,test.
flange-environment:StagingBucketName
The name of the S3 bucket for staging artifacts.

Deploy to the Cloud

Use the cloud deploy command of the Flange command-line interface (CLI) script flange.sh, found in the bin/ directory in the source code distribution, to deploy your services to the cloud. You may invoke the Flange CLI in a service implementation Maven project to deploy an individual service to the cloud, or invoke the Flange CLI in the root directory of an aggregate Maven project to deploy all services to the cloud. The following example assumes you have a CloudFormation stack (see above) for a deployment environment named dev.

flange.sh cloud deploy dev

Execution

Once you deploy your services to the cloud, they automatically know how to invoke other cloud services they depend on. In order to manually invoke a deployed Flange cloud function service, you can create a local application serving as a “driver”, as explained above. (The other option for manually invoking a deployed Flange cloud function service is to use a low-level cloud invocation, which requires knowledge of the underlying Flange Cloud marshalling technique and which is outside the scope of this quick start.)

Local Application Execution, Local Service Invocation

To execute your application locally, invoking your services locally, simply run your application as you would normally, either from the command line or within your IDE.

Local Application Execution, Cloud Service Invocation

You can also execute your application locally, but have it invoke your deployed services in the cloud (assuming you have already deployed the services as explained above). This requires that your application use the FlangeCloudApplication facility explained above. Execute it using the Flange CLI bin/flange.sh exec. Indicate the aws platform using the --flange-platform option, specify the deployment environment using the --flange-env option. The following example shows how to execute one of the applications from the published examples, invoking services deployed on the AWS platform in the dev deployment environment. Don't forget to include -- after flange.sh exec to indicate that the --flange-* arguments are intended for the application, not the the Flange CLI itself.

flange.sh exec -- \
    dev.flange.example.cloud.hellouser_faas.app.HelloUserFaasApp \
    --flange-platform aws --flange-env dev