Micronaut® Blog

Micronaut now supports Microsoft Azure Functions

By Sergio del Amo (Object Computing Grails & Micronaut Team)

May 15, 2020

Tags: #azure #serverless

The Micronaut team at Object Computing is pleased to announce that Micronaut 2.0.0.M3 now features support for developing serverless applications with Azure Functions. If you want to develop Azure Functions with Java, you'll find that you can dramatically improve your productivity and build incredibly fast and lightweight applications with the Micronaut framework.

Micronaut's Azure-friendly features include support for using dependency injection, validation, and AOP annotations within your serverless code.

Two Micronaut Azure Modules

Micronaut offers two modules to help you with the development of Azure Functions:

Micronaut Simple Azure Functions

Azure Functions support many triggers beyond HTTP, including Queue, Timer, and Blob storage. Simple Azure Functions are for these non-HTTP triggers.

Moreover, if your function only needs to bind to a single HTTP endpoint, you may choose Simple Azure Functions as well.

You can use dependency injection and validation within your functions as illustrated below:

public interface NameTransformer {
   @NonNull
   String transform(@NonNull @NotBlank String name);
}

@Singleton
public CapitalizeNameTransformer implements NameTransformer {
  @Override
  @NonNull
  public String transform(@NonNull @NotBlank String name) {
      return StringUtils.capitalize(name);
  }
}

public class NameTransformFunction extends AzureFunction {
    @Inject // 1️⃣
    NameTransformer nameTransformer

    public String echo(
          @HttpTrigger(name = "req",
                       methods = HttpMethod.GET,
                       authLevel = AuthorizationLevel.ANONYMOUS)
           HttpRequestMessage<Optional<String>> request,
           ExecutionContext context) {
        try {
            String name = request.getQueryParameters().get("name");
            return nameTransformer.transform(name);
        } catch(ConstraintViolationException e) { // 2️⃣
            return "The supplied name must be not blank";
        }
    }
}

1️⃣ User can dependency inject fields with @Inject. 2️⃣ Name::transformer parameter constraints are enforced.

Micronaut Azure Http Functions

If your function needs to respond to multiple HTTP endpoints, or if you want to write regular Micronaut controllers and have them executed using an Azure Function, you can choose Azure HTTP Functions.

With the Micronaut Azure HTTP Functions module, for the previous example, instead of NameTransformFunction, you will have a controller:

@Controller("/")
public NameController {

    private final NameTransformer transformer;

    public NameController(NameTransformer transformer) { // 1️⃣
        this.transformer = transformer;
    }

    @Produces(MediaType.TEXT_PLAIN)
    @Get
    public String index(@Nullable String name) {
        try {
            return transformer.transform(name);
        } catch(ConstraintViolationException e) {
            return "The supplied name must be not blank";
        }
    }
}

1️⃣ Micronaut supports constructor based injection as well.

In addition, testing Micronaut Azure Functions is easy. The next test shows how to test the previous controller:

public class NameControllerTest {

    @Test
    public void testNameSupplied() throws Exception {
        try (Function function = new Function()) {
            HttpRequestMessageBuilder.AzureHttpResponseMessage response =
                function.request(HttpMethod.GET, "/")
                        .parameter("name", "sergio")
                        .invoke();
            assertEquals(HttpStatus.OK, response.getStatus());
            assertEquals("Sergio", response.getBodyAsString());
        }
    }
}

Next Steps

As you'll quickly see, by combining Micronaut and Azure, you don't have to give up the software paradigms that make you productive and keep your code robust when coding Java serverless functions.