Halyx 1.1.0

Halyx 1.1.0 adds a ninth service, function invocation, and reads keys and passwords from a parameter store as they're used, so rotating one no longer means restarting. It also brings Kotlin coroutines to listeners and repositories. Code written for 1.0 keeps compiling and running unchanged.

Release on GitHub

Function invocation#

Issue #22. A FunctionInvoker calls an AWS Lambda function, an Azure Function or a Cloud Run function by name, with each cloud's login: IAM on Lambda, an Entra ID token or a function key on Azure, and a Google ID token on Cloud Run.

Java
FunctionInvoker resize = halyx.provider("images").functionInvoker("resize-image");

FunctionResponse response = resize.invoke(FunctionRequest.builder("{\"key\":\"a.png\"}")
        .header("X-Tenant", tenant)
        .build());

The behaviour is the same on all three clouds:

A function conformance kit checks every provider: in memory, on Floci's Lambda, the Azure Functions host and Google's Functions Framework, and on real Lambda, Azure Functions and Cloud Run functions. See the functions guide.

Keys and passwords that rotate#

Issue #26. Logging in with IAM or Entra ID is still the best way, but some services take a key or a password. Halyx now reads them from a parameter store as they're used, so a rotation takes effect without a restart:

In Spring Boot, these are secrets entries and auth.secret:

YAML
halyx:
  providers:
    azure:
      type: azure
      properties:
        azure.cosmos.endpoint: https://acme.documents.azure.com:443/
      secrets:
        - property: azure.cosmos.key
          store: app-secrets       # one of halyx.parameter-stores, on any provider
          name: orders-cosmos-key

A missing secret fails the start, naming the entry, and so does a halyx.* value whose ${...} placeholder didn't resolve. Before, Spring left the placeholder as written, and it was sent as the key. The store can be on another cloud: a function on Azure can keep its key in AWS Secrets Manager. See Keys for other services.

Note

Service Bus and App Configuration connection strings are still read once, because their SDKs copy the key when the client is built. For keys that rotate there, log in with Entra ID.

Kotlin coroutines#

Issue #11. A @HalyxListener can be a suspend fun, for subscriptions and stream consumers. Returning acknowledges the message and throwing retries it, as with any listener. Repositories take suspend CRUD methods and derived queries, with Flow results read page by page.

@HalyxListener("billing")
suspend fun onOrder(placed: CloudEvent) {
    invoices.put(BlobKey.of(placed.subject().orElseThrow()), render(placed)).awaitSingle()
}

Tested on Boot 3.5 (Kotlin 1.9) and Boot 4 (Kotlin 2.3). See Reactive applications.

Also in 1.1.0#

Before the release, every real-cloud tier passed on AWS, Azure and Google Cloud, with Spring Boot 3.5 and 4, including the key rotation tests on Azure. The portable orders service passed on EKS, GKE and AKS. The results are in Cloud testing.

Upgrading#

Bump the BOM; nothing else changes.

implementation(platform("dev.halyx:halyx-bom:1.1.0"))

From 1.1.0, security fixes go to the 1.1 line.