Spring Cloud Azure developer guide

This article applies to: ✔️ Version 4.5.0 ✔️ Version 5.0.0

For more information about supported versions, see Spring Versions Mapping.

Spring is an open-source application framework developed by VMware that provides a simplified, modular approach for creating Java applications. Spring Cloud Azure is an open-source project that provides seamless Spring integration with Azure.

Get help

If you have any questions about this documentation, create a GitHub issue in one of the following GitHub repositories. Pull requests are also welcome.

GitHub repositories Description
Azure/azure-sdk-for-java This repository holds the source code.
MicrosoftDocs/azure-dev-docs This repository holds the documentation.

What's new in 4.0 since 3.10.x

This documentation covers changes made in 4.0 since 3.10. This major release brings better security, leaner dependencies, support for production readiness, and more.

Tip

For more information on migrating to 4.0, see Migration guide for 4.0.

The following list summarizes some of the changes that Spring Cloud Azure 4.0 provides:

  • A unified development experience, with unified project name, artifact ID, and properties.
  • Simplified dependency management using a single spring-cloud-azure-dependencies BOM.
  • Expanded Azure support on Spring Initializr to cover Kafka, Event Hubs, Azure Cache for Redis, and Azure App Configuration.
  • Rearchitected Spring module dependencies to remove excess layers and entanglement.
  • Managed Identity support for Azure App Configuration, Event Hubs, Service Bus, Azure Cosmos DB, Key Vault, Storage Blob, and Storage Queue.
  • Continued support for authentication methods in the underlying Azure SDK from our Spring libraries, such as SAS token and token credential authentication with Service Bus and Event Hubs.
  • Credential chain is now enabled by default, enabling applications to obtain credentials from application properties, environment variables, managed identity, IDEs, and so on.
  • Granular access control at the resource level (such as Service Bus queue) to enable better security governance and adherence to IT policies.
  • More options exposed in a Spring-idiomatic way through significantly improved auto-configuration coverage of Azure SDK clients for both synchronous and asynchronous scenarios.
  • Added health indicators for Azure App Configuration, Event Hubs, Azure Cosmos DB, Key Vault, Storage Blob, Storage Queue, and Storage File.
  • Spring Cloud Sleuth support for all HTTP-based Azure SDKs.

Migration guide for 4.0

For more information on migrating to 4.0, see Migration guide for 4.0.

Getting started

Setting up dependencies

Bill of materials (BOM)

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.azure.spring</groupId>
      <artifactId>spring-cloud-azure-dependencies</artifactId>
      <version>${spring.cloud.azure.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

Starter dependencies

Spring Cloud Azure Starters are a set of convenient dependency descriptors to include in your application. Each starter contains all the dependencies and transitive dependencies needed to begin using their corresponding Spring Cloud Azure module. These starters boost your Spring Boot application development with Azure services.

For example, if you want to get started using Spring and Azure Cosmos DB for data persistence, include the spring-cloud-azure-starter-cosmos dependency in your project.

The following table lists application starters provided by Spring Cloud Azure under the com.azure.spring group:

Name Description
spring-cloud-azure-starter The core starter, including auto-configuration support.
spring-cloud-azure-starter-active-directory The starter for using Azure Active Directory with Spring Security.
spring-cloud-azure-starter-active-directory-b2c The starter for using Azure Active Directory B2C with Spring Security.
spring-cloud-azure-starter-appconfiguration The starter for using Azure App Configuration.
spring-cloud-azure-starter-cosmos The starter for using Azure Cosmos DB.
spring-cloud-azure-starter-eventhubs The starter for using Azure Event Hubs.
spring-cloud-azure-starter-keyvault The Starter for using Azure Key Vault.
spring-cloud-azure-starter-keyvault-secrets The starter for using Azure Key Vault Secrets.
spring-cloud-azure-starter-keyvault-certificates The starter for using Azure Key Vault Certificates.
spring-cloud-azure-starter-servicebus The starter for using Azure Service Bus.
spring-cloud-azure-starter-servicebus-jms The starter for using Azure Service Bus and JMS.
spring-cloud-azure-starter-storage The starter for using Azure Storage.
spring-cloud-azure-starter-storage-blob The starter for using Azure Storage Blob.
spring-cloud-azure-starter-storage-file-share The starter for using Azure Storage File Share.
spring-cloud-azure-starter-storage-queue The starter for using Azure Storage Queue.
spring-cloud-azure-starter-actuator The starter for using Spring Boot’s Actuator, which provides production ready features.

The following table lists starters for Spring Data support:

Name Description
spring-cloud-azure-starter-data-cosmos The starter for using Spring Data for Azure Cosmos DB.

The following table lists starters for Spring Integration support:

Name Description
spring-cloud-azure-starter-integration-eventhubs The starter for using Azure Event Hubs and Spring Integration.
spring-cloud-azure-starter-integration-servicebus The starter for using Azure Service Bus and Spring Integration.
spring-cloud-azure-starter-integration-storage-queue The starter for using Azure Storage Queue and Spring Integration.

The following table lists starters for Spring Cloud Stream support:

Name Description
spring-cloud-azure-starter-stream-eventhubs The starters for using Azure Event Hubs and Spring Cloud Stream Binder.
spring-cloud-azure-starter-stream-servicebus The starter for using Azure Service Bus and Spring Cloud Stream Binder.

The following table lists starters for MySQL support:

Name Description
spring-cloud-azure-starter-jdbc-mysql The starters for using Azure MySQLs and JDBC through Azure AD authentication.

The following table lists starters for PostgreSQL support:

Name Description
spring-cloud-azure-starter-jdbc-postgresql The starters for using Azure PostgreSQL and JDBC through Azure AD authentication.

Learning Spring Cloud Azure

We've prepared a full list of samples to show usage. You can find these samples at Spring Cloud Azure Samples.

Spring Cloud Azure configuration

Configuration for each Azure Service SDK

Most of Azure Service SDKs can be divided into two categories by transport type: HTTP-based or AMQP-based. There are properties that are common to all SDKs, such as authentication principals and Azure environment settings, or common to HTTP-based clients, such as logging level to log HTTP requests and responses. In Spring Cloud Azure 4.0, we added five common categories of configuration properties that you can specify for each Azure service.

The following table lists properties common to multiple services:

Property Description
spring.cloud.azure.azure-service.client Configures the transport clients underneath one Azure service SDK.
spring.cloud.azure.azure-service.credential Configures authentication with Azure Active Directory for one Azure service SDK.
spring.cloud.azure.azure-service.profile Configures the Azure cloud environment for one Azure service SDK.
spring.cloud.azure.azure-service.proxy Configures the proxy options for one Azure service SDK.
spring.cloud.azure.azure-service.retry Configures the retry options applicable to one Azure service SDK. The retry options has supported part of the SDKs, there’s no spring.cloud.azure.cosmos.retry.

The configuration properties' prefixes have been unified to the spring.cloud.azure namespace since Spring Cloud Azure 4.0 to make configuration properties more consistent and more intuitive. The following table provides a quick review of the prefixes for supported Azure services:

Azure service Configuration property prefix Configuration Properties Link
Azure App Configuration spring.cloud.azure.appconfiguration App Configuration configuration properties
Azure Cosmos DB spring.cloud.azure.cosmos Azure Cosmos DB configuration properties
Azure Event Hubs spring.cloud.azure.eventhubs Event Hubs configuration properties
Azure Key Vault Certificate spring.cloud.azure.keyvault.certificate Key Vault Certificates configuration properties
Azure Key Vault Secret spring.cloud.azure.keyvault.secret Key Vault Secrets configuration properties
Azure Service Bus spring.cloud.azure.servicebus Service Bus configuration properties
Azure Storage Blob spring.cloud.azure.storage.blob Storage Blob configuration properties
Azure Storage File Share spring.cloud.azure.storage.fileshare Storage File Share configuration properties
Azure Storage Queue spring.cloud.azure.storage.queue Storage Queue configuration properties

Global configuration for Azure Service SDKs

There are some properties that you can share among different Azure services, for example to use the same service principal to access Azure Cosmos DB and Azure Event Hubs. Spring Cloud Azure 4.0 enables you to define properties that apply to all Azure SDKs in the namespace spring.cloud.azure.

The following table lists global properties:

Property Description
spring.cloud.azure.client Configures the transport clients; applies to all Azure SDKs by default.
spring.cloud.azure.credential Configures authentication with Azure Active Directory for all Azure SDKs by default.
spring.cloud.azure.profile Configures the Azure cloud environment for all Azure SDKs by default.
spring.cloud.azure.proxy Configures the proxy options applicable to all Azure SDK clients by default.
spring.cloud.azure.retry Configures the retry options applicable to all Azure SDK clients by default.

Note

Properties configured under each Azure service will override the global configurations.

Configuration examples

Global retry configuration for Azure Service SDKs

The following example shows you how to configure the retry behavior for any HTTP or AMQP protocol based Azure SDK client:

spring.cloud.azure:
  retry:
    mode: exponential
    exponential:
      max-retries: 4
      base-delay: PT0.0801S
      max-delay: PT9S

Retry configuration for Key Vault property source

The following configuration example shows you how to configure the retry behavior for the Azure Key Vault Secret client:

spring.cloud.azure:
  keyvault:
    secret:
      property-source-enabled: true
      property-sources:
        - endpoint: <your-Azure-Key-Vault-endpoint>
          retry:
            mode: exponential
            exponential:
              max-retries: 4
              base-delay: PT0.0801S
              max-delay: PT9S

Spring Cloud Azure authentication

DefaultAzureCredential

The DefaultAzureCredential is appropriate for most scenarios where the application is intended to be run in the Azure Cloud. This is because the DefaultAzureCredential combines credentials commonly used to authenticate when deployed with credentials used to authenticate in a development environment.

Note

DefaultAzureCredential is intended to simplify getting started with the SDK by handling common scenarios with reasonable default behaviors. If you want more control or your scenario isn't served by the default settings, you should use other credential types.

The DefaultAzureCredential will attempt to authenticate via the following mechanisms in order:

Diagram showing the authentication mechanism for `DefaultAzureCredential`.

  • Environment - The DefaultAzureCredential will read account information specified via environment variables and use it to authenticate.
  • Managed Identity - If the application is deployed to an Azure host with Managed Identity enabled, the DefaultAzureCredential will authenticate with that account.
  • IntelliJ - If you've authenticated via Azure Toolkit for IntelliJ, the DefaultAzureCredential will authenticate with that account.
  • Visual Studio Code - If you've authenticated via the Visual Studio Code Azure Account plugin, the DefaultAzureCredential will authenticate with that account.
  • Azure CLI - If you've authenticated an account via the Azure CLI az login command, the DefaultAzureCredential will authenticate with that account.

Tip

Be sure the security principal has been granted sufficient permission to access the Azure resource. For more information, see Authorize access with Azure Active Directory.

Note

Since Spring Cloud Azure AutoConfigure 4.1.0, a ThreadPoolTaskExecutor bean named springCloudAzureCredentialTaskExecutor will be automatically registered by default and will manage all threads created by Azure Identity. The name of each thread managed by this thread pool is prefixed with az-identity-. This ThreadPoolTaskExecutor bean is independent of the Executor bean provided by Spring Boot.

Managed identities

A common challenge is the management of secrets and credentials used to secure communication between different components making up a solution. Managed identities eliminate the need to manage credentials. Managed identities provide an identity for applications to use when connecting to resources that support Azure Active Directory (Azure AD) authentication. Applications may use the managed identity to obtain Azure AD tokens. For example, an application may use a managed identity to access resources like Azure Key Vault where you can store credentials in a secure manner or to access storage accounts.

We encourage using managed identity instead of using connection string or key in your application because it's more secure and will save the trouble of managing secrets and credentials. In this case, DefaultAzureCredential could better serve the scenario of developing locally using account information stored locally, then deploying the application to Azure Cloud and using managed identity.

Managed identity types

There are two types of managed identities:

  • System-assigned - Some Azure services allow you to enable a managed identity directly on a service instance. When you enable a system-assigned managed identity, an identity is created in Azure AD that's tied to the lifecycle of that service instance. So when the resource is deleted, Azure automatically deletes the identity for you. By design, only that Azure resource can use this identity to request tokens from Azure AD.
  • User-assigned - You may also create a managed identity as a standalone Azure resource. You can create a user-assigned managed identity and assign it to one or more instances of an Azure service. With user-assigned managed identities, the identity is managed separately from the resources that use it.

Note

When using a user-assigned managed identity, you can specify the client ID via spring.cloud.azure.credential.managed-identity-client-id or spring.cloud.azure.<azure-service>.credential.managed-identity-client-id. You don't need credential configuration if you use a system-assigned managed identity.

Tip

Be sure the security principal has been granted sufficient permission to access the Azure resource. For more information, see Authorize access with Azure Active Directory.

For more information about managed identity, see What are managed identities for Azure resources?.

Other credential types

If you want more control, or your scenario isn't served by the DefaultAzureCredential or the default settings, you should use other credential types.

Authentication and authorization with Azure Active Directory

With Azure AD, you can use Azure role-based access control (Azure RBAC) to grant permissions to a security principal, which may be a user or an application service principal. When a security principal (a user or an application) attempts to access an Azure resource, for example an Event Hubs resource, the request must be authorized. With Azure AD, access to a resource is a two-step process:

  1. First, the security principal's identity is authenticated, and an OAuth 2.0 token is returned.
  2. Next, the token is passed as part of a request to the Azure service to authorize access to the specified resource.
Authenticate with Azure Active Directory

To connect applications to resources that support Azure Active Directory (Azure AD) authentication, you can set the following configurations with the prefix spring.cloud.azure.credential or spring.cloud.azure.<azure-service>.credential

The following table lists authentication properties:

Property Description
client-id The client ID to use when performing service principal authentication with Azure.
client-secret The client secret to use when performing service principal authentication with Azure.
client-certificate-path Path of a PEM certificate file to use when performing service principal authentication with Azure.
client-certificate-password The password of the certificate file.
username The username to use when performing username/password authentication with Azure.
password The password to use when performing username/password authentication with Azure.
managed-identity-enabled Whether to enable managed identity.

Tip

For the list of all Spring Cloud Azure configuration properties, see Spring Cloud Azure configuration properties.

The application will look in several places to find an available credential, and will use DefaultAzureCredential if no credential properties are configured. If you want to use specific credential, see the following examples for guidance.

The following example shows you how to authenticate using a system-assigned managed identity:

spring.cloud.azure:
  credential:
    managed-identity-enabled: true

The following example shows you how to authenticate using a user-assigned managed identity:

spring.cloud.azure:
  credential:
    managed-identity-enabled: true
    client-id: ${AZURE_CLIENT_ID}

The following example shows you how to authenticate using a service principal with a client secret:

spring.cloud.azure:
  credential:
    client-id: ${AZURE_CLIENT_ID}
    client-secret: ${AZURE_CLIENT_SECRET}
  profile:
    tenant-id: ${AZURE_TENANT_ID}

The following example shows you how to authenticate using a service principal with a client PFX certificate:

spring.cloud.azure:
  credential:
    client-id: ${AZURE_CLIENT_ID}
    client-certificate-path: ${AZURE_CLIENT_CERTIFICATE_PATH}
    client-certificate-password: ${AZURE_CLIENT_CERTIFICATE_PASSWORD}
  profile:
    tenant-id: ${AZURE_TENANT_ID}

The following example shows you how to authenticate using a service principal with client PEM certificate:

spring.cloud.azure:
  credential:
    client-id: ${AZURE_CLIENT_ID}
    client-certificate-path: ${AZURE_CLIENT_CERTIFICATE_PATH}
  profile:
    tenant-id: ${AZURE_TENANT_ID}

The following example shows you how to authenticate using a user credential:

spring.cloud.azure:
  credential:
    client-id: ${AZURE_CLIENT_ID}
    username: ${AZURE_USER_USERNAME}
    password: ${AZURE_USER_PASSWORD}

The following example shows you how to authenticate with Key Vault using a different service principal. This example configures the application with two credentials: one system-assigned managed identity and one service principal. The Key Vault Secret client will use the service principal, but any other components will use managed identity instead.

spring.cloud.azure:
  credential:
    managed-identity-enabled: true
  keyvault.secret:
    credential:
      client-id: ${AZURE_CLIENT_ID}
      client-secret: ${AZURE_CLIENT_SECRET}
    profile:
      tenant-id: ${AZURE_TENANT_ID}
Authorize access with Azure Active Directory

The authorization step requires that one or more Azure roles be assigned to the security principal. The roles that are assigned to a security principal determine the permissions that the principal will have.

Tip

For the list of all Azure built-in roles, see Azure built-in roles.

The following table lists the Azure built-in roles for authorizing access to Azure services supported in Spring Cloud Azure:

Role Description
App Configuration Data Owner Allows full access to App Configuration data.
App Configuration Data Reader Allows read access to App Configuration data.
Azure Event Hubs Data Owner Allows full access to Azure Event Hubs resources.
Azure Event Hubs Data Receiver Allows receive access to Azure Event Hubs resources.
Azure Event Hubs Data Sender Allows send access to Azure Event Hubs resources.
Azure Service Bus Data Owner Allows full access to Azure Service Bus resources.
Azure Service Bus Data Receiver Allows receive access to Azure Service Bus resources.
Azure Service Bus Data Sender Allows send access to Azure Service Bus resources.
Storage Blob Data Owner Provides full access to Azure Storage blob containers and data, including assigning POSIX access control.
Storage Blob Data Reader Read and list Azure Storage containers and blobs.
Storage Queue Data Reader Read and list Azure Storage queues and queue messages.
Redis Cache Contributor Manage Redis caches.

Note

When using Spring Cloud Azure Resource Manager to get the connection strings for Event Hubs, Service Bus, and Storage Queue, or the properties of Cache for Redis, assign the Azure built-in role Contributor. Azure Cache for Redis is special, and you can also assign the Redis Cache Contributor role to get the Redis properties.

Note

A Key Vault access policy determines whether a given security principal, namely a user, application or user group, can perform different operations on Key Vault secrets, keys, and certificates. You can assign access policies using the Azure portal, the Azure CLI, or Azure PowerShell. For more information, see Assign a Key Vault access policy.

Important

Azure Cosmos DB exposes two built-in role definitions: Cosmos DB Built-in Data Reader and Cosmos DB Built-in Data Contributor. However, Azure portal support for role management isn't available yet. For more information about the permission model, role definitions, and role assignment, see Configure role-based access control with Azure Active Directory for your Azure Cosmos DB account.

SAS tokens

You can also configure services for authentication with Shared Access Signature (SAS). spring.cloud.azure.<azure-service>.sas-token is the property to configure. For example, use spring.cloud.azure.storage.blob.sas-token to authenticate to Storage Blob service.

Connection strings

Connection string is supported by some Azure services to provide connection information and credentials. To connect to those Azure services using connection string, just configure spring.cloud.azure.<azure-service>.connection-string. For example, configure spring.cloud.azure.eventhubs.connection-string to connect to the Event Hubs service.

Production ready

We’ve added health indicators for App Configuration, Event Hubs, Azure Cosmos DB, Key Vault, Storage Blob, Storage Queue, and Storage File, as well as Spring Cloud Sleuth support for all HTTP-based Azure SDKs. As an example, you now can probe to determine whether a storage blob is up or down via Spring Boot actuator endpoint, as well as track dependencies and latencies going from your application to Key Vault.

Enable health indicator

To enable the health indicators, add the Spring Cloud Azure Actuator Starter dependency to your pom.xml file. This dependency will also include the spring-boot-starter-actuator.

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-actuator</artifactId>
</dependency>

The following table lists configurable properties to enable or disable health indicators for each Azure service:

Azure Service Property
App Configuration management.health.azure-appconfiguration.enabled
Azure Cosmos DB management.health.azure-cosmos.enabled
Event Hubs management.health.azure-eventhubs.enabled
Key Vault Certificate management.health.azure-keyvault-certificate.enabled
Key Vault Secret management.health.azure-keyvault-secret.enabled
Storage Blob management.health.azure-storage-blob.enabled
Storage File Share management.health.azure-storage-fileshare.enabled
Storage Queue management.health.azure-storage-queue.enabled

Important

Calling the health endpoint of Azure services may cause extra charges. For example, if you call http://HOST_NAME:{port}/actuator/health/cosmos to get Azure Cosmos DB health info, it will calculate Request Units (RUs). For more information, see Request Units in Azure Cosmos DB.

Note

For calling the health endpoint of Cosmos, the option spring.cloud.azure.cosmos.database should be configured; Otherwise, the health status of unknown will be returned.

For calling the health endpoint of Storage Queue, role of Storage Account Contributor is required if Azure AD is used for authorizing.

Enable sleuth

When you want to trace Azure SDK activities by using Spring Cloud Sleuth, add the following Spring Cloud Azure Trace Sleuth dependency to your pom.xml file:

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-trace-sleuth</artifactId>
</dependency>

Note

Only HTTP-based Azure SDK clients are currently supported. For example, Event Hubs and Service Bus with AMQP transport are currently not supported. For these requirements, we recommend that you use Azure Application Insight.

Auto-configure Azure SDK clients

Spring Boot simplifies the Spring Cloud Azure development experience. Spring Cloud Azure starters are a set of convenient dependency descriptors to include in your application. The starters handle the object instantiation and configuration logic, so you don’t have to. Every starter depends on spring-cloud-azure-starter to provide critical bits of configuration, like the Azure cloud environment and authentication information. You can configure these as properties in, for example, a YAML file, as shown in the following example:

spring:
  cloud:
    azure:
      profile:
        tenant-id: ${AZURE_TENANT_ID}
        cloud-type: Azure
      credential:
        client-id: ${AZURE_CLIENT_ID}

Note

The cloud property is optional.

These properties are optional and, if not specified, Spring Boot will try to automatically find them for you. For details on how Spring Boot finds these properties, refer to the documentation.

Dependency setup

There are two ways to use Spring Cloud Azure starters. The first way is to use Azure SDKs with the spring-cloud-azure-starter dependency as shown in the following example:

<dependency>
  <groupId>com.azure</groupId>
  <artifactId>azure-cosmos</artifactId>
</dependency>
<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter</artifactId>
</dependency>

The second way is to avoid adding Azure SDK dependencies and instead include the Spring Cloud Azure Starter for each Service directly. For example, with Azure Cosmos DB, you would add the following dependency:

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-cosmos</artifactId>
</dependency>

Tip

For the list of supported starters, see Starter dependencies.

Configuration

Note

If you use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, be sure the security principal has been granted sufficient permission to access the Azure resource. For more information, see Authorize access with Azure Active Directory.

Configuration properties for each Azure service are under prefix spring.cloud.azure.<azure-service>.

Tip

For the list of all Spring Cloud Azure configuration properties, see Spring Cloud Azure configuration properties.

Basic usage

Adding the following properties to your application.yaml file will autoconfigure the Azure Cosmos DB client for you.

spring:
  cloud:
    azure:
      cosmos:
        database: ${AZURE_COSMOS_DATABASE_NAME}
        endpoint: ${AZURE_COSMOS_ENDPOINT}
        consistency-level: eventual
        connection-mode: direct

Then, both CosmosClient and CosmosAsyncClient are available in the context and can be autowired, as shown in the following example:

class Demo {
@Autowired
private CosmosClient cosmosClient;

    @Override
    public void run() {
        User item = User.randomUser();
        CosmosContainer container = cosmosClient.getDatabase(databaseName).getContainer(containerName);
        container.createItem(item);
    }
}

Samples

See the azure-spring-boot-samples on GitHub.

Resource handing

The Spring project provides a Spring Resources abstraction to access a number of low-level resources. The project provides interfaces like Resource, ResourceLoader and ResourcePatternResolver. Spring Cloud Azure implements these interfaces for Azure Storage services, which allows you to interact with Azure storage Blob and File Share using the Spring programming model. Spring Cloud Azure provides spring-cloud-azure-starter-storage-blob and spring-cloud-azure-starter-storage-file-share to auto-configure Azure Storage Blob and Azure Storage File Share.

The following table lists Azure Storage related libraries:

Starter Service Description
spring-cloud-azure-starter-storage-blob Azure Storage Blob Allows unstructured data to be stored and accessed at a massive scale in block blobs.
spring-cloud-azure-starter-storage-file-share Azure Storage File Share Offers fully managed cloud file shares that you can access from anywhere via the industry standard Server Message Block (SMB) protocol.

Dependency setup

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-storage-blob</artifactId>
    </dependency>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-storage-file-share</artifactId>
    </dependency>
</dependencies>

The spring-cloud-azure-starter-storage-blob dependency is only required when you're using Azure Storage Blob.

The spring-cloud-azure-starter-storage-file-share dependency is only required when you're using Azure Storage File Share.

Tip

We also provide spring-cloud-azure-starter-storage to support all the features of Storage. If you choose to use it, spring.cloud.azure.storage.enable is the property to configure and the default value is true. You can then use spring.cloud.azure.storage.<storage-service>.enable to disable unneeded services.

Configuration

Note

If you use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, be sure the security principal has been granted sufficient permission to access the Azure resource. For more information, see Authorize access with Azure Active Directory.

The following table lists the configurable properties of spring-cloud-azure-starter-storage-blob:

Property Default Description
spring.cloud.azure.storage.blob.enabled true A value that indicates whether an Azure Blob Storage service is enabled.
spring.cloud.azure.storage.blob.endpoint The URI to connect to Azure Blob Storage.
spring.cloud.azure.storage.blob.account-key The private key to connect to Azure Blob Storage.
spring.cloud.azure.storage.blob.account-name The Azure Storage Blob account name.

The following table lists the configurable properties of spring-cloud-azure-starter-storage-file-share:

Property Default Description
spring.cloud.azure.storage.fileshare.enabled true A value that indicates whether Azure File Storage service is enabled.
spring.cloud.azure.storage.fileshare.endpoint The URI to connect to Azure File Storage.
spring.cloud.azure.storage.fileshare.account-key The private key to connect to Azure File Storage.
spring.cloud.azure.storage.fileshare.account-name The Azure Storage File Share account name.

Basic usage

Add the following properties to your application.yml file:

spring:
  cloud:
    azure:
      storage:
        blob:
          account-name: ${STORAGE_ACCOUNT_NAME}
          account-key: ${STORAGE_ACCOUNT_KEY}
          endpoint: ${STORAGE_BLOB_ENDPOINT}
        fileshare:
          account-name: ${STORAGE_ACCOUNT_NAME}
          account-key: ${STORAGE_ACCOUNT_KEY}
          endpoint:  ${STORAGE_FILESHARE_ENDPOINT}

Get a resource

Get a resource with @Value

You can use the annotation of @Value("azure-blob://[your-container-name]/[your-blob-name]") to autowire a blob resource, as shown in the following example:

@Value("azure-blob://[your-container-name]/[your-blob-name]")
private Resource storageBlobResource;

You can use the annotation of @Value("azure-file://[your-fileshare-name]/[your-file-name]") to autowire a file resource, as shown in the following example:

@Value("azure-file://[your-fileshare-name]/[your-file-name]")
private Resource storageFileResource;
Get a resource with ResourceLoader
@Autowired
private ResourceLoader resourceLoader;
...
// Get a BlobResource.
Resource storageBlobResource = resourceLoader.getResource("azure-blob://[your-container-name]/[your-blob-name]");

// Get a FileResource.
Resource storageFileResource = resourceLoader.getResource("azure-file://[your-fileshare-name]/[your-file-name]");
Get resources by searching pattern

You can use an implementation class of ResourcePatternResolver to search resources. Use AzureStorageBlobProtocolResolver to search blob resources and AzureStorageFileProtocolResolver to search file resources.

  • For pattern search, the searchPattern should start with azure-blob:// or azure-file://. For example, azure-blob://**/** means to list all blobs in all containers, and azure-blob://demo-container/** means to list all blobs in the demo-container container, including any sub-folder.

  • For location search, the searchLocation should start with azure-blob:// or azure-file:// and the remaining file path should exist, otherwise an exception will be thrown.

@Autowired
private AzureStorageBlobProtocolResolver azureStorageBlobProtocolResolver;

@Autowired
private AzureStorageFileProtocolResolver azureStorageFileProtocolResolver;

// Get all text blobs.
Resource[] blobTextResources = azureStorageBlobProtocolResolver.getResources("azure-blob://[container-pattern]/*.txt");

// Get all text files.
Resource[] fileTextResources = azureStorageFileProtocolResolver.getResources("azure-file://[fileshare-pattern]/*.txt");

Handling with resource

Download data from specific resource

You can download a resource from Azure Storage Blob or File Share with the getInputStream() method of Resource.

@Value("azure-blob://[your-container-name]/[your-blob-name]")
private Resource storageBlobResource;

@Value("azure-file://[your-fileshare-name]/[your-file-name]")
private Resource storageFileResource;

//...

// Download data as a stream from a blob resource.
InputStream inputblobStream = storageBlobResource.getInputStream();

// Download data as a stream from a file resource.
InputStream inputfileStream = storageFileResource.getInputStream();
Upload data to specific resource

You can upload to a resource to Azure Blob or file storage by casting the Spring Resource to WritableResource, as shown in the following example:

@Value("azure-blob://[your-container-name]/[your-blob-name]")
private Resource storageBlobResource;

@Value("azure-file://[your-fileshare-name]/[your-file-name]")
private Resource storageFileResource;

String data = "sampledata";

// Upload string data to a blob.
try (OutputStream blobos = ((WritableResource) this.storageBlobResource).getOutputStream()) {
    blobos.write(data.getBytes());
}

// Upload string data to a file.
try (OutputStream fileos = ((WritableResource) this.storageFileResource).getOutputStream()) {
    fileos.write(data.getBytes());
}

Multipart upload

Files larger than 4 MiB will be uploaded to Azure Storage in parallel.

Samples

See the storage-blob-sample and storage-file-sample on GitHub.

Secret management

Spring Cloud Azure construct PropertySource which holds secrets stored in Azure Key Vault Secrets.

Dependency setup

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-keyvault-secrets</artifactId>
</dependency>

Tip

We also provide spring-cloud-azure-starter-keyvault to support all the features of Key Vault. If you choose to use it, spring.cloud.azure.keyvault.enable is the property to configure and the default value is true. You can then use spring.cloud.azure.keyvault.<keyvault-service>.enable to disable unneeded services.

Basic usage

If you want to authenticate by client-id and client-secret, the following properties are required:

Configuration Properties

spring:
  cloud:
    azure:
      keyvault:
        secret:
          property-sources:
            - name: key-vault-property-souece-1
              endpoint: ${ENDPOINT_1}
            - name: key-vault-property-souece-2
              endpoint: ${ENDPOINT_2}

Java code

@SpringBootApplication
public class SampleApplication implements CommandLineRunner {

    @Value("${sampleProperty1}")
    private String sampleProperty1;
    @Value("${sampleProperty2}")
    private String sampleProperty2;
    @Value("${samplePropertyInMultipleKeyVault}")
    private String samplePropertyInMultipleKeyVault;

    public static void main(String[] args) {
        SpringApplication.run(SampleApplication.class, args);
    }

    public void run(String[] args) {
        System.out.println("sampleProperty1: " + sampleProperty1);
        System.out.println("sampleProperty2: " + sampleProperty2);
        System.out.println("samplePropertyInMultipleKeyVault: " + samplePropertyInMultipleKeyVault);
    }
}

Advanced usage

Special characters in property name

Key Vault secret names support only characters in [0-9a-zA-Z-]. For more information, see theVault-name and Object-name section of Azure Key Vault keys, secrets and certificates overview. If your property name contains other characters, you can use the workarounds described in the following sections.

Use - instead of . in secret names

. isn't supported in secret names. If your application has a property name that contains ., such as spring.datasource.url, replace . with - when saving the secret in Azure Key Vault. For example, save spring-datasource-url in Azure Key Vault. In your application, you can still use spring.datasource.url to retrieve the property value.

Note

This method cannot satisfy a requirement like spring.datasource-url. When you save spring-datasource-url in Key Vault, only spring.datasource.url and spring-datasource-url is supported to retrieve the property value, but spring.datasource-url isn't supported. To handle this case, see the Use property placeholders section.

Use property placeholders

For example, suppose you're setting this property in your application.properties file:

property.with.special.character__=${propertyWithoutSpecialCharacter}

The application will get a propertyWithoutSpecialCharacter key name and assign its value to property.with.special.character__.

Case-sensitive

To enable case-sensitive mode, you can set the following property:

spring.cloud.azure.keyvault.secret.property-sources[].case-sensitive=true

Not retrieve all secrets in Key Vault

If you stored 1000 secrets in the Key Vault, and you just want to use 3 of them. You can list the 3 secret names by spring.cloud.azure.keyvault.secret.property-sources[].secret-keys.

Setting refresh interval

By default, the secrets in KeyVaultPropertySource will refresh every 30 minutes. You can configure the time by spring.cloud.azure.keyvault.secret.property-sources[].refresh-interval. For example: spring.cloud.azure.keyvault.secret.property-sources[].refresh-interval=60m means refresh every 60 minutes. Set to 0 to disable auto refresh.

PropertySource priority

If key exists in multiple PropertySources, which will take effect is decided by the priority.

  • If there is no SystemEnvironmentPropertySource in PropertySource list, then KeyVaultPropertySource will take the highest priority.
  • If there is SystemEnvironmentPropertySource in PropertySource list, then SystemEnvironmentPropertySource have higher priority than KeyVaultPropertySource. Which means you can use environment variable to override the Key Vault secret value in your application.
  • If there are multiple KeyVaultPropertySource in PropertySource list, then the definition order is the priority order. Take above sample as example, key-vault-property-souece-1 has higher priority than key-vault-property-souece-2.

All configurable properties

Property Default value Description
spring.cloud.azure.keyvault.secret.property-source-enabled true Whether to enable the Key Vault property source.
spring.cloud.azure.keyvault.secret.property-sources[].name Name of this property source.
spring.cloud.azure.keyvault.secret.property-sources[].endpoint Azure Key Vault endpoint.
spring.cloud.azure.keyvault.secret.property-sources[].case-sensitive false Whether the secret keys are case-sensitive.
spring.cloud.azure.keyvault.secret.property-sources[].secret-keys The secret keys supported for this property source. All keys be retrieved if this property is missing.
spring.cloud.azure.keyvault.secret.property-sources[].refresh-interval 30m Time interval to refresh all Key Vault secrets.
spring.cloud.azure.keyvault.secret.property-sources[].service-version Secret service version used when making API requests.
spring.cloud.azure.keyvault.secret.property-sources[].client Client related properties.
spring.cloud.azure.keyvault.secret.property-sources[].credential Credential related properties.
spring.cloud.azure.keyvault.secret.property-sources[].profile Profile related properties.
spring.cloud.azure.keyvault.secret.property-sources[].proxy Proxy related properties.
spring.cloud.azure.keyvault.secret.property-sources[].retry Retry related properties.

Samples

See the spring-cloud-azure-starter-keyvault-secrets samples on GitHub.

Spring Data support

Spring Data Azure Cosmos DB support

Azure Cosmos DB is a globally distributed database service that allows developers to work with data using various standard APIs, such as SQL, MongoDB, Graph, and Azure Table storage.

Dependency setup

<dependency>
   <groupId>com.azure.spring</groupId>
   <artifactId>spring-cloud-azure-starter-data-cosmos</artifactId>
</dependency>

Configuration

Note

If you use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, be sure the security principal has been granted sufficient permission to access the Azure resource. For more information, see Authorize access with Azure Active Directory.

The following table lists the configurable properties of spring-cloud-azure-starter-data-cosmos:

Property Description
spring.cloud.azure.cosmos.enabled A value that indicates whether Azure Cosmos DB Service is enabled. The default value is true.
spring.cloud.azure.cosmos.database The Azure Cosmos DB database ID.
spring.cloud.azure.cosmos.endpoint The URI to connect Azure Cosmos DB.
spring.cloud.azure.cosmos.key The PrivateKey to connect Azure Cosmos DB.
spring.cloud.azure.cosmos.credential.client-certificate-password The password of the certificate file.
spring.cloud.azure.cosmos.credential.client-certificate-path The path of a PEM certificate file to use when performing service principal authentication with Azure.
spring.cloud.azure.cosmos.credential.client-id The client ID to use when performing service principal authentication with Azure.
spring.cloud.azure.cosmos.credential.client-secret The client secret to use when performing service principal authentication with Azure.
spring.cloud.azure.cosmos.credential.managed-identity-enabled Whether to enable managed identity. The default value is false.
spring.cloud.azure.cosmos.credential.password The password to use when performing username/password authentication with Azure.
spring.cloud.azure.cosmos.credential.username The username to use when performing username/password authentication with Azure.
spring.cloud.azure.cosmos.populate-query-metrics A value that indicates whether to populate diagnostics strings and query metrics. The default value is false.
spring.cloud.azure.cosmos.consistency-level A consistency level for Azure Cosmos DB.

Key concepts

The following list shows the key concepts of the Spring Data support:

  • The Spring Data CrudRepository and ReactiveCrudRepository, which provide the following basic CRUD functionality:

    • save
    • findAll
    • findOne by ID
    • deleteAll
    • delete by ID
    • delete entity
  • The Spring Data @Id annotation. There are two ways to map a field in a domain class to the id of an Azure Cosmos DB document:

    • Annotate a field in domain class with @Id. This field will be mapped to document id in Azure Cosmos DB.
    • Set the name of this field to id. This field will be mapped to document id in Azure Cosmos DB.

    Note

    If both ways are applied, the @Id annotation has higher priority.

  • Custom collection names. By default, collection name will be class name of user domain class. To customize it, add annotation @Document(collection="myCustomCollectionName") to your domain class, that's all.

  • Supports Azure Cosmos DB partition. To specify a field of your domain class to be a partition key field, annotate it with @PartitionKey. When you do CRUD operations, specify your partition value. For more examples, see AddressRepositoryIT.java on GitHub.

  • Supports Spring Data custom query find operation.

  • Supports spring-boot-starter-data-rest.

  • Supports List and nested types in domain classes.

Basic usage

Use a private key to access Azure Cosmos DB

The simplest way to connect Azure Cosmos DB with spring-cloud-azure-starter-data-cosmos is with a primary key. Add the following properties:

spring:
  cloud:
    azure:
      cosmos:
        key: ${AZURE_COSMOS_KEY}
        endpoint: ${AZURE_COSMOS_ENDPOINT}
        database: ${AZURE_COSMOS_DATABASE}
Define an entity

Define an entity as a Document in Azure Cosmos DB, as shown in the following example:

@Container(containerName = "mycollection")
public class User {
    @Id
    private String id;
    private String firstName;
    @PartitionKey
    private String lastName;
    private String address;

    public User() {
    }

    public User(String id, String firstName, String lastName, String address) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.address = address;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return String.format("%s %s, %s", firstName, lastName, address);
    }
}

The id field will be used as the document id in Azure Cosmos DB. Alternately, you can annotate any field with @Id to map it to the document id.

The annotation @Container(containerName = "mycollection") is used to specify the collection name of your document in Azure Cosmos DB.

Create repositories

To create repositories, extend the ReactiveCosmosRepository interface, which provides Spring Data repository support.

@Repository
public interface UserRepository extends ReactiveCosmosRepository<User, String> {
    Flux<User> findByFirstName(String firstName);
}

Currently, the ReactiveCosmosRepository interface provides basic save, delete, and find operations. More operations will be supported later.

Create an application class

The following example creates an application class with all the components:

@SpringBootApplication
public class CosmosSampleApplication implements CommandLineRunner {

private static final Logger LOGGER = LoggerFactory.getLogger(CosmosSampleApplication.class);

    @Autowired
    private UserRepository repository;

    @Autowired
    private CosmosProperties properties;

    public static void main(String[] args) {
        SpringApplication.run(CosmosSampleApplication.class, args);
    }

    public void run(String... var1) {
        final User testUser = new User("testId", "testFirstName",
                "testLastName", "test address line one");

        // Save the User class to Azure Cosmos DB database.
        final Mono<User> saveUserMono = repository.save(testUser);

        final Flux<User> firstNameUserFlux = repository.findByFirstName("testFirstName");

        //  Nothing happens until we subscribe to these Monos.
        //  findById will not return the user as user isn't present.
        final Mono<User> findByIdMono = repository.findById(testUser.getId());
        final User findByIdUser = findByIdMono.block();
        Assert.isNull(findByIdUser, "User must be null");

        final User savedUser = saveUserMono.block();
        Assert.state(savedUser != null, "Saved user must not be null");
        Assert.state(savedUser.getFirstName().equals(testUser.getFirstName()),
                "Saved user first name doesn't match");

        firstNameUserFlux.collectList().block();

        final Optional<User> optionalUserResult = repository.findById(testUser.getId()).blockOptional();
        Assert.isTrue(optionalUserResult.isPresent(), "Cannot find user.");

        final User result = optionalUserResult.get();
        Assert.state(result.getFirstName().equals(testUser.getFirstName()),
                "query result firstName doesn't match!");
        Assert.state(result.getLastName().equals(testUser.getLastName()),
                "query result lastName doesn't match!");
        LOGGER.info("findOne in User collection get result: {}", result.toString());

    }

    @PostConstruct
    public void setup() {
        // For this example, remove all of the existing records.
        this.repository.deleteAll().block();
    }
}

This example includes an autowired UserRepository interface to support save, delete, and find operations.

Samples

See the azure-spring-boot-samples on GitHub.

Apart from using the spring-cloud-azure-starter-data-cosmos library, you can directly use azure-spring-data-cosmos library for more complex scenarios. For more information, see Spring Data for Azure Cosmos DB client library.

Spring Security support

Spring Security with Azure Active Directory

When you're building a web application, identity and access management will always be foundational pieces.

Azure offers a great platform to democratize your application development journey, as it not only offers a cloud-base identity service, but also deep integration with the rest of the Azure ecosystem.

Spring Security has made it easy to secure your Spring based applications with powerful abstractions and extensible interfaces. However, as powerful as the Spring framework can be, it is not tailored to a specific identity provider.

The spring-cloud-azure-starter-active-directory provides the most optimal way to connect your web application to an Azure Active Directory (Azure AD for short) tenant and protect your resource server with Azure AD. It uses the Oauth 2.0 protocol to protect web applications and resource servers.

Accessing a web application

This scenario uses The OAuth 2.0 authorization code grant flow to log in a user with a Microsoft account.

System Diagram

System diagram for a standalone web application.

Create required resources in Azure
  1. Read MS docs about register an application with the Microsoft identity platform.

  2. Create app registration. Get AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET.

  3. Set redirect URI to APPLICATION_BASE_URI/login/oauth2/code/, for example http://localhost:8080/login/oauth2/code/. The tailing / is required.

Add required dependencies
<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
</dependencies>
Add required properties
spring:
  cloud:
    azure:
      active-directory:
        profile:
          tenant-id: ${AZURE_TENANT_ID}
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}

Now start you application and access your application by browser, then you will be redirected into Microsoft login page.

Advanced usages
Add extra security configurations
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class AadOAuth2LoginSecurityConfig extends AadWebSecurityConfigurerAdapter {

        /**
         * Add configuration logic as needed.
         */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            super.configure(http);
            http.authorizeRequests()
                    .anyRequest().authenticated();
            // Do some custom configuration
        }
    }
Authorize access by app roles
  1. Create Required Resources in Azure

Note

If you want to use app role based access control, you can't put group names in role claim . Refs: [Configuring groups optional claims] (/azure/active-directory/develop/active-directory-optional-claims#configuring-groups-optional-claims).

  1. Protect specific method.

    class Demo {
        @GetMapping("Admin")
        @ResponseBody
        @PreAuthorize("hasAuthority('APPROLE_Admin')")
        public String admin() {
            return "Admin message";
        }
    }
Authorize access by group name or group Id
  1. Add related configuration properties.

        spring:
          cloud:
            azure:
              active-directory:
                user-group:
                  allowed-group-names: group1_name_1, group2_name_2
                  # 1. If allowed-group-ids == all, then all group ID will take effect.
                  # 2. If "all" is used, we should not configure other group ids.
                  # 3. "all" is only supported for allowed-group-ids, not supported for allowed-group-names.
                  allowed-group-ids: group_id_1, group_id_2
    
  2. Protect specific method.

        @Controller
        public class RoleController {
            @GetMapping("group1")
            @ResponseBody
            @PreAuthorize("hasRole('ROLE_group1')")
            public String group1() {
                return "group1 message";
            }
    
            @GetMapping("group2")
            @ResponseBody
            @PreAuthorize("hasRole('ROLE_group2')")
            public String group2() {
                return "group2 message";
            }
    
            @GetMapping("group1Id")
            @ResponseBody
            @PreAuthorize("hasRole('ROLE_<group1-id>')")
            public String group1Id() {
                return "group1Id message";
            }
    
            @GetMapping("group2Id")
            @ResponseBody
            @PreAuthorize("hasRole('ROLE_<group2-id>')")
            public String group2Id() {
                return "group2Id message";
            }
        }
    
Use National Azure instead of Global Azure

Now except global Azure cloud, Azure Active Directory is deployed in the following national clouds:

  • Azure Government

  • Azure China 21Vianet

  • Azure Germany

Here is a sample of you want to use Azure China 21Vianet.

spring:
  cloud:
    azure:
      active-directory:
        base-uri: https://login.partner.microsoftonline.cn
        graph-base-uri: https://microsoftgraph.chinacloudapi.cn

You can refer to these MS doc to get more information from MS docs about National cloud deployments.

Configure redirect uri template

Developers can customize the redirect-uri.

System diagram for redirect URIs.

  1. Add redirect-uri-template properties in application.yml.

        spring:
          cloud:
            azure:
              active-directory:
                redirect-uri-template: ${REDIRECT-URI-TEMPLATE}
    
  2. Update redirect-uri in Azure portal.

    Configure Redirect URI Template.

  3. Update WebSecurityConfigurerAdapter

After we set redirect-uri-template, we need to update WebSecurityConfigurerAdapter:

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AadOAuth2LoginSecurityConfig extends AadWebSecurityConfigurerAdapter {
    /**
     * Add configuration logic as needed.
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.oauth2Login()
                .loginProcessingUrl("${REDIRECT-URI-TEMPLATE}")
                .and()
            .authorizeRequests()
                .anyRequest().authenticated();
    }
}
Connecting to Azure AD via proxy

To connect Azure AD via proxy, provide a RestTemplateCustomizer bean like the one shown in the following example:

@Configuration
class DemoConfiguration {
    @Bean
    public RestTemplateCustomizer proxyRestTemplateCustomizer() {
        return (RestTemplate restTemplate) -> {
            Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_SERVER_HOST, PROXY_SERVER_PORT));
            SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
            requestFactory.setProxy(proxy);
            restTemplate.setRequestFactory(requestFactory);
        };
    }
}
Samples

Sample project: aad-web-application.

Web application accessing resource servers

System Diagram

System diagram for a web application accessing resource servers.

Create Required Resources in Azure
  1. Read MS docs about register an application with the Microsoft identity platform.

  2. Create app registration. Get AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET.

  3. Set redirect URI to APPLICATION_BASE_URI/login/oauth2/code/, for example http://localhost:8080/login/oauth2/code/. The tailing / is required.

Add required dependencies
<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
</dependencies>
Add required properties
spring:
  cloud:
    azure:
      active-directory:
        profile:
          tenant-id: ${AZURE_TENANT_ID}
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        authorization-clients:
          graph:
            scopes: https://graph.microsoft.com/Analytics.Read, email

Here, graph is the name of OAuth2AuthorizedClient, scopes means the scopes need to consent when login.

Use OAuth2AuthorizedClient in your application
public class Demo {
    @GetMapping("/graph")
    @ResponseBody
    public String graph(
    @RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient graphClient) {
        // toJsonString() is just a demo.
        // oAuth2AuthorizedClient contains access_token. We can use this access_token to access resource server.
        return toJsonString(graphClient);
    }
}

Now start you application and access your application by browser, then you will be redirected into Microsoft login page.

Advanced usages
Client Credential Flow

The default flow is authorization code flow, if you want to use client credentials flow, you can configure like this:

spring:
  cloud:
    azure:
      active-directory:
        profile:
          tenant-id: ${AZURE_TENANT_ID}
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        authorization-clients:
          graph:
            authorization-grant-type: client_credentials # Change type to client_credentials
            scopes: https://graph.microsoft.com/Analytics.Read, email
Access multiple resource servers

In one web application, you can access multiple resource server by configuring like this:

spring:
  cloud:
    azure:
      active-directory:
        profile:
          tenant-id: ${AZURE_TENANT_ID}
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        authorization-clients:
          resource-server-1:
            scopes: # Scopes for resource-server-1
          resource-server-2:
            scopes: # Scopes for resource-server-2

Then you can use OAuth2AuthorizedClient in application like this

public class Demo {
    @GetMapping("/resource-server-1")
    @ResponseBody
    public String graph(
    @RegisteredOAuth2AuthorizedClient("resource-server-1") OAuth2AuthorizedClient client) {
        return callResourceServer1(client);
    }

    @GetMapping("/resource-server-2")
    @ResponseBody
    public String graph(
    @RegisteredOAuth2AuthorizedClient("resource-server-2") OAuth2AuthorizedClient client) {
        return callResourceServer2(client);
    }
}

In previous sample, all scopes will be consented when customer first login, no matter it's belong to resource-server-1 or resource-server-2. If you don't want to let customer consent all scopes, you can do like this:

spring:
  cloud:
    azure:
      active-directory:
        profile:
          tenant-id: ${AZURE_TENANT_ID}
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        authorization-clients:
          resource-server-1:
            scopes: # Scopes for resource-server-1
          resource-server-2:
            on-demand: true  # means incremental consent
            scopes: # Scopes for resource-server-2
Samples

Sample project: aad-web-application.

Accessing a resource server

This scenario doesn't support login, just protect the server by validating the access token. If the access token is valid, the server serves the request.

System Diagram

System diagram for standalone resource server usage.

Create required resources in Azure
  1. Read MS docs about register an application with the Microsoft identity platform.

  2. Create app registration. Get AZURE_CLIENT_ID.

  3. Read MS docs about configure an application to expose a web API.

  4. Expose a web API with a scope named Scope-1.

Add required dependencies
<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
    </dependency>
</dependencies>
Add required properties
spring:
  cloud:
    azure:
      active-directory:
        credential:
          client-id: ${AZURE_CLIENT_ID}

Now start your application and access your application's web api.

  1. You will get 401 without an access token.

  2. Access your application with an access token, the following claims in access token will be validated:

    • iss: The access token must be issued by Azure AD.

    • nbf: Current time can not before nbf.

    • exp: Current time can not after exp.

    • aud: If spring.cloud.azure.active-directory.credential.client-id or spring.cloud.azure.active-directory.credential.app-id-uri configured, the audience must equal to the configured client-id or app-id-uri. If the 2 properties are not configured, this claim will not be validated.

Refer to MS docs about Microsoft identity platform access tokens to get more information about access token.

Advanced usages
Add extra security configurations
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AadOAuth2ResourceServerSecurityConfig extends AadResourceServerWebSecurityConfigurerAdapter {
    /**
     * Add configuration logic as needed.
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.authorizeRequests((requests) -> requests.anyRequest().authenticated());
    }
}
Validate permission by scopes
  1. Create Required Resources in Azure

  2. Protect specific method.

    class Demo {
        @GetMapping("scope1")
        @ResponseBody
        @PreAuthorize("hasAuthority('SCOPE_Scope1')")
        public String scope1() {
            return "Congratulations, you can access `scope1` endpoint.";
        }
    }

By doing this, when access /scope1 endpoint, the following claims in access token will be validated:

  • scp: The value must contains Scope1.
Validate permission by app roles
  1. Create Required Resources in Azure

  2. Protect specific method.

    class Demo {
        @GetMapping("app-role1")
        @ResponseBody
        @PreAuthorize("hasAuthority('APPROLE_AppRole1')")
        public String appRole1() {
            return "Congratulations, you can access `app-role1` endpoint.";
        }
    }

By doing this, when access /app-role1 endpoint, the following claims in access token will be validated:

  • roles: The value must contains AppRole1.
Use JWT client authentication

To use a JSON Web Token (JWT) for client authentication, use the following steps:

  1. See the Register your certificate with Microsoft identity platform section of Microsoft identity platform application authentication certificate credentials.
  2. Upload a .pem certificate to the application registered in the Azure portal.
  3. Configure the certificate path and password of a .PFX or .P12 certificate.
  4. Add the property spring.cloud.azure.active-directory.authorization-clients.azure.client-authentication-method=private_key_jwt configuration to the client to be authenticated through JWT client authentication.

The following example configuration file is for a web application scenario. The certificate information is configured in the global properties.

spring:
  cloud:
    azure:
      credential:
        client-id: ${AZURE_CLIENT_ID}
        client-certificate-path: ${AZURE_CERTIFICATE_PATH}
        client-certificate-password: ${AZURE_CERTIFICATE_PASSWORD}
      profile:
        tenant-id: ${AZURE_TENANT_ID}
      active-directory:
        enabled: true
        user-group:
          allowed-group-names: group1,group2
          allowed-group-ids: <group1-id>,<group2-id>
        post-logout-redirect-uri: http://localhost:8080
        authorization-clients:
          azure:
            client-authentication-method: private_key_jwt
          arm:
            client-authentication-method: private_key_jwt
            on-demand: true
            scopes: https://management.core.windows.net/user_impersonation
          graph:
            client-authentication-method: private_key_jwt
            scopes:
              - https://graph.microsoft.com/User.Read
              - https://graph.microsoft.com/Directory.Read.All
          webapiA:
            client-authentication-method: private_key_jwt
            scopes:
              - ${WEB_API_A_APP_ID_URL}/Obo.WebApiA.ExampleScope
          webapiB:
            client-authentication-method: private_key_jwt
            scopes:
              - ${WEB_API_B_APP_ID_URL}/.default
            authorization-grant-type: client_credentials

You can also configure the certificate information in the active-directory service properties, as shown in this example:

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-certificate-path: ${AZURE_CERTIFICATE_PATH}
          client-certificate-password: ${AZURE_CERTIFICATE_PASSWORD}
        profile:
          tenant-id: ${AZURE_TENANT_ID}
        user-group:
          allowed-group-names: group1,group2
          allowed-group-ids: <group1-id>,<group2-id>
        post-logout-redirect-uri: http://localhost:8080
        authorization-clients:
          azure:
            client-authentication-method: private_key_jwt
          arm:
            client-authentication-method: private_key_jwt
            on-demand: true
            scopes: https://management.core.windows.net/user_impersonation
          graph:
            client-authentication-method: private_key_jwt
            scopes:
              - https://graph.microsoft.com/User.Read
              - https://graph.microsoft.com/Directory.Read.All
          webapiA:
            client-authentication-method: private_key_jwt
            scopes:
              - ${WEB_API_A_APP_ID_URL}/Obo.WebApiA.ExampleScope
          webapiB:
            client-authentication-method: private_key_jwt
            scopes:
              - ${WEB_API_B_APP_ID_URL}/.default
            authorization-grant-type: client_credentials
Connecting to Azure AD via proxy

To connect Azure AD via proxy, provide a RestTemplateCustomizer bean. For more information, see the Connecting to Azure AD via proxy section.

Samples

Sample project: aad-resource-server.

Resource server visiting other resource servers

System Diagram

System diagram for a resource server visiting other resource servers.

Create required resources in Azure
  1. Read MS docs about register an application with the Microsoft identity platform.

  2. Create app registration. Get AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET.

Add required dependencies
<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
</dependencies>
Add required properties
spring:
  cloud:
    azure:
      active-directory:
        profile:
          tenant-id: ${AZURE_TENANT_ID}
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        authorization-clients:
          graph:
            scopes:
              - https://graph.microsoft.com/User.Read
Use OAuth2AuthorizedClient in your application
public class SampleController {
    @GetMapping("call-graph")
    public String callGraph(@RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient graph) {
        return callMicrosoftGraphMeEndpoint(graph);
    }
}
Samples

Sample project: aad-resource-server-obo.

Web application and resource server in one application

Create required resources in Azure
  1. Read MS docs about register an application with the Microsoft identity platform.

  2. Create app registration. Get AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET.

Add required dependencies
<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
</dependencies>
Add required properties

Set property spring.cloud.azure.active-directory.application-type to web_application_and_resource_server, and specify the authorization type for each authorization client.

spring:
  cloud:
    azure:
      active-directory:
        profile:
          tenant-id: ${AZURE_TENANT_ID}
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        app-id-uri: ${WEB_API_ID_URI}
        application-type: web_application_and_resource_server  # This is required.
        authorization-clients:
          graph:
            authorizationGrantType: authorization_code # This is required.
            scopes:
              - https://graph.microsoft.com/User.Read
              - https://graph.microsoft.com/Directory.Read.All
Define securityConfigurationAdapter

Configure multiple HttpSecurity instances, AadWebApplicationAndResourceServerConfig contain two security configurations for resource server and web application.

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AadWebApplicationAndResourceServerConfig {

    @Order(1)
    @Configuration
    public static class ApiWebSecurityConfigurationAdapter extends AadResourceServerWebSecurityConfigurerAdapter {
        protected void configure(HttpSecurity http) throws Exception {
            super.configure(http);
            // All the paths that match `/api/**`(configurable) work as `Resource Server`, other paths work as `Web application`.
            http.antMatcher("/api/**")
                .authorizeRequests().anyRequest().authenticated();
        }
    }

    @Configuration
    public static class HtmlWebSecurityConfigurerAdapter extends AadWebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            super.configure(http);
            // @formatter:off
            http.authorizeRequests()
                    .antMatchers("/login").permitAll()
                    .anyRequest().authenticated();
            // @formatter:on
        }
    }
}

Configuration

Configurable properties of spring-cloud-azure-starter-active-directory:

Name Description
spring.cloud.azure.active-directory.app-id-uri App ID URI which might be used in the "aud" claim of an id_token.
spring.cloud.azure.active-directory.application-type Type of the Azure AD application.
spring.cloud.azure.active-directory.authenticate-additional-parameters Add additional parameters to the Authorization URL.
spring.cloud.azure.active-directory.authorization-clients The OAuth2 authorization clients.
spring.cloud.azure.active-directory.credential.client-id Client Id to use when performing service principal authentication with Azure.
spring.cloud.azure.active-directory.credential.client-secret Client secret to use when performing service principal authentication with Azure.
spring.cloud.azure.active-directory.jwk-set-cache-lifespan The lifespan of the cached JWK set before it expires, default is 5 minutes.
spring.cloud.azure.active-directory.jwk-set-cache-refresh-time The refresh time of the cached JWK set before it expires, default is 5 minutes.
spring.cloud.azure.active-directory.jwt-connect-timeout Connection Timeout for the JWKSet Remote URL call.
spring.cloud.azure.active-directory.jwt-read-timeout Read Timeout for the JWKSet Remote URL call.
spring.cloud.azure.active-directory.jwt-size-limit Size limit in Bytes of the JWKSet Remote URL call.
spring.cloud.azure.active-directory.post-logout-redirect-uri The redirect uri after logout.
spring.cloud.azure.active-directory.profile.cloud-type Name of the Azure cloud to connect to. Supported types are: AZURE, AZURE_CHINA, AZURE_GERMANY, AZURE_US_GOVERNMENT, OTHER.
spring.cloud.azure.active-directory.profile.environment Properties to Azure Active Directory endpoints.
spring.cloud.azure.active-directory.profile.tenant-id Azure Tenant ID.
spring.cloud.azure.active-directory.redirect-uri-template Redirection Endpoint: Used by the authorization server to return responses containing authorization credentials to the client via the resource owner user-agent. The default value is {baseUrl}/login/oauth2/code/.
spring.cloud.azure.active-directory.resource-server.claim-to-authority-prefix-map Configure which claim will be used to build GrantedAuthority, and prefix of the GrantedAuthority's string value. Default value is: "scp" -> "SCOPE_", "roles" -> "APPROLE_".
spring.cloud.azure.active-directory.resource-server.principal-claim-name Configure which claim in access token be returned in AuthenticatedPrincipal#getName. Default value is "sub".
spring.cloud.azure.active-directory.session-stateless If true activates the stateless auth filter AadAppRoleStatelessAuthenticationFilter. The default is false which activates AadAuthenticationFilter.
spring.cloud.azure.active-directory.user-group.allowed-group-ids The group ids can be used to construct GrantedAuthority.
spring.cloud.azure.active-directory.user-group.allowed-group-names The group names can be used to construct GrantedAuthority.
spring.cloud.azure.active-directory.user-group.use-transitive-members If "true", use "v1.0/me/transitiveMemberOf" to get members. Otherwise, use "v1.0/me/memberOf". The default value is false.
spring.cloud.azure.active-directory.user-name-attribute Decide which claim to be principal's name.

Here are some examples about how to use these properties:

Application type

THe application type can be inferred from the dependencies: spring-security-oauth2-client or spring-security-oauth2-resource-server. If the inferred value is not the value you want, you can specify the application type. Here is the table about valid values and inferred value:

Application type of spring-cloud-azure-starter-active-directory:

Has dependency: spring-security-oauth2-client Has dependency: spring-security-oauth2-resource-server Valid values of application type Inferred value
Yes No web_application web_application
No Yes resource_server resource_server
Yes Yes web_application, resource_server, resource_server_with_obo, web_application_and_resource_server resource_server_with_obo

Spring Security with Azure Active Directory B2C

Azure Active Directory (Azure AD) B2C is an identity management service that enables you to customize and control how customers sign up, sign in, and manage their profiles when using your applications. Azure AD B2C enables these actions while protecting the identities of your customers at the same time.

Dependency setup

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory-b2c</artifactId>
    </dependency>
</dependencies>

Configuration

Configurable properties of spring-cloud-azure-starter-active-directory-b2c:

Name Description
spring.cloud.azure.active-directory.b2c.app-id-uri App ID URI which might be used in the "aud" claim of a token.
spring.cloud.azure.active-directory.b2c.authenticate-additional-parameters Additional parameters for authentication.
spring.cloud.azure.active-directory.b2c.authorization-clients Specify client configuration.
spring.cloud.azure.active-directory.b2c.base-uri Azure AD B2C endpoint base uri.
spring.cloud.azure.active-directory.b2c.credential Azure AD B2C credential information.
spring.cloud.azure.active-directory.b2c.jwt-connect-timeout Connection Timeout for the JWKSet Remote URL call.
spring.cloud.azure.active-directory.b2c.jwt-read-timeout Read Timeout for the JWKSet Remote URL call.
spring.cloud.azure.active-directory.b2c.jwt-size-limit Size limit in Bytes of the JWKSet Remote URL call.
spring.cloud.azure.active-directory.b2c.login-flow Specify the primary sign-in flow key. The default value is sign-up-or-sign-in.
spring.cloud.azure.active-directory.b2c.logout-success-url Redirect url after logout. The default value is http://localhost:8080/login.
spring.cloud.azure.active-directory.b2c.profile Azure AD B2C profile information.
spring.cloud.azure.active-directory.b2c.reply-url Reply url after get authorization code. The default value is {baseUrl}/login/oauth2/code/.
spring.cloud.azure.active-directory.b2c.user-flows User flows.
spring.cloud.azure.active-directory.b2c.user-name-attribute-name User name attribute name.

For full configurations, check Spring Cloud Azure configuration properties.

Basic usage

A web application is any web-based application that allows user to login with Azure AD, whereas a resource server will either accept or deny access after validating access_token obtained from Azure AD. We will cover 4 scenarios in this guide:

  1. Accessing a web application.

  2. Web application accessing resource servers.

  3. Accessing a resource server.

  4. Resource server accessing other resource servers.

System diagram of web application interaction with Azure AD and resource servers.

Usage 1: Accessing a web application

This scenario uses The OAuth 2.0 authorization code grant flow to log in a user with your Azure AD B2C user.

  1. Select Azure AD B2C from the portal menu, click Applications, and then click Add.

  2. Specify your application Name, we call it webapp, add http://localhost:8080/login/oauth2/code/ for the Reply URL, record the Application ID as your WEB_APP_AZURE_CLIENT_ID and then click Save.

  3. Select Keys from your application, click Generate key to generate WEB_APP_AZURE_CLIENT_SECRET and then Save.

  4. Select User flows on your left, and then Click New user flow.

  5. Choose Sign up or in, Profile editing and Password reset to create user flows respectively. Specify your user flow Name and User attributes and claims, click Create.

  6. Select API permissions > Add a permission > Microsoft APIs, select Microsoft Graph, select Delegated permissions, check offline_access and openid permissions, select Add permission to complete the process.

  7. Grant admin consent for Graph permissions.

    Azure portal screenshot showing API permissions screen for an app, with graph permissions highlighted.

  8. Add the following dependencies in your pom.xml.

    <dependencies>
        <dependency>
            <groupId>com.azure.spring</groupId>
            <artifactId>azure-spring-boot-starter-active-directory-b2c</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        </dependency>
    </dependencies>
    
  9. Add properties in application.yml using the values you created earlier, for example:

    spring:
      cloud:
        azure:
          active-directory:
            b2c:
              authenticate-additional-parameters:
                domain_hint: xxxxxxxxx         # optional
                login_hint: xxxxxxxxx          # optional
                prompt: [login,none,consent]   # optional
              base-uri: ${BASE_URI}
              credential:
                client-id: ${WEBAPP_AZURE_CLIENT_ID}
                client-secret: ${WEBAPP_AZURE_CLIENT_SECRET}
              login-flow: ${LOGIN_USER_FLOW_KEY}               # default to sign-up-or-sign-in, will look up the user-flows map with provided key.
              logout-success-url: ${LOGOUT_SUCCESS_URL}
              user-flows:
                ${YOUR_USER_FLOW_KEY}: ${USER_FLOW_NAME}
              user-name-attribute-name: ${USER_NAME_ATTRIBUTE_NAME}
    
  10. Write your Java code.

    Controller code can refer to the following:

    @Controller
    public class WebController {
    
        private void initializeModel(Model model, OAuth2AuthenticationToken token) {
            if (token != null) {
                final OAuth2User user = token.getPrincipal();
                model.addAllAttributes(user.getAttributes());
                model.addAttribute("grant_type", user.getAuthorities());
                model.addAttribute("name", user.getName());
            }
        }
    
        @GetMapping(value = { "/", "/home" })
        public String index(Model model, OAuth2AuthenticationToken token) {
            initializeModel(model, token);
            return "home";
        }
    }
    

    Security configuration code can refer to the following:

    @EnableWebSecurity
    public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    
        private final AadB2cOidcLoginConfigurer configurer;
    
        public WebSecurityConfiguration(AadB2cOidcLoginConfigurer configurer) {
            this.configurer == configurer;
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // @formatter:off
            http.authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                .apply(configurer);
            // @formatter:off
        }
    }
    

    Copy the home.html from aad-b2c-web-application sample, and replace the PROFILE_EDIT_USER_FLOW and PASSWORD_RESET_USER_FLOW with your user flow name respectively that completed earlier.

  11. Build and test your app

    Let Webapp run on port 8080.

  12. After your application is built and started by Maven, open http://localhost:8080/ in a web browser; you should be redirected to login page.

  13. Click link with the login user flow, you should be redirected Azure AD B2C to start the authentication process.

  14. After you have logged in successfully, you should see the sample home page from the browser.

Usage 2: Web application accessing resource servers

This scenario is based on Accessing a web application scenario to allow application to access other resources, that is The OAuth 2.0 client credentials grant flow.

  1. Select Azure AD B2C from the portal menu, click Applications, and then click Add.

  2. Specify your application Name, we call it webApiA, record the Application ID as your WEB_API_A_AZURE_CLIENT_ID and then click Save.

  3. Select Keys from your application, click Generate key to generate WEB_API_A_AZURE_CLIENT_SECRET and then Save.

  4. Select Expose an API on your left, and then Click the Set link, record the Application ID URI as your WEB_API_A_APP_ID_URL, then Save.

  5. Select Manifest on your left, and then paste the following json segment into appRoles array, record the Application ID URI as your WEB_API_A_APP_ID_URL, record the value of the app role as your WEB_API_A_ROLE_VALUE, then save.

    {
      "allowedMemberTypes": [
        "Application"
      ],
      "description": "WebApiA.SampleScope",
      "displayName": "WebApiA.SampleScope",
      "id": "04989db0-3efe-4db6-b716-ae378517d2b7",
      "isEnabled": true,
      "value": "WebApiA.SampleScope"
    }
    

    Azure portal screenshot showing application manifest screen with `appRoles` JSON highlighted.

  6. Select API permissions > Add a permission > My APIs, select WebApiA application name, select Application Permissions, select WebApiA.SampleScope permission, select Add permission to complete the process.

  7. Grant admin consent for WebApiA permissions.

    Azure portal screenshot showing application API permissions screen.

  8. Add the following dependency on the basis of Accessing a web application scenario.

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    
  9. Add the following configuration on the basis of Accessing a web application scenario.

        spring:
          cloud:
            azure:
              active-directory:
                b2c:
                  base-uri: ${BASE_URI}             # Such as: https://xxxxb2c.b2clogin.com
                  profile:
                    tenant-id: ${AZURE_TENANT_ID}
                  authorization-clients:
                    ${RESOURCE_SERVER_A_NAME}:
                      authorization-grant-type: client_credentials
                      scopes: ${WEB_API_A_APP_ID_URL}/.default
    
  10. Write your Webapp Java code.

    Controller code can refer to the following:

    class Demo {
        /**
         * Access to protected data from Webapp to WebApiA through client credential flow. The access token is obtained by webclient, or
         * <p>@RegisteredOAuth2AuthorizedClient("webApiA")</p>. In the end, these two approaches will be executed to
         * DefaultOAuth2AuthorizedClientManager#authorize method, get the access token.
         *
         * @return Respond to protected data from WebApi A.
         */
        @GetMapping("/webapp/webApiA")
        public String callWebApiA() {
            String body = webClient
                .get()
                .uri(LOCAL_WEB_API_A_SAMPLE_ENDPOINT)
                .attributes(clientRegistrationId("webApiA"))
                .retrieve()
                .bodyToMono(String.class)
                .block();
            LOGGER.info("Call callWebApiA(), request '/webApiA/sample' returned: {}", body);
            return "Request '/webApiA/sample'(WebApi A) returned a " + (body != null ? "success." : "failure.");
        }
    }
    

    Security configuration code is the same with Accessing a web application scenario, another bean webClient is added as follows:

    public class SampleConfiguration {
        @Bean
        public WebClient webClient(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
            ServletOAuth2AuthorizedClientExchangeFilterFunction function =
                new ServletOAuth2AuthorizedClientExchangeFilterFunction(oAuth2AuthorizedClientManager);
            return WebClient.builder()
                            .apply(function.oauth2Configuration())
                            .build();
        }
    }
    
  11. See Accessing a resource server section to write your WebApiA Java code.

  12. Build and test your app

    Let Webapp and WebApiA run on port 8080 and 8081 respectively. Start Webapp and WebApiA application, return to the home page after logging successfully, you can access http://localhost:8080/webapp/webApiA to get WebApiA resource response.

Usage 3: Accessing a resource server

This scenario not support login. Just protect the server by validating the access token, and if valid, serves the request.

  1. Refer to Usage 2: Web Application Accessing Resource Servers to build your WebApiA permission.

  2. Add WebApiA permission and grant admin consent for your web application.

  3. Add the following dependencies in your pom.xml.

    <dependencies>
        <dependency>
            <groupId>com.azure.spring</groupId>
            <artifactId>azure-spring-boot-starter-active-directory-b2c</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    
  4. Add the following configuration.

        spring:
          cloud:
            azure:
              active-directory:
                b2c:
                  base-uri: ${BASE_URI}             # Such as: https://xxxxb2c.b2clogin.com
                  profile:
                    tenant-id: ${AZURE_TENANT_ID}
                  app-id-uri: ${APP_ID_URI}         # If you're using v1.0 token, configure app-id-uri for `aud` verification
                  credential:
                    client-id: ${AZURE_CLIENT_ID}           # If you're using v2.0 token, configure client-id for `aud` verification
    
  5. Write your Java code.

    Controller code can refer to the following:

    class Demo {
        /**
         * webApiA resource api for web app
         * @return test content
         */
        @PreAuthorize("hasAuthority('APPROLE_WebApiA.SampleScope')")
        @GetMapping("/webApiA/sample")
        public String webApiASample() {
            LOGGER.info("Call webApiASample()");
            return "Request '/webApiA/sample'(WebApi A) returned successfully.";
        }
    }
    

    Security configuration code can refer to the following:

    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests((requests) -> requests.anyRequest().authenticated())
                .oauth2ResourceServer()
                .jwt()
                .jwtAuthenticationConverter(new AadJwtBearerTokenAuthenticationConverter());
        }
    }
    
  6. Build and test your app

    Let WebApiA run on port 8081. Get the access token for webApiA resource and access http://localhost:8081/webApiA/sample as the Bearer authorization header.

Usage 4: Resource server accessing other resource servers

This scenario is an upgrade of Accessing a resource server, supports access to other application resources, based on OAuth2 client credentials flow.

  1. Referring to the previous steps, we create a WebApiB application and expose an application permission WebApiB.SampleScope.

    {
        "allowedMemberTypes": [
            "Application"
        ],
        "description": "WebApiB.SampleScope",
        "displayName": "WebApiB.SampleScope",
        "id": "04989db0-3efe-4db6-b716-ae378517d2b7",
        "isEnabled": true,
        "lang": null,
        "origin": "Application",
        "value": "WebApiB.SampleScope"
    }
    

    Azure portal screenshot showing application WebApiB manifest screen with `appRoles` JSON highlighted.

  2. Grant admin consent for WebApiB permissions.

    Azure portal screenshot showing application WebApiA API permissions screen.

  3. On the basis of Accessing a resource server, add a dependency in your pom.xml.

    <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    
  4. Add the following configuration on the basis of Accessing a resource server scenario configuration.

        spring:
          cloud:
            azure:
              active-directory:
                b2c:
                  credential:
                    client-secret: ${WEB_API_A_AZURE_CLIENT_SECRET}
                  authorization-clients:
                    ${RESOURCE_SERVER_B_NAME}:
                      authorization-grant-type: client_credentials
                      scopes: ${WEB_API_B_APP_ID_URL}/.default
    
  5. Write your Java code.

    WebApiA controller code can refer to the following:

    public class SampleController {
        /**
         * Access to protected data from WebApiA to WebApiB through client credential flow. The access token is obtained by webclient, or
         * <p>@RegisteredOAuth2AuthorizedClient("webApiA")</p>. In the end, these two approaches will be executed to
         * DefaultOAuth2AuthorizedClientManager#authorize method, get the access token.
         *
         * @return Respond to protected data from WebApi B.
         */
        @GetMapping("/webApiA/webApiB/sample")
        @PreAuthorize("hasAuthority('APPROLE_WebApiA.SampleScope')")
        public String callWebApiB() {
            String body = webClient
                .get()
                .uri(LOCAL_WEB_API_B_SAMPLE_ENDPOINT)
                .attributes(clientRegistrationId("webApiB"))
                .retrieve()
                .bodyToMono(String.class)
                .block();
            LOGGER.info("Call callWebApiB(), request '/webApiB/sample' returned: {}", body);
            return "Request 'webApiA/webApiB/sample'(WebApi A) returned a " + (body != null ? "success." : "failure.");
        }
    }
    

    WebApiB controller code can refer to the following:

    public class SampleController {
        /**
         * webApiB resource api for other web application
         * @return test content
         */
        @PreAuthorize("hasAuthority('APPROLE_WebApiB.SampleScope')")
        @GetMapping("/webApiB/sample")
        public String webApiBSample() {
            LOGGER.info("Call webApiBSample()");
            return "Request '/webApiB/sample'(WebApi B) returned successfully.";
        }
    }
    

    Security configuration code is the same with Accessing a resource server scenario, another bean webClient is added as follows

    public class SampleConfiguration {
        @Bean
        public WebClient webClient(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
            ServletOAuth2AuthorizedClientExchangeFilterFunction function =
                new ServletOAuth2AuthorizedClientExchangeFilterFunction(oAuth2AuthorizedClientManager);
            return WebClient.builder()
                            .apply(function.oauth2Configuration())
                            .build();
        }
    }
    
  6. Build and test your app

    Let WebApiA and WebApiB run on port 8081 and 8082 respectively. Start WebApiA and WebApiB application, get the access token for webApiA resource and access http://localhost:8081/webApiA/webApiB/sample as the Bearer authorization header.

Samples

See spring-cloud-azure-starter-active-directory-b2c samples for more details.

Spring Integration support

Spring Integration Extension for Azure provides Spring Integration adapters for the various services provided by the Azure SDK for Java. We provide Spring Integration support for these Azure services: Event Hubs, Service Bus, Storage Queue. The following is a list of supported adapters:

Spring Integration with Azure Event Hubs

Key concepts

Azure Event Hubs is a big data streaming platform and event ingestion service. It can receive and process millions of events per second. Data sent to an event hub can be transformed and stored by using any real-time analytics provider or batching/storage adapters.

Spring Integration enables lightweight messaging within Spring-based applications and supports integration with external systems via declarative adapters. Those adapters provide a higher-level of abstraction over Spring's support for remoting, messaging, and scheduling. The Spring Integration for Event Hubs extension project provides inbound and outbound channel adapters and gateways for Azure Event Hubs.

Note

RxJava support APIs are dropped from version 4.0.0. See Javadoc for details.

Consumer group

Event Hubs provides similar support of consumer group as Apache Kafka, but with slight different logic. While Kafka stores all committed offsets in the broker, you have to store offsets of Event Hubs messages being processed manually. Event Hubs SDK provides the function to store such offsets inside Azure Storage.

Partitioning support

Event Hubs provides a similar concept of physical partition as Kafka. But unlike Kafka's auto re-balancing between consumers and partitions, Event Hubs provides a kind of preemptive mode. The storage account acts as a lease to determine which partition is owned by which consumer. When a new consumer starts, it will try to steal some partitions from most heavy-loaded consumers to achieve the workload balancing.

To specify the load balancing strategy, developers can use EventHubsContainerProperties for the configuration. See the following section for an example of how to configure EventHubsContainerProperties.

Batch consumer support

The EventHubsInboundChannelAdapter supports the batch-consuming mode. To enable it, users can specify the listener mode as ListenerMode.BATCH when constructing an EventHubsInboundChannelAdapter instance. When enabled, an Message of which the payload is a list of batched events will be received and passed to the downstream channel. Each message header is also converted as a list, of which the content is the associated header value parsed from each event. For the communal headers of partition ID, checkpointer and last enqueued properties, they are presented as a single value for the entire batch of events shares the same one. See Event Hubs Message Headers for more details.

Note

The checkpoint header only exists when MANUAL checkpoint mode is used.

Checkpointing of batch consumer supports two modes: BATCH and MANUAL. BATCH mode is an auto checkpointing mode to checkpoint the entire batch of events together once they are received. MANUAL mode is to checkpoint the events by users. When used, the Checkpointer will be passed into the message header, and users could use it to do checkpointing.

The batch consuming policy can be specified by properties of max-size and max-wait-time, where max-size is a necessary property while max-wait-time is optional. To specify the batch consuming strategy, developers can use EventHubsContainerProperties for the configuration. See the following section for an example of how to configure EventHubsContainerProperties.

Dependency setup

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-integration-eventhubs</artifactId>
</dependency>

Configuration

This starter provides the following 3 parts of configuration options:

Connection Configuration Properties

This section contains the configuration options used for connecting to Azure Event Hubs.

Note

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, see Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.

Connection configurable properties of spring-cloud-azure-starter-integration-eventhubs:

Property Type Description
spring.cloud.azure.eventhubs.enabled boolean Whether an Azure Event Hubs is enabled.
spring.cloud.azure.eventhubs.connection-string String Event Hubs Namespace connection string value.
spring.cloud.azure.eventhubs.namespace String Event Hubs Namespace value, which is the prefix of the FQDN. A FQDN should be composed of NamespaceName.DomainName
spring.cloud.azure.eventhubs.domain-name String Domain name of an Azure Event Hubs Namespace value.
spring.cloud.azure.eventhubs.custom-endpoint-address String Custom Endpoint address.
spring.cloud.azure.eventhubs.shared-connection Boolean Whether the underlying EventProcessorClient and EventHubProducerAsyncClient use the same connection. By default, a new connection is constructed and used created for each Event Hub client created.
Checkpoint Configuration Properties

This section contains the configuration options for the Storage Blobs service, which is used for persisting partition ownership and checkpoint information.

Note

From version 4.0.0, when the property of spring.cloud.azure.eventhubs.processor.checkpoint-store.create-container-if-not-exists is not enabled manually, no Storage container will be created automatically.

Checkpointing configurable properties of spring-cloud-azure-starter-integration-eventhubs:

Property Type Description
spring.cloud.azure.eventhubs.processor.checkpoint-store.create-container-if-not-exists Boolean Whether to allow creating containers if not exists.
spring.cloud.azure.eventhubs.processor.checkpoint-store.account-name String Name for the storage account.
spring.cloud.azure.eventhubs.processor.checkpoint-store.account-key String Storage account access key.
spring.cloud.azure.eventhubs.processor.checkpoint-store.container-name String Storage container name.

Common Azure Service SDK configuration options are configurable for Storage Blob checkpoint store as well. The supported configuration options are introduced in the Configuration page, and could be configured with either the unified prefix spring.cloud.azure. or the prefix of spring.cloud.azure.eventhubs.processor.checkpoint-store.

Event Hub processor configuration properties

The EventHubsInboundChannelAdapter uses the EventProcessorClient to consume messages from an event hub, to configure the overall properties of an EventProcessorClient, developers can use EventHubsContainerProperties for the configuration. See the following section about how to work with EventHubsInboundChannelAdapter.

Basic usage

Send messages to Azure Event Hubs
  1. Fill the credential configuration options.

    • For credentials as connection string, configure the following properties in application.yml:
        spring:
          cloud:
            azure:
              eventhubs:
                connection-string: ${AZURE_SERVICE_BUS_CONNECTION_STRING}
                processor:
                  checkpoint-store:
                    container-name: ${CHECKPOINT-CONTAINER}
                    account-name: ${CHECKPOINT-STORAGE-ACCOUNT}
                    account-key: ${CHECKPOINT-ACCESS-KEY}
    
    • For credentials as managed identities, configure the following properties in application.yml:
        spring:
          cloud:
            azure:
              credential:
                managed-identity-enabled: true
                client-id: ${AZURE_CLIENT_ID}
              eventhubs:
                namespace: ${AZURE_SERVICE_BUS_NAMESPACE}
                processor:
                  checkpoint-store:
                    container-name: ${CONTAINER_NAME}
                    account-name: ${ACCOUNT_NAME}
    
    • For credentials as service principal, configure the following properties in application.yml:
        spring:
          cloud:
            azure:
              credential:
                client-id: ${AZURE_CLIENT_ID}
                client-secret: ${AZURE_CLIENT_SECRET}
              profile:
                tenant-id: ${AZURE_TENANT_ID}
              eventhubs:
                namespace: ${AZURE_SERVICE_BUS_NAMESPACE}
                processor:
                  checkpoint-store:
                    container-name: ${CONTAINER_NAME}
                    account-name: ${ACCOUNT_NAME}
    
  2. Create DefaultMessageHandler with the bean of EventHubsTemplate to send messages to Event Hubs.

    class Demo {
        private static final String OUTPUT_CHANNEL = "output";
        private static final String EVENTHUB_NAME = "eh1";
    
        @Bean
        @ServiceActivator(inputChannel = OUTPUT_CHANNEL)
        public MessageHandler messageSender(EventHubsTemplate eventHubsTemplate) {
            DefaultMessageHandler handler = new DefaultMessageHandler(EVENTHUB_NAME, eventHubsTemplate);
            handler.setSendCallback(new ListenableFutureCallback<Void>() {
                @Override
                public void onSuccess(Void result) {
                    LOGGER.info("Message was sent successfully.");
                }
                @Override
                public void onFailure(Throwable ex) {
                    LOGGER.error("There was an error sending the message.", ex);
                }
            });
            return handler;
        }
    }
    
  3. Create a message gateway binding with the above message handler via a message channel.

    class Demo {
        @Autowired
        EventHubOutboundGateway messagingGateway;
    
        @MessagingGateway(defaultRequestChannel = OUTPUT_CHANNEL)
        public interface EventHubOutboundGateway {
            void send(String text);
        }
    }
    
  4. Send messages using the gateway.

    class Demo {
        public void demo() {
            this.messagingGateway.send(message);
        }
    }
    
Receive messages from Azure Event Hubs
  1. Fill the credential configuration options.

  2. Create a bean of message channel as the input channel.

    @Configuration
    class Demo {
        @Bean
        public MessageChannel input() {
            return new DirectChannel();
        }
    }
    
  3. Create EventHubsInboundChannelAdapter with the bean of EventHubsMessageListenerContainer to receive messages from Event Hubs.

    @Configuration
    class Demo {
        private static final String INPUT_CHANNEL = "input";
        private static final String EVENTHUB_NAME = "eh1";
        private static final String CONSUMER_GROUP = "$Default";
    
        @Bean
        public EventHubsInboundChannelAdapter messageChannelAdapter(
                @Qualifier(INPUT_CHANNEL) MessageChannel inputChannel,
                EventHubsMessageListenerContainer listenerContainer) {
            EventHubsInboundChannelAdapter adapter = new EventHubsInboundChannelAdapter(processorContainer);
            adapter.setOutputChannel(inputChannel);
            return adapter;
        }
    
        @Bean
        public EventHubsMessageListenerContainer messageListenerContainer(EventHubsProcessorFactory processorFactory) {
            EventHubsContainerProperties containerProperties = new EventHubsContainerProperties();
            containerProperties.setEventHubName(EVENTHUB_NAME);
            containerProperties.setConsumerGroup(CONSUMER_GROUP);
            containerProperties.setCheckpointConfig(new CheckpointConfig(CheckpointMode.MANUAL));
            return new EventHubsMessageListenerContainer(processorFactory, containerProperties);
        }
    }
    
  4. Create a message receiver binding with EventHubsInboundChannelAdapter via the message channel created before.

    class Demo {
        @ServiceActivator(inputChannel = INPUT_CHANNEL)
        public void messageReceiver(byte[] payload, @Header(AzureHeaders.CHECKPOINTER) Checkpointer checkpointer) {
            String message = new String(payload);
            LOGGER.info("New message received: '{}'", message);
            checkpointer.success()
                    .doOnSuccess(s -> LOGGER.info("Message '{}' successfully checkpointed", message))
                    .doOnError(e -> LOGGER.error("Error found", e))
                    .block();
        }
    }
    
Configure EventHubsMessageConverter to customize objectMapper

EventHubsMessageConverter is made as a configurable bean to allow users to customize ObjectMapper.

Batch consumer support

To consume messages from Event Hubs in batches is similar with the above sample, besides users should set the batch-consuming related configuration options for EventHubsInboundChannelAdapter.

When create EventHubsInboundChannelAdapter, the listener mode should be set as BATCH. When create bean of EventHubsMessageListenerContainer, set the checkpoint mode as either MANUAL or BATCH, and the batch options can be configured as needed.

@Configuration
class Demo {
    private static final String INPUT_CHANNEL = "input";
    private static final String EVENTHUB_NAME = "eh1";
    private static final String CONSUMER_GROUP = "$Default";

    @Bean
    public EventHubsInboundChannelAdapter messageChannelAdapter(
            @Qualifier(INPUT_CHANNEL) MessageChannel inputChannel,
            EventHubsMessageListenerContainer listenerContainer) {
        EventHubsInboundChannelAdapter adapter = new EventHubsInboundChannelAdapter(processorContainer, ListenerMode.BATCH);
        adapter.setOutputChannel(inputChannel);
        return adapter;
    }

    @Bean
    public EventHubsMessageListenerContainer messageListenerContainer(EventHubsProcessorFactory processorFactory) {
        EventHubsContainerProperties containerProperties = new EventHubsContainerProperties();
        containerProperties.setEventHubName(EVENTHUB_NAME);
        containerProperties.setConsumerGroup(CONSUMER_GROUP);
        containerProperties.getBatch().setMaxSize(100);
        containerProperties.setCheckpointConfig(new CheckpointConfig(CheckpointMode.MANUAL));
        return new EventHubsMessageListenerContainer(processorFactory, containerProperties);
    }
}
Event Hubs message headers

The following table illustrates how Event Hubs message properties are mapped to Spring message headers. For Azure Event Hubs, message is called as event.

Mapping between Event Hubs Message / Event Properties and Spring Message Headers in Record Listener Mode:

Event Hubs Event Properties Spring Message Header Constants Type Description
Enqueued time EventHubsHeaders#ENQUEUED_TIME Instant The instant, in UTC, of when the event was enqueued in the Event Hub partition.
Offset EventHubsHeaders#OFFSET Long The offset of the event when it was received from the associated Event Hub partition.
Partition key AzureHeaders#PARTITION_KEY String The partition hashing key if it was set when originally publishing the event.
Partition ID AzureHeaders#RAW_PARTITION_ID String The partition ID of the Event Hub.
Sequence number EventHubsHeaders#SEQUENCE_NUMBER Long The sequence number assigned to the event when it was enqueued in the associated Event Hub partition.
Last enqueued event properties EventHubsHeaders#LAST_ENQUEUED_EVENT_PROPERTIES LastEnqueuedEventProperties The properties of the last enqueued event in this partition.
NA AzureHeaders#CHECKPOINTER Checkpointer The header for checkpoint the specific message.

Users can parse the message headers for the related information of each event. To set a message header for the event, all customized headers will be put as an application property of an event, where the header is set as the property key. When events are received from Event Hubs, all application properties will be converted to the message header.

Note

Message headers of partition key, enqueued time, offset and sequence number is not supported to be set manually.

When the batch-consumer mode is enabled, the specific headers of batched messages are listed the follows, which contains a list of values from each single Event Hubs event.

Mapping between Event Hubs Message / Event Properties and Spring Message Headers in Batch Listener Mode:

Event Hubs Event Properties Spring Batch Message Header Constants Type Description
Enqueued time EventHubsHeaders#ENQUEUED_TIME List of Instant List of the instant, in UTC, of when each event was enqueued in the Event Hub partition.
Offset EventHubsHeaders#OFFSET List of Long List of the offset of each event when it was received from the associated Event Hub partition.
Partition key AzureHeaders#PARTITION_KEY List of String List of the partition hashing key if it was set when originally publishing each event.
Sequence number EventHubsHeaders#SEQUENCE_NUMBER List of Long List of the sequence number assigned to each event when it was enqueued in the associated Event Hub partition.
System properties EventHubsHeaders#BATCH_CONVERTED_SYSTEM_PROPERTIES List of Map List of the system properties of each event.
Application properties EventHubsHeaders#BATCH_CONVERTED_APPLICATION_PROPERTIES List of Map List of the application properties of each event, where all customized message headers or event properties are placed.

Note

When publish messages, all the above batch headers will be removed from the messages if exist.

Samples

See azure-spring-boot-samples for more details.

Spring Integration with Azure Service Bus

Key concepts

Spring Integration enables lightweight messaging within Spring-based applications and supports integration with external systems via declarative adapters.

The Spring Integration for Azure Service Bus extension project provides inbound and outbound channel adapters for Azure Service Bus.

Note

CompletableFuture support APIs have been deprecated from version 2.10.0, and is replaced by Reactor Core from version 4.0.0. See Javadoc for details.

Dependency setup

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-integration-servicebus</artifactId>
</dependency>

Configuration

This starter provides the following 2 parts of configuration options:

Connection configuration properties

This section contains the configuration options used for connecting to Azure Service Bus.

Note

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, see Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.

Connection configurable properties of spring-cloud-azure-starter-integration-servicebus:

Property Type Description
spring.cloud.azure.servicebus.enabled boolean Whether an Azure Service Bus is enabled.
spring.cloud.azure.servicebus.connection-string String Service Bus Namespace connection string value.
spring.cloud.azure.servicebus.namespace String Service Bus Namespace value, which is the prefix of the FQDN. A FQDN should be composed of NamespaceName.DomainName
spring.cloud.azure.servicebus.domain-name String Domain name of an Azure Service Bus Namespace value.
Service Bus processor configuration properties

The ServiceBusInboundChannelAdapter uses the ServiceBusProcessorClient to consume messages, to configure the overall properties of an ServiceBusProcessorClient, developers can use ServiceBusContainerProperties for the configuration. See the following section about how to work with ServiceBusInboundChannelAdapter.

Basic usage

Send messages to Azure Service Bus
  1. Fill the credential configuration options.

    • For credentials as connection string, configure the following properties in application.yml:
        spring:
          cloud:
            azure:
              servicebus:
                connection-string: ${AZURE_SERVICE_BUS_CONNECTION_STRING}
    
    • For credentials as managed identities, configure the following properties in application.yml:
        spring:
          cloud:
            azure:
              credential:
                managed-identity-enabled: true
                client-id: ${AZURE_CLIENT_ID}
              profile:
                tenant-id: ${AZURE_TENANT_ID}
              servicebus:
                namespace: ${AZURE_SERVICE_BUS_NAMESPACE}
    
    • For credentials as service principal, configure the following properties in application.yml:

          spring:
            cloud:
              azure:
                credential:
                  client-id: ${AZURE_CLIENT_ID}
                  client-secret: ${AZURE_CLIENT_SECRET}
                profile:
                  tenant-id: ${AZURE_TENANT_ID}
                servicebus:
                  namespace: ${AZURE_SERVICE_BUS_NAMESPACE}
      
  2. Create DefaultMessageHandler with the bean of ServiceBusTemplate to send messages to Service Bus, set the entity type for the ServiceBusTemplate. This sample takes Service Bus Queue as example.

    class Demo {
        private static final String OUTPUT_CHANNEL = "queue.output";
    
        @Bean
        @ServiceActivator(inputChannel = OUTPUT_CHANNEL)
        public MessageHandler queueMessageSender(ServiceBusTemplate serviceBusTemplate) {
            serviceBusTemplate.setDefaultEntityType(ServiceBusEntityType.QUEUE);
            DefaultMessageHandler handler = new DefaultMessageHandler(QUEUE_NAME, serviceBusTemplate);
            handler.setSendCallback(new ListenableFutureCallback<Void>() {
                @Override
                public void onSuccess(Void result) {
                    LOGGER.info("Message was sent successfully.");
                }
    
                @Override
                public void onFailure(Throwable ex) {
                    LOGGER.info("There was an error sending the message.");
                }
            });
    
            return handler;
        }
    }
    
  3. Create a message gateway binding with the above message handler via a message channel.

    class Demo {
        @Autowired
        QueueOutboundGateway messagingGateway;
    
        @MessagingGateway(defaultRequestChannel = OUTPUT_CHANNEL)
        public interface QueueOutboundGateway {
            void send(String text);
        }
    }
    
  4. Send messages using the gateway.

    class Demo {
        public void demo() {
            this.messagingGateway.send(message);
        }
    }
    
Receive messages from Azure Service Bus
  1. Fill the credential configuration options.

  2. Create a bean of message channel as the input channel.

    @Configuration
    class Demo {
        private static final String INPUT_CHANNEL = "input";
    
        @Bean
        public MessageChannel input() {
            return new DirectChannel();
        }
    }
    
  3. Create ServiceBusInboundChannelAdapter with the bean of ServiceBusMessageListenerContainer to receive messages to Service Bus. This sample takes Service Bus Queue as example.

    @Configuration
    class Demo {
        private static final String QUEUE_NAME = "queue1";
    
        @Bean
        public ServiceBusMessageListenerContainer messageListenerContainer(ServiceBusProcessorFactory processorFactory) {
            ServiceBusContainerProperties containerProperties = new ServiceBusContainerProperties();
            containerProperties.setEntityName(QUEUE_NAME);
            containerProperties.setAutoComplete(false);
            return new ServiceBusMessageListenerContainer(processorFactory, containerProperties);
        }
    
        @Bean
        public ServiceBusInboundChannelAdapter queueMessageChannelAdapter(
            @Qualifier(INPUT_CHANNEL) MessageChannel inputChannel,
            ServiceBusMessageListenerContainer listenerContainer) {
            ServiceBusInboundChannelAdapter adapter = new ServiceBusInboundChannelAdapter(listenerContainer);
            adapter.setOutputChannel(inputChannel);
            return adapter;
        }
    }
    
  4. Create a message receiver binding with ServiceBusInboundChannelAdapter via the message channel we created before.

    class Demo {
        @ServiceActivator(inputChannel = INPUT_CHANNEL)
        public void messageReceiver(byte[] payload, @Header(AzureHeaders.CHECKPOINTER) Checkpointer checkpointer) {
            String message = new String(payload);
            LOGGER.info("New message received: '{}'", message);
            checkpointer.success()
                    .doOnSuccess(s -> LOGGER.info("Message '{}' successfully checkpointed", message))
                    .doOnError(e -> LOGGER.error("Error found", e))
                    .block();
        }
    }
    
Configure ServiceBusMessageConverter to customize objectMapper

ServiceBusMessageConverter is made as a configurable bean to allow users to customize ObjectMapper.

Service Bus message headers

For some Service Bus headers that can be mapped to multiple Spring header constants, the priority of different Spring headers is listed.

Mapping between Service Bus Headers and Spring Headers:

Service Bus Message Headers and Properties Spring Message Header Constants Type Configurable Description
Content type MessageHeaders#CONTENT_TYPE String Yes The RFC2045 Content-Type descriptor of the message.
Correlation ID ServiceBusMessageHeaders#CORRELATION_ID String Yes The correlation ID of the message
Message ID ServiceBusMessageHeaders#MESSAGE_ID String Yes The message ID of the message, this header has higher priority than MessageHeaders#ID.
Message ID MessageHeaders#ID UUID Yes The message ID of the message, this header has lower priority than ServiceBusMessageHeaders#MESSAGE_ID.
Partition key ServiceBusMessageHeaders#PARTITION_KEY String Yes The partition key for sending the message to a partitioned entity.
Reply to MessageHeaders#REPLY_CHANNEL String Yes The address of an entity to send replies to.
Reply to session ID ServiceBusMessageHeaders#REPLY_TO_SESSION_ID String Yes The ReplyToGroupId property value of the message.
Scheduled enqueue time utc ServiceBusMessageHeaders#SCHEDULED_ENQUEUE_TIME OffsetDateTime Yes The datetime at which the message should be enqueued in Service Bus, this header has higher priority than AzureHeaders#SCHEDULED_ENQUEUE_MESSAGE.
Scheduled enqueue time utc AzureHeaders#SCHEDULED_ENQUEUE_MESSAGE Integer Yes The datetime at which the message should be enqueued in Service Bus, this header has lower priority than ServiceBusMessageHeaders#SCHEDULED_ENQUEUE_TIME.
Session ID ServiceBusMessageHeaders#SESSION_ID String Yes The session IDentifier for a session-aware entity.
Time to live ServiceBusMessageHeaders#TIME_TO_LIVE Duration Yes The duration of time before this message expires.
To ServiceBusMessageHeaders#TO String Yes The "to" address of the message, reserved for future use in routing scenarios and presently ignored by the broker itself.
Subject ServiceBusMessageHeaders#SUBJECT String Yes The subject for the message.
Dead letter error description ServiceBusMessageHeaders#DEAD_LETTER_ERROR_DESCRIPTION String No The description for a message that has been dead-lettered.
Dead letter reason ServiceBusMessageHeaders#DEAD_LETTER_REASON String No The reason a message was dead-lettered.
Dead letter source ServiceBusMessageHeaders#DEAD_LETTER_SOURCE String No The entity in which the message was dead-lettered.
Delivery count ServiceBusMessageHeaders#DELIVERY_COUNT long No The number of the times this message was delivered to clients.
Enqueued sequence number ServiceBusMessageHeaders#ENQUEUED_SEQUENCE_NUMBER long No The enqueued sequence number assigned to a message by Service Bus.
Enqueued time ServiceBusMessageHeaders#ENQUEUED_TIME OffsetDateTime No The datetime at which this message was enqueued in Service Bus.
Expires at ServiceBusMessageHeaders#EXPIRES_AT OffsetDateTime No The datetime at which this message will expire.
Lock token ServiceBusMessageHeaders#LOCK_TOKEN String No The lock token for the current message.
Locked until ServiceBusMessageHeaders#LOCKED_UNTIL OffsetDateTime No The datetime at which the lock of this message expires.
Sequence number ServiceBusMessageHeaders#SEQUENCE_NUMBER long No The unique number assigned to a message by Service Bus.
State ServiceBusMessageHeaders#STATE ServiceBusMessageState No The state of the message, which can be Active, Deferred, or Scheduled.
Partition key support

This starter supports Service Bus partitioning by allowing setting partition key and session ID in the message header. This section introduces how to set partition key for messages.

Recommended: Use ServiceBusMessageHeaders.PARTITION_KEY as the key of the header.

public class SampleController {
    @PostMapping("/messages")
    public ResponseEntity<String> sendMessage(@RequestParam String message) {
        LOGGER.info("Going to add message {} to Sinks.Many.", message);
        many.emitNext(MessageBuilder.withPayload(message)
                                    .setHeader(ServiceBusMessageHeaders.PARTITION_KEY, "Customize partition key")
                                    .build(), Sinks.EmitFailureHandler.FAIL_FAST);
        return ResponseEntity.ok("Sent!");
    }
}

Not recommended but currently supported: AzureHeaders.PARTITION_KEY as the key of the header.

public class SampleController {
    @PostMapping("/messages")
    public ResponseEntity<String> sendMessage(@RequestParam String message) {
        LOGGER.info("Going to add message {} to Sinks.Many.", message);
        many.emitNext(MessageBuilder.withPayload(message)
                                    .setHeader(AzureHeaders.PARTITION_KEY, "Customize partition key")
                                    .build(), Sinks.EmitFailureHandler.FAIL_FAST);
        return ResponseEntity.ok("Sent!");
    }
}

Note

When both ServiceBusMessageHeaders.PARTITION_KEY and AzureHeaders.PARTITION_KEY are set in the message headers, ServiceBusMessageHeaders.PARTITION_KEY is preferred.

Session support

This example demonstrates how to manually set the session ID of a message in the application.

public class SampleController {
    @PostMapping("/messages")
    public ResponseEntity<String> sendMessage(@RequestParam String message) {
        LOGGER.info("Going to add message {} to Sinks.Many.", message);
        many.emitNext(MessageBuilder.withPayload(message)
                                    .setHeader(ServiceBusMessageHeaders.SESSION_ID, "Customize session ID")
                                    .build(), Sinks.EmitFailureHandler.FAIL_FAST);
        return ResponseEntity.ok("Sent!");
    }
}

Note

When the ServiceBusMessageHeaders.SESSION_ID is set in the message headers, and a different ServiceBusMessageHeaders.PARTITION_KEY (or AzureHeaders.PARTITION_KEY) header is also set, the value of the session ID will eventually be used to overwrite the value of the partition key.

Samples

See azure-spring-boot-samples for more details.

Spring Integration with Azure Storage Queue

Key concepts

Azure Queue Storage is a service for storing large numbers of messages. You access messages from anywhere in the world via authenticated calls using HTTP or HTTPS. A queue message can be up to 64 KB in size. A queue may contain millions of messages, up to the total capacity limit of a storage account. Queues are commonly used to create a backlog of work to process asynchronously.

Dependency setup

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-integration-storage-queue</artifactId>
</dependency>

Configuration

This starter provides the following configuration options:

Connection configuration properties

This section contains the configuration options used for connecting to Azure Storage Queue.

Note

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, see Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.

Connection configurable properties of spring-cloud-azure-starter-integration-storage-queue:

Property Type Description
spring.cloud.azure.storage.queue.enabled boolean Whether an Azure Storage Queue is enabled.
spring.cloud.azure.storage.queue.connection-string String Storage Queue Namespace connection string value.
spring.cloud.azure.storage.queue.accountName String Storage Queue account name.
spring.cloud.azure.storage.queue.accountKey String Storage Queue account key.
spring.cloud.azure.storage.queue.endpoint String Storage Queue service endpoint.
spring.cloud.azure.storage.queue.sasToken String Sas token credential
spring.cloud.azure.storage.queue.serviceVersion QueueServiceVersion QueueServiceVersion that is used when making API requests.
spring.cloud.azure.storage.queue.messageEncoding String Queue message encoding.

Basic usage

Send messages to Azure Storage Queue
  1. Fill the credential configuration options.

    • For credentials as connection string, configure the following properties in application.yml:
        spring:
          cloud:
            azure:
              storage:
                queue:
                  connection-string: ${AZURE_SERVICE_BUS_CONNECTION_STRING}
    
    • For credentials as managed identities, configure the following properties in application.yml:
        spring:
          cloud:
            azure:
              credential:
                managed-identity-enabled: true
                client-id: ${AZURE_CLIENT_ID}
              profile:
                tenant-id: ${AZURE_TENANT_ID}
              storage:
                queue:
                  namespace: ${AZURE_SERVICE_BUS_NAMESPACE}
    
    • For credentials as service principal, configure the following properties in application.yml:
        spring:
          cloud:
            azure:
              credential:
                client-id: ${AZURE_CLIENT_ID}
                client-secret: ${AZURE_CLIENT_SECRET}
              profile:
                tenant-id: ${AZURE_TENANT_ID}
              storage:
                queue:
                  namespace: ${AZURE_SERVICE_BUS_NAMESPACE}
    
  2. Create DefaultMessageHandler with the bean of StorageQueueTemplate to send messages to Storage Queue.

    class Demo {
        private static final String STORAGE_QUEUE_NAME = "example";
        private static final String OUTPUT_CHANNEL = "output";
    
        @Bean
        @ServiceActivator(inputChannel = OUTPUT_CHANNEL)
        public MessageHandler messageSender(StorageQueueTemplate storageQueueTemplate) {
            DefaultMessageHandler handler = new DefaultMessageHandler(STORAGE_QUEUE_NAME, storageQueueTemplate);
            handler.setSendCallback(new ListenableFutureCallback<Void>() {
                @Override
                public void onSuccess(Void result) {
                    LOGGER.info("Message was sent successfully.");
                }
    
                @Override
                public void onFailure(Throwable ex) {
                    LOGGER.info("There was an error sending the message.");
                }
            });
            return handler;
        }
    }
    
  3. Create a Message gateway binding with the above message handler via a message channel.

    class Demo {
        @Autowired
        StorageQueueOutboundGateway storageQueueOutboundGateway;
    
        @MessagingGateway(defaultRequestChannel = OUTPUT_CHANNEL)
        public interface StorageQueueOutboundGateway {
            void send(String text);
        }
    }
    
  4. Send messages using the gateway.

    class Demo {
        public void demo() {
            this.storageQueueOutboundGateway.send(message);
        }
    }
    
Receive messages from Azure Storage Queue
  1. Fill the credential configuration options.

  2. Create a bean of message channel as the input channel.

    class Demo {
        private static final String INPUT_CHANNEL = "input";
    
        @Bean
        public MessageChannel input() {
            return new DirectChannel();
        }
    }
    
  3. Create StorageQueueMessageSource with the bean of StorageQueueTemplate to receive messages to Storage Queue.

    class Demo {
        private static final String STORAGE_QUEUE_NAME = "example";
    
        @Bean
        @InboundChannelAdapter(channel = INPUT_CHANNEL, poller = @Poller(fixedDelay = "1000"))
        public StorageQueueMessageSource storageQueueMessageSource(StorageQueueTemplate storageQueueTemplate) {
            return new StorageQueueMessageSource(STORAGE_QUEUE_NAME, storageQueueTemplate);
        }
    }
    
  4. Create a message receiver binding with StorageQueueMessageSource created in the last step via the message channel we created before.

    class Demo {
        @ServiceActivator(inputChannel = INPUT_CHANNEL)
        public void messageReceiver(byte[] payload, @Header(AzureHeaders.CHECKPOINTER) Checkpointer checkpointer) {
            String message = new String(payload);
            LOGGER.info("New message received: '{}'", message);
            checkpointer.success()
                .doOnError(Throwable::printStackTrace)
                .doOnSuccess(t -> LOGGER.info("Message '{}' successfully checkpointed", message))
                .block();
        }
    }
    

Samples

See azure-spring-boot-samples for more details.

Spring Cloud Stream support

Spring Cloud Stream is a framework for building highly scalable event-driven microservices connected with shared messaging systems.

The framework provides a flexible programming model built on already established and familiar Spring idioms and best practices, including support for persistent pub/sub semantics, consumer groups, and stateful partitions.

Current binder implementations include:

Spring Cloud Stream Binder for Azure Event Hubs

Key concepts

The Spring Cloud Stream Binder for Azure Event Hubs provides the binding implementation for the Spring Cloud Stream framework. This implementation uses Spring Integration Event Hubs Channel Adapters at its foundation. From design's perspective, Event Hubs is similar as Kafka. Also, Event Hubs could be accessed via Kafka API. If your project has tight dependency on Kafka API, you can try Events Hub with Kafka API Sample

Consumer group

Event Hubs provides similar support of consumer group as Apache Kafka, but with slight different logic. While Kafka stores all committed offsets in the broker, you have to store offsets of Event Hubs messages being processed manually. Event Hubs SDK provides the function to store such offsets inside Azure Storage.

Partitioning support

Event Hubs provides a similar concept of physical partition as Kafka. But unlike Kafka's auto re-balancing between consumers and partitions, Event Hubs provides a kind of preemptive mode. The storage account acts as a lease to determine which partition is owned by which consumer. When a new consumer starts, it will try to steal some partitions from most heavy-loaded consumers to achieve the workload balancing.

To specify the load balancing strategy, properties of spring.cloud.stream.eventhubs.bindings.<binding-name>.consumer.load-balancing.* are provided. See Consumer properties section for more details.

Batch consumer support

Spring Cloud Azure Stream Event Hubs binder supports Spring Cloud Stream Batch Consumer feature.

To work with the batch-consumer mode, the property of spring.cloud.stream.bindings.<binding-name>.consumer.batch-mode should be set as true. When enabled, an Message of which the payload is a list of batched events will be received and passed to the Consumer function. Each message header is also converted as a list, of which the content is the associated header value parsed from each event. For the communal headers of partition ID, checkpointer and last enqueued properties, they are presented as a single value for the entire batch of events shares the same one. See Event Hubs Message Headers for more details.

Note

The checkpoint header only exists when MANUAL checkpoint mode is used.

Checkpointing of batch consumer supports two modes: BATCH and MANUAL. BATCH mode is an auto checkpointing mode to checkpoint the entire batch of events together once they are received by the binder. MANUAL mode is to checkpoint the events by users. When used, the Checkpointer will be passed into the message header, and users could use it to do checkpointing.

The batch size can be specified by properties of max-size and max-wait-time with prefix as spring.cloud.stream.eventhubs.bindings.<binding-name>.consumer.batch., where max-size is a necessary property while max-wait-time is optional. See Consumer properties section for more details.

Dependency setup

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-stream-binder-eventhubs</artifactId>
</dependency>

Alternatively, you can also use the Spring Cloud Azure Stream Event Hubs Starter, as shown in the following example for Maven:

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-stream-eventhubs</artifactId>
</dependency>

Configuration

The binder provides the following 3 parts of configuration options:

Connection configuration properties

This section contains the configuration options used for connecting to Azure Event Hubs.

Note

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, refer to Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.

Connection configurable properties of spring-cloud-azure-stream-binder-eventhubs:

Property Type Description
spring.cloud.azure.eventhubs.enabled boolean Whether an Azure Event Hubs is enabled.
spring.cloud.azure.eventhubs.connection-string String Event Hubs Namespace connection string value.
spring.cloud.azure.eventhubs.namespace String Event Hubs Namespace value, which is the prefix of the FQDN. A FQDN should be composed of NamespaceName.DomainName
spring.cloud.azure.eventhubs.domain-name String Domain name of an Azure Event Hubs Namespace value.
spring.cloud.azure.eventhubs.custom-endpoint-address String Custom Endpoint address.

Tip

Common Azure Service SDK configuration options are configurable for the Spring Cloud Azure Stream Event Hubs binder as well. The supported configuration options are introduced in the Configuration page, and could be configured with either the unified prefix spring.cloud.azure. or the prefix of spring.cloud.azure.eventhubs..

The binder also supports Spring Could Azure Resource Manager by default. To learn about how to retrieve the connection string with security principals that are not granted with Data related roles, refer to the resource manager example for details.

Checkpoint configuration properties

This section contains the configuration options for the Storage Blobs service, which is used for persisting partition ownership and checkpoint information.

Note

From version 4.0.0, when the property of spring.cloud.azure.eventhubs.processor.checkpoint-store.create-container-if-not-exists is not enabled manually, no Storage container will be created automatically with the name from spring.cloud.stream.bindings.binding-name.destination.

Checkpointing configurable properties of spring-cloud-azure-stream-binder-eventhubs:

Property Type Description
spring.cloud.azure.eventhubs.processor.checkpoint-store.create-container-if-not-exists Boolean Whether to allow creating containers if not exists.
spring.cloud.azure.eventhubs.processor.checkpoint-store.account-name String Name for the storage account.
spring.cloud.azure.eventhubs.processor.checkpoint-store.account-key String Storage account access key.
spring.cloud.azure.eventhubs.processor.checkpoint-store.container-name String Storage container name.

Tip

Common Azure Service SDK configuration options are configurable for Storage Blob checkpoint store as well. The supported configuration options are introduced in the Configuration page, and could be configured with either the unified prefix spring.cloud.azure. or the prefix of spring.cloud.azure.eventhubs.processor.checkpoint-store.

Azure Event Hubs Binding configuration properties

The following options are divided into four sections: Consumer Properties, Advanced Consumer Configurations, Producer Properties and Advanced Producer Configurations.

Consumer properties

These properties are exposed via EventHubsConsumerProperties.

Consumer configurable properties of spring-cloud-azure-stream-binder-eventhubs:

Property Type Description
spring.cloud.stream.eventhubs.bindings.binding-name.consumer.checkpoint.mode CheckpointMode Checkpoint mode used when consumer decide how to checkpoint message
spring.cloud.stream.eventhubs.bindings.binding-name.consumer.checkpoint.count Integer Decides the amount of message for each partition to do one checkpoint. Will take effect only when PARTITION_COUNT checkpoint mode is used.
spring.cloud.stream.eventhubs.bindings.binding-name.consumer.checkpoint.interval Duration Decides the time interval to do one checkpoint. Will take effect only when TIME checkpoint mode is used.
spring.cloud.stream.eventhubs.bindings.<binding-name.consumer.batch.max-size Integer The maximum number of events in a batch. Required for the batch-consumer mode.
spring.cloud.stream.eventhubs.bindings.binding-name.consumer.batch.max-wait-time Duration The maximum time duration for batch consuming. Will take effect only when the batch-consumer mode is enabled and is optional.
spring.cloud.stream.eventhubs.bindings.binding-name.consumer.load-balancing.update-interval Duration The interval time duration for updating.
spring.cloud.stream.eventhubs.bindings.binding-name.consumer.load-balancing.strategy LoadBalancingStrategy The load balancing strategy.
spring.cloud.stream.eventhubs.bindings.binding-name.consumer.load-balancing.partition-ownership-expiration-interval Duration The time duration after which the ownership of partition expires.
spring.cloud.stream.eventhubs.bindings.binding-name.consumer.track-last-enqueued-event-properties Boolean Whether the event processor should request information on the last enqueued event on its associated partition, and track that information as events are received.
spring.cloud.stream.eventhubs.bindings.binding-name.consumer.prefetch-count Integer The count used by the consumer to control the number of events the Event Hub consumer will actively receive and queue locally.
spring.cloud.stream.eventhubs.bindings.binding-name.consumer.initial-partition-event-position Map with the key as the partition ID, and values of StartPositionProperties The map containing the event position to use for each partition if a checkpoint for the partition does not exist in checkpoint store. This map is keyed off of the partition ID.

Note

The initial-partition-event-position configuration accepts a map to specify the initial position for each event hub. Thus, its key is the partition ID, and the value is of StartPositionProperties which includes properties of offset, sequence number, enqueued date time and whether inclusive. For example, you can set it as

spring:
  cloud:
    stream:
      eventhubs:
        bindings:
          <binding-name>:
            consumer:
              initial-partition-event-position:
                0:
                  offset: earliest
                1:
                  sequence-number: 100
                2:
                  enqueued-date-time: 2022-01-12T13:32:47.650005Z
                4:
                  inclusive: false
Advanced consumer configuration

The above connection, checkpoint and common Azure SDK client configuration are supported to be customized for each binder consumer, which can be configured with the prefix spring.cloud.stream.eventhubs.bindings.<binding-name>.consumer..

Producer properties

These properties are exposed via EventHubsProducerProperties.

Producer configurable properties of spring-cloud-azure-stream-binder-eventhubs:

Property Type Description
spring.cloud.stream.eventhubs.bindings.binding-name.producer.sync boolean The switch flag for sync of producer. If true, the producer will wait for a response after a send operation.
spring.cloud.stream.eventhubs.bindings.binding-name.producer.send-timeout long The amount of time to wait for a response after a send operation. Will take effect only when a sync producer is enabled.
Advanced producer configuration

The above connection and common Azure SDK client configuration are supported to be customized for each binder producer, which can be configured with the prefix spring.cloud.stream.eventhubs.bindings.<binding-name>.producer..

Basic usage

Sending and receiving messages from/to Event Hubs
  1. Fill the configuration options with credential information.

    • For credentials as connection string, configure the following properties in application.yml:
    spring:
      cloud:
        azure:
          eventhubs:
            connection-string: ${EVENTHUB_NAMESPACE_CONNECTION_STRING}
            processor:
              checkpoint-store:
                container-name: ${CHECKPOINT_CONTAINER}
                account-name: ${CHECKPOINT_STORAGE_ACCOUNT}
                account-key: ${CHECKPOINT_ACCESS_KEY}
        stream:
          function:
            definition: consume;supply
          bindings:
            consume-in-0:
              destination: ${EVENTHUB_NAME}
              group: ${CONSUMER_GROUP}
            supply-out-0:
              destination: ${THE_SAME_EVENTHUB_NAME_AS_ABOVE}
          eventhubs:
            bindings:
              consume-in-0:
                consumer:
                  checkpoint:
                    mode: MANUAL
    
    • For credentials as service principal, configure the following properties in application.yml:
    spring:
      cloud:
        azure:
          credential:
            client-id: ${AZURE_CLIENT_ID}
            client-secret: ${AZURE_CLIENT_SECRET}
          profile:
            tenant-id: ${AZURE_TENANT_ID}
          eventhubs:
            namespace: ${EVENTHUB_NAMESPACE}
            processor:
              checkpoint-store:
                container-name: ${CONTAINER_NAME}
                account-name: ${ACCOUNT_NAME}
        stream:
          function:
            definition: consume;supply
          bindings:
            consume-in-0:
              destination: ${EVENTHUB_NAME}
              group: ${CONSUMER_GROUP}
            supply-out-0:
              destination: ${THE_SAME_EVENTHUB_NAME_AS_ABOVE}
          eventhubs:
            bindings:
              consume-in-0:
                consumer:
                  checkpoint:
                    mode: MANUAL
    
    • For credentials as managed identites, configure the following properties in application.yml:
    spring:
      cloud:
        azure:
          credential:
            managed-identity-enabled: true
            client-id: ${AZURE_MANAGED_IDENTITY_CLIENT_ID} # Only needed when using a user-assigned managed identity
          eventhubs:
            namespace: ${EVENTHUB_NAMESPACE}
            processor:
              checkpoint-store:
                container-name: ${CONTAINER_NAME}
                account-name: ${ACCOUNT_NAME}
        stream:
          function:
            definition: consume;supply
          bindings:
            consume-in-0:
              destination: ${EVENTHUB_NAME}
              group: ${CONSUMER_GROUP}
            supply-out-0:
              destination: ${THE_SAME_EVENTHUB_NAME_AS_ABOVE}
    
          eventhubs:
            bindings:
              consume-in-0:
                consumer:
                  checkpoint:
                    mode: MANUAL
    
  2. Define supplier and consumer.

    @Bean
    public Consumer<Message<String>> consume() {
        return message -> {
            Checkpointer checkpointer = (Checkpointer) message.getHeaders().get(CHECKPOINTER);
            LOGGER.info("New message received: '{}', partition key: {}, sequence number: {}, offset: {}, enqueued time: {}",
                    message.getPayload(),
                    message.getHeaders().get(EventHubsHeaders.PARTITION_KEY),
                    message.getHeaders().get(EventHubsHeaders.SEQUENCE_NUMBER),
                    message.getHeaders().get(EventHubsHeaders.OFFSET),
                    message.getHeaders().get(EventHubsHeaders.ENQUEUED_TIME)
            );
    
            checkpointer.success()
                    .doOnSuccess(success -> LOGGER.info("Message '{}' successfully checkpointed", message.getPayload()))
                    .doOnError(error -> LOGGER.error("Exception found", error))
                    .block();
        };
    }
    
    @Bean
    public Supplier<Message<String>> supply() {
        return () -> {
            LOGGER.info("Sending message, sequence " + i);
            return MessageBuilder.withPayload("Hello world, " + i++).build();
        };
    }
    
Partitioning support

A PartitionSupplier with user-provided partition information will be created to configure the partition information about the message to be sent, the following is the process of obtaining different priorities of the partition ID and key:

Flowchart showing the partitioning support process. )

Batch consumer support
  1. Fill the batch configuration options

    spring:
      cloud:
        stream:
          function:
            definition: consume
          bindings:
            consume-in-0:
              destination: ${AZURE_EVENTHUB_NAME}
              group: ${AZURE_EVENTHUB_CONSUMER_GROUP}
              consumer:
                batch-mode: true
          eventhubs:
            bindings:
              consume-in-0:
                consumer:
                  batch:
                    max-batch-size: 10 # Required for batch-consumer mode
                    max-wait-time: 1m # Optional, the default value is null
                  checkpoint:
                    mode: BATCH # or MANUAL as needed
    
  2. Define supplier and consumer.

    For checkpointing mode as BATCH, you can use the following code to send messages and consume in batches.

    @Bean
    public Consumer<Message<List<String>>> consume() {
        return message -> {
                for (int i = 0; i < message.getPayload().size(); i++) {
                    LOGGER.info("New message received: '{}', partition key: {}, sequence number: {}, offset: {}, enqueued time: {}",
                            message.getPayload().get(i),
                            ((List<Object>) message.getHeaders().get(EventHubsHeaders.BATCH_CONVERTED_PARTITION_KEY)).get(i),
                            ((List<Object>) message.getHeaders().get(EventHubsHeaders.BATCH_CONVERTED_SEQUENCE_NUMBER)).get(i),
                            ((List<Object>) message.getHeaders().get(EventHubsHeaders.BATCH_CONVERTED_OFFSET)).get(i),
                            ((List<Object>) message.getHeaders().get(EventHubsHeaders.BATCH_CONVERTED_ENQUEUED_TIME)).get(i));
                }
    
            };
    }
    
    @Bean
    public Supplier<Message<String>> supply() {
        return () -> {
            LOGGER.info("Sending message, sequence " + i);
            return MessageBuilder.withPayload("\"test"+ i++ +"\"").build();
        };
    }
    

    For checkpointing mode as MANUAL, you can use the following code to send messages and consume/checkpoint in batches.

    @Bean
    public Consumer<Message<List<String>>> consume() {
        return message -> {
            for (int i = 0; i < message.getPayload().size(); i++) {
                LOGGER.info("New message received: '{}', partition key: {}, sequence number: {}, offset: {}, enqueued time: {}",
                    message.getPayload().get(i),
                    ((List<Object>) message.getHeaders().get(EventHubHeaders.BATCH_CONVERTED_PARTITION_KEY)).get(i),
                    ((List<Object>) message.getHeaders().get(EventHubHeaders.BATCH_CONVERTED_SEQUENCE_NUMBER)).get(i),
                    ((List<Object>) message.getHeaders().get(EventHubHeaders.BATCH_CONVERTED_OFFSET)).get(i),
                    ((List<Object>) message.getHeaders().get(EventHubHeaders.BATCH_CONVERTED_ENQUEUED_TIME)).get(i));
            }
    
            Checkpointer checkpointer = (Checkpointer) message.getHeaders().get(CHECKPOINTER);
            checkpointer.success()
                        .doOnSuccess(success -> LOGGER.info("Message '{}' successfully checkpointed", message.getPayload()))
                        .doOnError(error -> LOGGER.error("Exception found", error))
                        .block();
        };
    }
    
    @Bean
    public Supplier<Message<String>> supply() {
        return () -> {
            LOGGER.info("Sending message, sequence " + i);
            return MessageBuilder.withPayload("\"test"+ i++ +"\"").build();
        };
    }
    

Note

In the batch-consuming mode, the default content type of Spring Cloud Stream binder is application/json, so make sure the message payload is aligned with the content type. For example, when using the default content type of application/json to receive messages with String payload, the payload should be JSON String, surrounded with double quotes for the original String text. While for text/plain content type, it can be a String object directly. For more details, refer to the official doc of Spring Cloud Stream Content Type Negotiation.

Error channels
  • Consumer error channel

This channel is open by default, you can handle the error message in this way:

// Replace destination with spring.cloud.stream.bindings.input.destination
// Replace group with spring.cloud.stream.bindings.input.group
@ServiceActivator(inputChannel = "{destination}.{group}.errors")
public void consumerError(Message<?> message) {
    LOGGER.error("Handling customer ERROR: " + message);
}
  • Producer error channel

This channel is not open by default. You need to add a configuration in your application.properties to enable it, like this:

spring.cloud.stream.default.producer.errorChannelEnabled=true

You can handle the error message in this way:

// Replace destination with spring.cloud.stream.bindings.output.destination
@ServiceActivator(inputChannel = "{destination}.errors")
public void producerError(Message<?> message) {
    LOGGER.error("Handling Producer ERROR: " + message);
}
  • Global default error channel

A global error channel called "errorChannel" is created by default Spring Integration, which allows users to subscribe many endpoints to it.

@ServiceActivator(inputChannel = "errorChannel")
public void producerError(Message<?> message) {
    LOGGER.error("Handling ERROR: " + message);
}
Event Hubs message headers

See the Event Hubs message headers for the basic message headers supported.

Multiple binder support

Connection to multiple Event Hubs namespaces is also supported by using multiple binders.This sample takes connection string as example. Credentials of service principals and managed identities are also supported, users can set related properties in each binder's environment settings.

  1. To use multiple binders of EventHubs, we need to configure the following properties in application.yml

    spring:
      cloud:
        stream:
          function:
            definition: consume1;supply1;consume2;supply2
          bindings:
            consume1-in-0:
              destination: ${EVENTHUB_NAME_01}
              group: ${CONSUMER_GROUP_01}
            supply1-out-0:
              destination: ${THE_SAME_EVENTHUB_NAME_01_AS_ABOVE}
            consume2-in-0:
              binder: eventhub-2
              destination: ${EVENTHUB_NAME_02}
              group: ${CONSUMER_GROUP_02}
            supply2-out-0:
              binder: eventhub-2
              destination: ${THE_SAME_EVENTHUB_NAME_02_AS_ABOVE}
          binders:
            eventhub-1:
              type: eventhubs
              default-candidate: true
              environment:
                spring:
                  cloud:
                    azure:
                      eventhubs:
                        connection-string: ${EVENTHUB_NAMESPACE_01_CONNECTION_STRING}
                        processor:
                          checkpoint-store:
                            container-name: ${CHECKPOINT_CONTAINER_01}
                            account-name: ${CHECKPOINT_STORAGE_ACCOUNT}
                            account-key: ${CHECKPOINT_ACCESS_KEY}
            eventhub-2:
              type: eventhubs
              default-candidate: false
              environment:
                spring:
                  cloud:
                    azure:
                      eventhubs:
                        connection-string: ${EVENTHUB_NAMESPACE_02_CONNECTION_STRING}
                        processor:
                          checkpoint-store:
                            container-name: ${CHECKPOINT_CONTAINER_02}
                            account-name: ${CHECKPOINT_STORAGE_ACCOUNT}
                            account-key: ${CHECKPOINT_ACCESS_KEY}
          eventhubs:
            bindings:
              consume1-in-0:
                consumer:
                  checkpoint:
                    mode: MANUAL
              consume2-in-0:
                consumer:
                  checkpoint:
                    mode: MANUAL
          poller:
            initial-delay: 0
            fixed-delay: 1000
    
  2. we need define two suppliers and two consumers

    @Bean
    public Supplier<Message<String>> supply1() {
        return () -> {
            LOGGER.info("Sending message1, sequence1 " + i);
            return MessageBuilder.withPayload("Hello world1, " + i++).build();
        };
    }
    
    @Bean
    public Supplier<Message<String>> supply2() {
        return () -> {
            LOGGER.info("Sending message2, sequence2 " + j);
            return MessageBuilder.withPayload("Hello world2, " + j++).build();
        };
    }
    
    @Bean
    public Consumer<Message<String>> consume1() {
        return message -> {
            Checkpointer checkpointer = (Checkpointer) message.getHeaders().get(CHECKPOINTER);
            LOGGER.info("New message1 received: '{}'", message);
            checkpointer.success()
                    .doOnSuccess(success -> LOGGER.info("Message1 '{}' successfully checkpointed", message))
                    .doOnError(error -> LOGGER.error("Exception found", error))
                    .block();
        };
    }
    
    @Bean
    public Consumer<Message<String>> consume2() {
        return message -> {
            Checkpointer checkpointer = (Checkpointer) message.getHeaders().get(CHECKPOINTER);
            LOGGER.info("New message2 received: '{}'", message);
            checkpointer.success()
                    .doOnSuccess(success -> LOGGER.info("Message2 '{}' successfully checkpointed", message))
                    .doOnError(error -> LOGGER.error("Exception found", error))
                    .block();
        };
    }
    
Resource provision

Event Hubs binder supports provisioning of event hub and consumer group, users could use the following properties to enable provisioning.

spring:
  cloud:
    azure:
      credential:
        tenant-id: ${AZURE_TENANT_ID}
      profile:
        subscription-id: ${AZURE_SUBSCRIPTION_ID}
      eventhubs:
        resource:
          resource-group: ${AZURE_EVENTHUBS_RESOURECE_GROUP}

Samples

See azure-spring-boot-samples for more details.

Spring Cloud Stream Binder for Azure Service Bus

Key concepts

The Spring Cloud Stream Binder for Azure Service Bus provides the binding implementation for the Spring Cloud Stream Framework. This implementation uses Spring Integration Service Bus Channel Adapters at its foundation.

Scheduled message

This binder supports submitting messages to a topic for delayed processing. Users can send scheduled messages with header x-delay expressing in milliseconds a delay time for the message. The message will be delivered to the respective topics after x-delay milliseconds.

Consumer group

Service Bus Topic provides similar support of consumer group as Apache Kafka, but with slight different logic. This binder relies on Subscription of a topic to act as a consumer group.

Dependency setup

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-stream-binder-servicebus</artifactId>
</dependency>

Alternatively, you can also use the Spring Cloud Azure Stream Service Bus Starter, as shown in the following example for Maven:

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-stream-servicebus</artifactId>
</dependency>

Configuration

The binder provides the following 2 parts of configuration options:

Connection configuration properties

This section contains the configuration options used for connecting to Azure Service Bus.

Note

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, refer to Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.

Connection configurable properties of spring-cloud-azure-stream-binder-servicebus:

Property Type Description
spring.cloud.azure.servicebus.enabled boolean Whether an Azure Service Bus is enabled.
spring.cloud.azure.servicebus.connection-string String Service Bus Namespace connection string value.
spring.cloud.azure.servicebus.namespace String Service Bus Namespace value, which is the prefix of the FQDN. A FQDN should be composed of NamespaceName.DomainName
spring.cloud.azure.servicebus.domain-name String Domain name of an Azure Service Bus Namespace value.

Note

Common Azure Service SDK configuration options are configurable for the Spring Cloud Azure Stream Service Bus binder as well. The supported configuration options are introduced in the Configuration page, and could be configured with either the unified prefix spring.cloud.azure. or the prefix of spring.cloud.azure.servicebus..

The binder also supports Spring Could Azure Resource Manager by default. To learn about how to retrieve the connection string with security principals that are not granted with Data related roles, refer to the resource manager example for details.

Azure Service Bus binding configuration properties

The following options are divided into four sections: Consumer Properties, Advanced Consumer Configurations, Producer Properties and Advanced Producer Configurations.

Consumer properties

These properties are exposed via ServiceBusConsumerProperties.

Consumer configurable properties of spring-cloud-azure-stream-binder-servicebus:

Property Type Default Description
spring.cloud.stream.servicebus.bindings.binding-name.consumer.requeue-rejected boolean false If the failed messages are routed to the DLQ.
spring.cloud.stream.servicebus.bindings.binding-name.consumer.max-concurrent-calls Integer 1 Max concurrent messages that the Service Bus processor client should process.
spring.cloud.stream.servicebus.bindings.binding-name.consumer.max-concurrent-sessions Integer null Maximum number of concurrent sessions to process at any given time.
spring.cloud.stream.servicebus.bindings.binding-name.consumer.session-enabled Boolean null Whether session is enabled.
spring.cloud.stream.servicebus.bindings.binding-name.consumer.prefetch-count Integer 0 The prefetch count of the Service Bus processor client.
spring.cloud.stream.servicebus.bindings.binding-name.consumer.sub-queue SubQueue none The type of the sub queue to connect to.
spring.cloud.stream.servicebus.bindings.binding-name.consumer.max-auto-lock-renew-duration Duration 5m The amount of time to continue auto-renewing the lock.
spring.cloud.stream.servicebus.bindings.binding-name.consumer.receive-mode ServiceBusReceiveMode peek_lock The receive mode of the Service Bus processor client.
spring.cloud.stream.servicebus.bindings.binding-name.consumer.auto-complete Boolean true Whether to settle messages automatically. If set as false, a message header of Checkpointer will be added to enable developers to settle messages manually.
Advanced consumer configuration

The above connection and common Azure SDK client configuration are supported to be customized for each binder consumer, which can be configured with the prefix spring.cloud.stream.servicebus.bindings.<binding-name>.consumer..

Producer properties

These properties are exposed via ServiceBusProducerProperties.

Producer configurable properties of spring-cloud-azure-stream-binder-servicebus:

Property Type Default Description
spring.cloud.stream.servicebus.bindings.binding-name.producer.sync boolean false Switch flag for sync of producer.
spring.cloud.stream.servicebus.bindings.binding-name.producer.send-timeout long 10000 Timeout value for sending of producer.
spring.cloud.stream.servicebus.bindings.binding-name.producer.entity-type ServiceBusEntityType null Service Bus entity type of the producer, required for the binding producer.

Important

When using the binding producer, property of spring.cloud.stream.servicebus.bindings.<binding-name>.producer.entity-type is required to be configured.

Advanced producer configuration

The above connection and common Azure SDK client configuration are supported to be customized for each binder producer, which can be configured with the prefix spring.cloud.stream.servicebus.bindings.<binding-name>.producer..

Basic usage

Sending and receiving messages from/to Service Bus
  1. Fill the configuration options with credential information.

    • For credentials as connection string, configure the following properties in application.yml:
        spring:
          cloud:
            azure:
              servicebus:
                connection-string: ${SERVICEBUS_NAMESPACE_CONNECTION_STRING}
            stream:
              function:
                definition: consume;supply
              bindings:
                consume-in-0:
                  destination: ${SERVICEBUS_ENTITY_NAME}
                  # If you use Service Bus Topic, add the following configuration
                  # group: ${SUBSCRIPTION_NAME}
                supply-out-0:
                  destination: ${SERVICEBUS_ENTITY_NAME_SAME_AS_ABOVE}
              servicebus:
                bindings:
                  consume-in-0:
                    consumer:
                      auto-complete: false
                  supply-out-0:
                    producer:
                      entity-type: queue # set as "topic" if you use Service Bus Topic
    
    • For credentials as service principal, configure the following properties in application.yml:
        spring:
          cloud:
            azure:
              credential:
                client-id: ${AZURE_CLIENT_ID}
                client-secret: ${AZURE_CLIENT_SECRET}
              profile:
                tenant-id: ${AZURE_TENANT_ID}
              servicebus:
                namespace: ${SERVICEBUS_NAMESPACE}
            stream:
              function:
                definition: consume;supply
              bindings:
                consume-in-0:
                  destination: ${SERVICEBUS_ENTITY_NAME}
                  # If you use Service Bus Topic, add the following configuration
                  # group: ${SUBSCRIPTION_NAME}
                supply-out-0:
                  destination: ${SERVICEBUS_ENTITY_NAME_SAME_AS_ABOVE}
              servicebus:
                bindings:
                  consume-in-0:
                    consumer:
                      auto-complete: false
                  supply-out-0:
                    producer:
                      entity-type: queue # set as "topic" if you use Service Bus Topic
    
    • For credentials as managed identities, configure the following properties in application.yml:
        spring:
          cloud:
            azure:
              credential:
                managed-identity-enabled: true
                client-id: ${MANAGED_IDENTITY_CLIENT_ID} # Only needed when using a user-assigned managed identity
              servicebus:
                namespace: ${SERVICEBUS_NAMESPACE}
            stream:
              function:
                definition: consume;supply
              bindings:
                consume-in-0:
                  destination: ${SERVICEBUS_ENTITY_NAME}
                  # If you use Service Bus Topic, add the following configuration
                  # group: ${SUBSCRIPTION_NAME}
                supply-out-0:
                  destination: ${SERVICEBUS_ENTITY_NAME_SAME_AS_ABOVE}
              servicebus:
                bindings:
                  consume-in-0:
                    consumer:
                      auto-complete: false
                  supply-out-0:
                    producer:
                      entity-type: queue # set as "topic" if you use Service Bus Topic
    
  2. Define supplier and consumer.

    @Bean
    public Consumer<Message<String>> consume() {
        return message -> {
            Checkpointer checkpointer = (Checkpointer) message.getHeaders().get(CHECKPOINTER);
            LOGGER.info("New message received: '{}'", message.getPayload());
    
            checkpointer.success()
                    .doOnSuccess(success -> LOGGER.info("Message '{}' successfully checkpointed", message.getPayload()))
                    .doOnError(error -> LOGGER.error("Exception found", error))
                    .block();
        };
    }
    
    @Bean
    public Supplier<Message<String>> supply() {
        return () -> {
            LOGGER.info("Sending message, sequence " + i);
            return MessageBuilder.withPayload("Hello world, " + i++).build();
        };
    }
    
Partition key support

The binder supports Service Bus partitioning by allowing setting partition key and session ID in the message header. This section introduces how to set partition key for messages.

Spring Cloud Stream provides a partition key SpEL expression property spring.cloud.stream.bindings.<binding-name>.producer.partition-key-expression. For example, setting this property as "'partitionKey-' + headers[<message-header-key>]" and add a header called message-header-key. Spring Cloud Stream will use the value for this header when evaluating the above expression to assign a partition key. Here is an example producer code:

@Bean
public Supplier<Message<String>> generate() {
    return () -> {
        String value = "random payload";
        return MessageBuilder.withPayload(value)
            .setHeader("<message-header-key>", value.length() % 4)
            .build();
    };
}
Session support

The binder supports message sessions of Service Bus. Session ID of a message could be set via the message header.

@Bean
public Supplier<Message<String>> generate() {
    return () -> {
        String value = "random payload";
        return MessageBuilder.withPayload(value)
            .setHeader(ServiceBusMessageHeaders.SESSION_ID, "Customize session ID")
            .build();
    };
}

Note

According to Service Bus partitioning, session ID has higher priority than partition key. So when both of ServiceBusMessageHeaders#SESSION_ID and ServiceBusMessageHeaders#PARTITION_KEY (or AzureHeaders#PARTITION_KEY) headers are set, the value of the session ID will eventually be used to overwrite the value of the partition key.

Error channels
  • Consumer error channel

This channel is open by default, and a default consumer error channel handler is used to send failed messages to the dead-letter queue when spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.requeue-rejected is enabled, otherwise the failed messages will be abandoned.

To customize the consumer error channel handler, you can register you own error handler to the related consumer error channel in this way:

// Replace destination with spring.cloud.stream.bindings.input.destination
// Replace group with spring.cloud.stream.bindings.input.group
@ServiceActivator(inputChannel = "{destination}.{group}.errors")
public void consumerError(Message<?> message) {
    LOGGER.error("Handling customer ERROR: " + message);
}
  • Producer error channel

This channel is not open by default. You need to add a configuration in your application.properties to enable it, like this:

spring.cloud.stream.default.producer.errorChannelEnabled=true

You can handle the error message in this way:

// Replace destination with spring.cloud.stream.bindings.output.destination
@ServiceActivator(inputChannel = "{destination}.errors")
public void producerError(Message<?> message) {
    LOGGER.error("Handling Producer ERROR: " + message);
}
  • Global default error channel

A global error channel called "errorChannel" is created by default Spring Integration, which allows users to subscribe many endpoints to it.

@ServiceActivator(inputChannel = "errorChannel")
public void producerError(Message<?> message) {
    LOGGER.error("Handling ERROR: " + message);
}
Service Bus message headers

See the Service Bus message headers for the basic message headers supported.

Note

When setting the partiton key, the priority of message header is higher than Spring Cloud Stream property. So spring.cloud.stream.bindings.<binding-name>.producer.partition-key-expression will take effect only when none of the headers of ServiceBusMessageHeaders#SESSION_ID, ServiceBusMessageHeaders#PARTITION_KEY, AzureHeaders#PARTITION_KEY is configured.

Multiple Binder support

Connection to multiple Service Bus namespaces is also supported by using multiple binders. This sample takes connection string as example. Credentials of service principals and managed identities are also supported, users can set related properties in each binder's environment settings.

  1. To use multiple binders of ServiceBus, we need to configure the following properties in application.yml

    spring:
      cloud:
        stream:
          function:
            definition: consume1;supply1;consume2;supply2
          bindings:
            consume1-in-0:
              destination: ${SERVICEBUS_TOPIC_NAME}
              group: ${SUBSCRIPTION_NAME}
            supply1-out-0:
              destination: ${SERVICEBUS_TOPIC_NAME_SAME_AS_ABOVE}
            consume2-in-0:
              binder: servicebus-2
              destination: ${SERVICEBUS_QUEUE_NAME}
            supply2-out-0:
              binder: servicebus-2
              destination: ${SERVICEBUS_QUEUE_NAME_SAME_AS_ABOVE}
          binders:
            servicebus-1:
              type: servicebus
              default-candidate: true
              environment:
                spring:
                  cloud:
                    azure:
                      servicebus:
                        connection-string: ${SERVICEBUS_NAMESPACE_01_CONNECTION_STRING}
            servicebus-2:
              type: servicebus
              default-candidate: false
              environment:
                spring:
                  cloud:
                    azure:
                      servicebus:
                        connection-string: ${SERVICEBUS_NAMESPACE_02_CONNECTION_STRING}
          servicebus:
            bindings:
              consume1-in-0:
                consumer:
                  auto-complete: false
              supply1-out-0:
                producer:
                  entity-type: topic
              consume2-in-0:
                consumer:
                  auto-complete: false
              supply2-out-0:
                producer:
                  entity-type: queue
          poller:
            initial-delay: 0
            fixed-delay: 1000
    
  2. we need define two suppliers and two consumers

    @Bean
    public Supplier<Message<String>> supply1() {
        return () -> {
            LOGGER.info("Sending message1, sequence1 " + i);
            return MessageBuilder.withPayload("Hello world1, " + i++).build();
        };
    }
    
    @Bean
    public Supplier<Message<String>> supply2() {
        return () -> {
            LOGGER.info("Sending message2, sequence2 " + j);
            return MessageBuilder.withPayload("Hello world2, " + j++).build();
        };
    }
    
    @Bean
    public Consumer<Message<String>> consume1() {
        return message -> {
            Checkpointer checkpointer = (Checkpointer) message.getHeaders().get(CHECKPOINTER);
            LOGGER.info("New message1 received: '{}'", message);
            checkpointer.success()
                    .doOnSuccess(s -> LOGGER.info("Message '{}' successfully checkpointed", message.getPayload()))
                    .doOnError(e -> LOGGER.error("Error found", e))
                    .block();
        };
    }
    
    @Bean
    public Consumer<Message<String>> consume2() {
        return message -> {
            Checkpointer checkpointer = (Checkpointer) message.getHeaders().get(CHECKPOINTER);
            LOGGER.info("New message2 received: '{}'", message);
            checkpointer.success()
                    .doOnSuccess(s -> LOGGER.info("Message '{}' successfully checkpointed", message.getPayload()))
                    .doOnError(e -> LOGGER.error("Error found", e))
                    .block();
        };
    
    }
    
Resource provision

Service bus binder supports provisioning of queue, topic and subscription, users could use the following properties to enable provisioning.

spring:
  cloud:
    azure:
      credential:
        tenant-id: ${AZURE_TENANT_ID}
      profile:
        subscription-id: ${AZURE_SUBSCRIPTION_ID}
      servicebus:
        resource:
          resource-group: ${AZURE_SERVICEBUS_RESOURECE_GROUP}
    stream:
      servicebus:
        bindings:
          <binding-name>:
            consumer:
              entity-type: ${SERVICEBUS_CONSUMER_ENTITY_TYPE}

Samples

See azure-spring-boot-samples for more details.

Spring JMS support

To use Azure Service Bus by the JMS API integrated into the Spring JMS framework. Azure Service Bus connection string have to be provided which is to be parsed into the login username, password and remote URI for the AMQP broker.

Dependency setup

Adding the following dependencies if you want to migrate your Spring JMS application to use Azure Service Bus.

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-servicebus-jms</artifactId>
</dependency>

Configuration

Configurable properties when using Spring JMS support:

Property Description
spring.jms.servicebus.connection-string Azure Service Bus connection string. Should be provided when want to provide the connection string directly.
spring.jms.servicebus.topic-client-id JMS client ID. Only works for the bean of topicJmsListenerContainerFactory.
spring.jms.servicebus.idle-timeout The duration for idle.
spring.jms.servicebus.pricing-tier The Azure Service Bus Price Tier.
spring.jms.servicebus.listener.reply-pub-sub-domain Whether the reply destination type is topic.
spring.jms.servicebus.listener.phase Specify the phase in which this container should be started and stopped.
spring.jms.servicebus.listener.reply-qos-settings Configure the QosSettings to use when sending a reply.
spring.jms.servicebus.listener.subscription-durable Whether to make the subscription durable. Only works for the bean of topicJmsListenerContainerFactory.
spring.jms.servicebus.listener.subscription-shared Whether to make the subscription shared. Only works for the bean of topicJmsListenerContainerFactory.
spring.jms.servicebus.password Login password of the AMQP broker
spring.jms.servicebus.pool.block-if-full Whether to block when a connection is requested and the pool is full.
spring.jms.servicebus.pool.block-if-full-timeout Blocking period before throwing an exception if the pool is still full.
spring.jms.servicebus.pool.enabled Whether a JmsPoolConnectionFactory should be created, instead of a regularConnectionFactory.
spring.jms.servicebus.pool.idle-timeout Connection idle timeout.
spring.jms.servicebus.pool.max-connections Maximum number of pooled connections.
spring.jms.servicebus.pool.max-sessions-per-connection Maximum number of pooled sessions per connection in the pool.
spring.jms.servicebus.pool.time-between-expiration-check Time to sleep between runs of the idle connection eviction thread.
spring.jms.servicebus.pool.use-anonymous-producers Whether to use only one anonymous "MessageProducer" instance.
spring.jms.servicebus.prefetch-policy.all Fallback value for prefetch option in this Service Bus namespace.
spring.jms.servicebus.prefetch-policy.durable-topic-prefetch The number of prefetch for durable topic.
spring.jms.servicebus.prefetch-policy.queue-browser-prefetch The number of prefetch for queue browser.
spring.jms.servicebus.prefetch-policy.queue-prefetch The number of prefetch for queue.
spring.jms.servicebus.prefetch-policy.topic-prefetch The number of prefetch for topic.
spring.jms.servicebus.remote-url URL of the AMQP broker.
spring.jms.servicebus.username Login user of the AMQP broker.

Note

Spring JMS general configuration is omitted for short. See Spring JMS Document for more details.

Basic usage

Use Service Bus connection String

The simplest way to connect to Service Bus for Spring JMS application is with the connection string.

Add the following properties and you are good to go.

spring:
  jms:
    servicebus:
      connection-string: ${AZURE_SERVICEBUS_CONNECTION_STRING}
      pricing-tier: ${PRICING_TIER}

Note

The default enabled ConnectionFactory is the CachingConnectionFactory which adds Session caching as well MessageProducer caching. If you want to activate the connection pooling featured one of JmsPoolConnectionFactory, the property of spring.jms.servicebus.pool.enabled should be specified true. You can find other pooling configuration options (properties with prefix spring.jms.servicebus.pool.) from the above Configuration section.

Samples

See azure-spring-boot-samples for more details.

Spring Native support

Spring Native provides support for compiling Spring Boot applications to native executables using the GraalVM native-image compiler. The native images will bring many advantages, such as instant startup, instant peak performance, and reduced memory consumption. Some Spring Cloud Azure features can also benefit from the Spring Native support. The goal is that Spring Cloud Azure applications can be built as native images without any code modification. For more information, see the Spring Native documentation.

Support

Spring Cloud Azure has been validated against GraalVM and Spring Native, and provides the beta version support. You can try it on your projects if they are using those supported dependencies, and raise bugs or contribute pull requests if something goes wrong on Spring Cloud Azure. For more information, see the Support section in the Spring Native documentation.

Spring Native

Spring Cloud Azure 4.1.0-beta.1 has been tested against Spring Native 0.11.4 and GraalVM 22.0.0.

Spring Cloud Azure Native

Note

Spring Native 0.11.4 has been tested against Spring Cloud Azure Native Configuration 4.0.0-beta.1.

Spring Cloud Azure provides a dependency spring-cloud-azure-native-configuration that is an extension of Spring Native configuration for Spring Cloud Azure libraries. The Spring Native AOT plugin will combine the spring-native-configuration and spring-cloud-azure-native-configuration to build applications into native executables. You don't need any extra modifications to the code that uses Spring Cloud Azure libraries apart from adding the dependency, which only applies to the code in the Spring Cloud Azure libraries.

The following features are supported:

  • Azure App Configuration clients auto-configuration
  • Azure Event Hubs clients auto-configuration
  • Azure Key Vault Certificates clients auto-configuration
  • Azure Key Vault Secrets clients auto-configuration
  • Azure Storage Blob clients auto-configuration
  • Azure Storage File Share clients auto-configuration
  • Azure Storage Queue clients auto-configuration
  • Spring Integration for Azure Event Hubs
  • Spring Integration for Azure Storage Queue

Limitations

The Spring Cloud Azure support for Spring Native is still in the early stages and continues to be updated. The following features are not yet supported:

  • Azure Cosmos DB clients auto-configuration
  • Azure Service Bus clients auto-configuration
  • Spring Data for Azure Cache for Redis
  • Spring Data for Azure Cosmos DB
  • Spring Cloud Stream for Azure Event Hubs
  • Spring Cloud Stream for Azure Service Bus
  • Spring Kafka for Azure Event Hubs
  • Spring Integration for Azure Service Bus

Note

Not all the native image options are supported by Spring Native. For more information, see the Native image options section of the Spring Native documentation.

Warning

Spring Cloud Azure 4.1.0-beta.1 is not validated for building native executables based on Gradle Kotlin.

Project setup

Spring Cloud Azure applications can enable Spring Native support by following the instructions in the Getting started section of the Spring Native documentation. The only additional processing required is to add the following dependency to the POM file.

Tip

The dependency com.azure.spring:spring-cloud-azure-native-configuration is not managed in com.azure.spring:spring-cloud-azure-dependencies.

<dependency>
  <groupId>com.azure.spring</groupId>
  <artifactId>spring-cloud-azure-native-configuration</artifactId>
  <version>4.0.0-beta.1</version>
</dependency>

Build the native application

The following sections describe the two main ways to build a Spring Boot native application with Spring Cloud Azure libraries.

Build with Buildpacks

The native application can be built as follows:

mvn spring-boot:build-image

For more information, see the Getting started with Buildpacks section in the Spring Native documentation.

Build with Native Build Tools

You can build the native application by using the following command:

mvn -Pnative -DskipTests package

For more information, see the Getting started with Native Build Tools section of the Spring Native documentation.

Run the native application

The following sections describe the two main ways to run a native executable.

Tip

Assuming the project artifact ID is spring-cloud-azure-sample and the project version is 0.0.1-SNAPSHOT, you can specify the custom image name in one of the following ways:

  • If you're using Cloud Native Buildpacks, use the image->name->custom-image-name configuration element in the Spring Boot plugin.
  • If you're using GraalVM Native Build Tools, use the imageName->custom-image-name configuration element in the Spring Boot plugin.

Run with Buildpacks

To run the application, you can use docker the usual way as shown in the following example:

docker run --rm -p 8080:8080 spring-cloud-azure-sample:0.0.1-SNAPSHOT

Run with Native Build Tools

To run your application, use the following command:

target\spring-cloud-azure-sample

Samples

For more information, see Using Spring Native with Spring Cloud Azure Storage Blob Starter on GitHub.

Here are other verified samples that support Spring Native. For more information, see Run Samples Based On Spring Native on GitHub.

Library Artifact ID Supported Example Projects
spring-cloud-azure-starter-appconfiguration appconfiguration-client
spring-cloud-azure-starter-eventhubs eventhubs-client
spring-cloud-azure-starter-integration-eventhubs storage-queue-integration, storage-queue-operation
spring-cloud-azure-starter-integration-storage-queue appconfiguration-client
spring-cloud-azure-starter-keyvault-secrets property-source, secret-client
spring-cloud-azure-starter-storage-blob storage-blob-sample
spring-cloud-azure-starter-storage-file-share storage-file-sample
spring-cloud-azure-starter-storage-queue storage-queue-client

MySQL support

Azure Database for MySQL is a relational database service powered by the MySQL community edition. You can use either Single Server or Flexible Server to host a MySQL database in Azure. It's a fully managed database-as-a-service offering that can handle mission-critical workloads with predictable performance and dynamic scalability.

From version 4.5.0, Spring Cloud Azure supports various types of credentials for authentication to Azure Database for MySQL Flexible server.

Supported MySQL version

The current version of the starter should use Azure Database for MySQL Flexible Server version 5.7 or 8.0.

Core Features

Passwordless connection

Passwordless connection uses Azure Active Directory (Azure AD) authentication for connecting to Azure services without storing any credentials in the application, its configuration files, or in environment variables. Azure AD authentication is a mechanism for connecting to Azure Database for MySQL using identities defined in Azure AD. With Azure AD authentication, you can manage database user identities and other Microsoft services in a central location, which simplifies permission management.

How it works

Spring Cloud Azure will first build one of the following types of credentials depending on the application authentication configuration:

  • ClientSecretCredential
  • ClientCertificateCredential
  • UsernamePasswordCredential
  • ManagedIdentityCredential
  • DefaultAzureCredential

If none of these types of credentials are found, the DefaultAzureCredential credentials will be obtained from application properties, environment variables, managed identities, or the IDE. For detailed information, see the Spring Cloud Azure authentication section.

The following high-level diagram summarizes how authentication works using OAuth credential authentication with Azure Database for MySQL. The arrows indicate communication pathways.

Diagram showing Azure Active Directory authentication for MySQL.

Configuration

Spring Cloud Azure for MySQL supports the following two levels of configuration options:

  1. The global authentication configuration options of credential and profile with prefixes of spring.cloud.azure.

  2. Spring Cloud Azure for MySQL common configuration options.

The following table shows the Spring Cloud Azure for MySQL common configuration options:

Name Description
spring.datasource.azure.passwordless-enabled Whether to enable passwordless connections to Azure databases by using OAuth2 Azure Active Directory token credentials.
spring.datasource.azure.credential.client-certificate-password Password of the certificate file.
spring.datasource.azure.credential.client-certificate-path Path of a PEM certificate file to use when performing service principal authentication with Azure.
spring.datasource.azure.credential.client-id Client ID to use when performing service principal authentication with Azure. This is a legacy property.
spring.datasource.azure.credential.client-secret Client secret to use when performing service principal authentication with Azure. This is a legacy property.
spring.datasource.azure.credential.managed-identity-enabled Whether to enable managed identity to authenticate with Azure. If true and the client-id is set, will use the client ID as user assigned managed identity client ID. The default value is false.
spring.datasource.azure.credential.password Password to use when performing username/password authentication with Azure.
spring.datasource.azure.credential.username Username to use when performing username/password authentication with Azure.
spring.datasource.azure.profile.cloud-type Name of the Azure cloud to connect to.
spring.datasource.azure.profile.environment.active-directory-endpoint The Azure Active Directory endpoint to connect to.
spring.datasource.azure.profile.tenant-id Tenant ID for Azure resources.

Dependency setup

Add the following dependency to your project. This will automatically include the spring-boot-starter dependency in your project transitively.

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-jdbc-mysql</artifactId>
</dependency>

Note

Passwordless connections have been supported since version 4.5.0.

Remember to add the BOM spring-cloud-azure-dependencies along with the above dependency. For more information, see the Getting started section.

Basic usage

The following sections show the classic Spring Boot application usage scenarios.

Important

Passwordless connection uses Azure AD authentication. To use Azure AD authentication, you should set the Azure AD admin user first. Only an Azure AD Admin user can create and enable users for Azure AD-based authentication. For more information, see the Create an Azure Database for MySQL instance and set up the admin user section.

Connect to Azure MySQL locally without password

  1. To create users and grant permission, see the Create a MySQL non-admin user and grant permission section.

  2. Configure the following properties in your application.yml file:

    spring:
      datasource:
        url: jdbc:mysql://${AZURE_MYSQL_SERVER_NAME}.mysql.database.azure.com:3306/${AZURE_MYSQL_DATABASE_NAME}
        username: ${AZURE_MYSQL_AD_NON_ADMIN_USERNAME}
        azure:
          passwordless-enabled: true
    

Connect to Azure MySQL using a service principal

  1. Create an Azure AD user for service principal and grant permission.

    1. First, use the following commands to set up some environment variables.

      export AZURE_MYSQL_AZURE_AD_SP_USERID=$(az ad sp list --display-name <service_principal-name> --query '[0].appId' -otsv)
      export AZURE_MYSQL_AZURE_AD_SP_USERNAME=<YOUR_MYSQL_AZURE_AD_USERNAME>
      export AZURE_MYSQL_SERVER_NAME=<YOUR_MYSQL_SERVER_NAME>
      export AZURE_MYSQL_DATABASE_NAME=<YOUR_MYSQL_DATABASE_NAME>
      export CURRENT_USERNAME=$(az ad signed-in-user show --query userPrincipalName -o tsv)
      
    2. Then, create a SQL script called create_ad_user_sp.sql for creating a non-admin user. Add the following contents and save it locally:

      cat << EOF > create_ad_user_sp.sql
      SET aad_auth_validate_oids_in_tenant = OFF;
      CREATE AADUSER '$AZURE_MYSQL_AZURE_AD_SP_USERNAME' IDENTIFIED BY '$AZURE_MYSQL_AZURE_AD_SP_USERID';
      GRANT ALL PRIVILEGES ON $AZURE_MYSQL_DATABASE_NAME.* TO '$AZURE_MYSQL_AZURE_AD_SP_USERNAME'@'%';
      FLUSH privileges;
      EOF
      
    3. Use the following command to run the SQL script to create the Azure AD non-admin user:

      mysql -h $AZURE_MYSQL_SERVER_NAME.mysql.database.azure.com --user $CURRENT_USERNAME --enable-cleartext-plugin --password=`az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken` < create_ad_user_sp.sql
      
    4. Now use the following command to remove the temporary SQL script file:

      rm create_ad_user_sp.sql
      
  2. Configure the following properties in your application.yml file:

    spring:
      cloud:
        azure:
          credential:
            client-id: ${AZURE_CLIENT_ID}
            client-secret: ${AZURE_CLIENT_SECRET}
          profile:
            tenant-id: ${AZURE_TENANT_ID}
      datasource:
        url: jdbc:mysql://${AZURE_MYSQL_SERVER_NAME}.mysql.database.azure.com:3306/${AZURE_MYSQL_DATABASE_NAME}
        username: ${AZURE_MYSQL_AD_SP_USERNAME}
        azure:
          passwordless-enabled: true
    

Connect to Azure MySQL with Managed Identity in Azure Spring Apps

  1. To enable managed identity, see the Assign the managed identity using the Azure portal section.

  2. To grant permissions, see the Assign roles to the managed identity section.

  3. Configure the following properties in your application.yml file:

    spring:
      datasource:
        url: jdbc:mysql://${AZURE_MYSQL_SERVER_NAME}.mysql.database.azure.com:3306/${AZURE_MYSQL_DATABASE_NAME}
        username: ${AZURE_MYSQL_AD_MI_USERNAME}
        azure:
          passwordless-enabled: true
    

Samples

See the azure-spring-boot-samples repository on GitHub.

PostgreSQL support

Azure Database for PostgreSQL is a relational database service based on the open-source Postgres database engine. It's a fully managed database-as-a-service that can handle mission-critical workloads with predictable performance, security, high availability, and dynamic scalability.

From version 4.5.0, Spring Cloud Azure supports various types of credentials for authentication to Azure Database for PostgreSQL Flexible server.

Supported PostgreSQL version

For supported versions, see Supported PostgreSQL major versions in Azure Database for PostgreSQL - Flexible Server.

Core Features

Passwordless connection

Passwordless connection uses Azure Active Directory (Azure AD) authentication for connecting to Azure services without storing any credentials in the application, its configuration files, or in environment variables. Azure AD authentication is a mechanism for connecting to Azure Database for PostgreSQL using identities defined in Azure AD. With Azure AD authentication, you can manage database user identities and other Microsoft services in a central location, which simplifies permission management.

How it works

Spring Cloud Azure will first build one of the following types of credentials depending on the application authentication configuration:

  • ClientSecretCredential
  • ClientCertificateCredential
  • UsernamePasswordCredential
  • ManagedIdentityCredential
  • DefaultAzureCredential

If none of these types of credentials are found, the DefaultAzureCredential credentials will be obtained from application properties, environment variables, managed identities, or the IDE. For detailed information, see the Spring Cloud Azure authentication section.

The following high-level diagram summarizes how authentication works using OAuth credential authentication with Azure Database for PostgreSQL. The arrows indicate communication pathways.

Diagram showing Azure Active Directory authentication for PostgreSQL .

Configuration

Spring Cloud Azure for PostgreSQL supports the following two levels of configuration options:

  1. The global authentication configuration options of credential and profile with prefixes of spring.cloud.azure.

  2. Spring Cloud Azure for PostgreSQL common configuration options.

The following table shows the Spring Cloud Azure for PostgreSQL common configuration options:

Name Description
spring.datasource.azure.passwordless-enabled Whether to enable passwordless connections to Azure databases by using OAuth2 Azure Active Directory token credentials.
spring.datasource.azure.credential.client-certificate-password Password of the certificate file.
spring.datasource.azure.credential.client-certificate-path Path of a PEM certificate file to use when performing service principal authentication with Azure.
spring.datasource.azure.credential.client-id Client ID to use when performing service principal authentication with Azure. This is a legacy property.
spring.datasource.azure.credential.client-secret Client secret to use when performing service principal authentication with Azure. This is a legacy property.
spring.datasource.azure.credential.managed-identity-enabled Whether to enable managed identity to authenticate with Azure. If true and the client-id is set, will use the client ID as user assigned managed identity client ID. The default value is false.
spring.datasource.azure.credential.password Password to use when performing username/password authentication with Azure.
spring.datasource.azure.credential.username Username to use when performing username/password authentication with Azure.
spring.datasource.azure.profile.cloud-type Name of the Azure cloud to connect to.
spring.datasource.azure.profile.environment.active-directory-endpoint The Azure Active Directory endpoint to connect to.
spring.datasource.azure.profile.tenant-id Tenant ID for Azure resources.

Dependency setup

Add the following dependency to your project. This will automatically include the spring-boot-starter dependency in your project transitively.

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-jdbc-postgresql</artifactId>
</dependency>

Note

Passwordless connections have been supported since version 4.5.0.

Remember to add the BOM spring-cloud-azure-dependencies along with the above dependency. For more information, see the Getting started section.

Basic usage

The following sections show the classic Spring Boot application usage scenarios.

Important

Passwordless connection uses Azure AD authentication. To use Azure AD authentication, you should set the Azure AD admin user first. Only an Azure AD Admin user can create and enable users for Azure AD-based authentication. For more information, see the Create an Azure Database for PostgreSQL instance and set up the admin user section.

Connect to Azure PostgreSQL locally without password

  1. To create users and grant permission, see the Create a PostgreSQL non-admin user and grant permission section.

  2. Configure the following properties in your application.yml file:

    spring:
      datasource:
        url: jdbc:postgresql://${AZ_DATABASE_SERVER_NAME}.postgres.database.azure.com:5432/${AZ_DATABASE_NAME}?sslmode=require
        username: ${AZ_POSTGRESQL_AD_NON_ADMIN_USERNAME}
        azure:
          passwordless-enabled: true
    

Connect to Azure PostgreSQL using a service principal

  1. Assign role to service principal:

    1. Create a SQL script called create_ad_user_sp.sql for creating a non-admin user. Add the following contents and save it locally:

      Important

      Make sure <service-principal-name> already exists in your Azure AD tenant, or you won't be able to create the non-admin user.

      cat << EOF > create_ad_user_sp.sql
      select * from pgaadauth_create_principal('<service-principal-name>', false, false);
      EOF
      
    2. Use the following command to run the SQL script to create the Azure AD non-admin user:

      psql "host=$AZ_DATABASE_SERVER_NAME.postgres.database.azure.com user=$CURRENT_USERNAME@$AZ_DATABASE_SERVER_NAME dbname=postgres port=5432 password=`az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken` sslmode=require" < create_ad_user_sp.sql
      
    3. Now use the following command to remove the temporary SQL script file:

      rm create_ad_user_sp.sql
      
  2. Configure the following properties in your application.yml file:

    spring:
      cloud:
        azure:
          credential:
            client-id: ${AZURE_CLIENT_ID}
            client-secret: ${AZURE_CLIENT_SECRET}
          profile:
            tenant-id: ${AZURE_TENANT_ID}
      datasource:
        url: jdbc:postgresql://${AZ_DATABASE_SERVER_NAME}.postgres.database.azure.com:5432/${AZ_DATABASE_NAME}?sslmode=require
        username: ${AZ_POSTGRESQL_AD_SP_USERNAME}
        azure:
          passwordless-enabled: true
    

Connect to Azure PostgreSQL with Managed Identity in Azure Spring Apps

  1. To enable managed identity, see the Assign the managed identity using the Azure portal section.

  2. To grant permissions, see the Assign role to managed identity section.

  3. Configure the following properties in your application.yml file:

    spring:
      cloud:
        azure:
          credential:
            managed-identity-enabled: true
            client-id: ${AZURE_CLIENT_ID}
      datasource:
        url: jdbc:postgresql://${AZ_DATABASE_SERVER_NAME}.postgres.database.azure.com:5432/${AZ_DATABASE_NAME}?sslmode=require
        username: ${AZ_POSTGRESQL_AD_MI_USERNAME}
        azure:
          passwordless-enabled: true
    

Samples

See the azure-spring-boot-samples repository on GitHub.

Kafka support

From version 4.3.0, Spring Cloud Azure for Kafka supports various types of credentials to authenticate and connect to Azure Event Hubs.

Supported Kafka version

The current version of the starter should be compatible with Apache Kafka Clients 2.0.0 using Java 8 or above.

Supported authentication types

The following authentication types are supported:

  • Plain connection string authentication
    • Direct connection string authentication
    • ARM-based connection string authentication
  • OAuth credential authentication
    • Managed identity authentication
    • Username/password authentication
    • Service principal authentication
    • DefaultAzureCredential authentication

How it works

OAuth credential authentication

This section describes the overall workflow of Spring Cloud Azure OAuth authentication.

Spring Cloud Azure will first build one of the following types of credentials depending on the application authentication configuration:

  • ClientSecretCredential
  • ClientCertificateCredential
  • UsernamePasswordCredential
  • ManagedIdentityCredential

If none of these types of credentials are found, the credential chain via DefaultAzureTokenCredential will be used to obtain credentials from application properties, environment variables, managed identity, or IDEs. For detailed information, see the Spring Cloud Azure authentication section.

Plain connection string authentication

For the connection string authentication mode, you can use connection string authentication directly or use the Azure Resource Manager to retrieve the connection string. For more information about the usage, see the Basic usage for connection string authentication section.

Note

Since version of 4.3.0, connection string authentication is deprecated in favor of OAuth authentications.

Configuration

Configurable properties when using Kafka support with OAuth authentication

Spring Cloud Azure for Kafka supports the following two levels of configuration options:

  1. Spring Cloud Azure for Event Hubs Kafka properties.
  2. The global authentication configuration options of credential and profile with prefixes of spring.cloud.azure.
  3. Kafka-specific level configurations. The Kafka-level configurations are also available for Spring Boot and Spring Cloud Stream binders for common, consumer, producer, or admin scopes, which have different prefixes.

The global properties are exposed via com.azure.spring.cloud.autoconfigure.context.AzureGlobalProperties. The Kafka-specific properties are exposed via org.springframework.boot.autoconfigure.kafka.KafkaProperties (Spring Boot) and org.springframework.cloud.stream.binder.kafka.properties.KafkaBinderConfigurationProperties (Spring Cloud Stream binder).

The following list shows all supported configuration options.

  • Spring Cloud Azure for Event Hubs Kafka properties.

    • Property: spring.cloud.azure.eventhubs.kafka.enabled
    • Description: whether to enable credential free connection to Azure Event Hubs for Kafka, the default value is true.
  • The Spring Cloud Azure global authentication configuration options

    • Prefix: spring.cloud.azure
    • Supported options: spring.cloud.azure.credential.*, spring.cloud.azure.profile.*

    For the full list of global configuration options, see Global configuration properties.

  • Spring Boot Kafka common configuration

    • Prefix: spring.kafka.properties.azure
    • Example: spring.kafka.properties.azure.credential.*
  • Spring Kafka consumer configuration options

    • Prefix: spring.kafka.consumer.properties.azure
    • Example: spring.kafka.consumer.properties.azure.credential.*
  • Spring Kafka producer configuration options

    • Prefix: spring.kafka.producer.properties.azure
    • Example: spring.kafka.producer.properties.azure.credential.*
  • Spring Kafka admin configuration options

    • Prefix: spring.kafka.admin.properties.azure
    • Example: spring.kafka.admin.properties.azure.credential.*
  • Spring Cloud Stream Kafka Binder common configuration

    • Prefix: spring.cloud.stream.kafka.binder.configuration.azure
    • Example: spring.cloud.stream.kafka.binder.configuration.azure.credential.*
  • Spring Cloud Stream Kafka Binder consumer configuration

    • Prefix: spring.cloud.stream.kafka.binder.consumer-properties.azure
    • Example: spring.cloud.stream.kafka.binder.consumer-properties.azure.credential.*
  • Spring Cloud Stream Kafka Binder producer configuration

    • Prefix: spring.cloud.stream.kafka.binder.producer-properties.azure
    • Example: spring.cloud.stream.kafka.binder.producer-properties.azure.credential.*
  • Spring Cloud Stream Kafka Binder admin configuration

    • Prefix: Not supported, should use Spring Boot Kafka common or admin configuration.

The following table shows the Spring Boot Kafka common configuration options:

Name Description
spring.kafka.properties.azure.credential.client-certificate-password Password of the certificate file.
spring.kafka.properties.azure.credential.client-certificate-path Path of a PEM certificate file to use when performing service principal authentication with Azure.
spring.kafka.properties.azure.credential.client-id Client ID to use when performing service principal authentication with Azure. This is a legacy property.
spring.kafka.properties.azure.credential.client-secret Client secret to use when performing service principal authentication with Azure. This is a legacy property.
spring.kafka.properties.azure.credential.managed-identity-enabled Whether to enable managed identity to authenticate with Azure. If true and the client-id is set, will use the client ID as user assigned managed identity client ID. The default value is false.
spring.kafka.properties.azure.credential.password Password to use when performing username/password authentication with Azure.
spring.kafka.properties.azure.credential.username Username to use when performing username/password authentication with Azure.
spring.kafka.properties.azure.profile.environment.active-directory-endpoint The Azure Active Directory endpoint to connect to.
spring.kafka.properties.azure.profile.tenant-id Tenant ID for Azure resources.

Note

The configuration options in different levels apply the following rules. The more specific configuration options have higher priority than the common ones. For example:

  • Spring Kafka common configuration options supersede the global options.
  • Spring Kafka consumer configuration options supersede the common options.
  • Spring Kafka producer configuration options supersede the common options.
  • Spring Kafka admin configuration options supersede the common options.
  • The Spring Cloud Stream Kafka Binder options are just like the above.

Configurable properties when using Kafka support with plain connection string authentication

The following table shows the Spring Boot Event Hubs for Kafka common configuration options:

Property Description
spring.cloud.azure.eventhubs.kafka.enabled Whether to enable the Azure Event Hubs Kafka support. The default value is true.
spring.cloud.azure.eventhubs.connection-string Azure Event Hubs connection string. Provide this value when you want to provide the connection string directly.
spring.cloud.azure.eventhubs.namespace Azure Event Hubs namespace. Provide this value when you want to retrieve the connection information through Azure Resource Manager.
spring.cloud.azure.eventhubs.resource.resource-group The resource group of Azure Event Hubs namespace. Provide this value when you want to retrieve the connection information through Azure Resource Manager.
spring.cloud.azure.profile.subscription-id The subscription ID. Provide this value when you want to retrieve the connection information through Azure Resource Manager.

Dependency setup

Add the following dependency to your project. This will automatically include the spring-boot-starter dependency in your project transitively.

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter</artifactId>
</dependency>

Note

Remember to add the BOM spring-cloud-azure-dependencies along with the above dependency. For details, see the Getting started section.

Basic usage

The following sections show the classic Spring Boot application usage scenarios.

Use OAuth authentication

When you use the OAuth authentication provided by Spring Cloud Azure for Kafka, you can configure the specific credentials using the above configurations. Alternatively, you can choose to configure nothing about credentials, in which case Spring Cloud Azure will load the credentials from the environment. This section describes the usages that load the credentials from the Azure CLI environment or the Azure Spring Apps hosting environment.

Note

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, see the Authorize access with Azure Active Directory section to make sure the security principal has been granted the sufficient permission to access the Azure resource.

The following section describes the scenarios using different Spring ecosystem libraries with OAuth authentication.

Spring Kafka application support

This section describes the usage scenario for Spring Boot application using Spring Kafka or Spring Integration Kafka library.

Dependency setup
<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter</artifactId>
</dependency>
<!-- Using Spring Kafka library only-->
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
    <version>{version}</version><!--Need to be set, for example:2.8.6-->
</dependency>
<!-- Using Spring Integration library only -->
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-kafka</artifactId>
    <version>{version}</version><!--Need to be set, for example:5.5.12-->
</dependency>

Configuration update

To use the OAuth authentication, just specify the Event Hubs endpoint, as shown in the following example:

spring.kafka.bootstrap-servers=<NAMESPACENAME>.servicebus.windows.net:9093
Spring Cloud Stream binder Kafka application support

This section describes the usage scenario for Spring Boot applications using the Spring Cloud Stream binder Kafka library.

Dependency setup
<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-kafka</artifactId>
    <version>{version}</version><!--Need to be set, for example:3.2.3-->
</dependency>
Configuration

To use the OAuth authentication, just specify the Event Hubs endpoint as shown in the following example:

spring.cloud.stream.kafka.binder.brokers=<NAMESPACENAME>.servicebus.windows.net:9093

Note

If you're using version 4.3.0, don't forget to set the spring.cloud.stream.binders.<kafka-binder-name>.environment.spring.main.sources=com.azure.spring.cloud.autoconfigure.kafka.AzureKafkaSpringCloudStreamConfiguration property to enable the whole OAuth authentication workflow, where kafka-binder-name is kafka by default in a single Kafka binder application. The configuration AzureKafkaSpringCloudStreamConfiguration specifies the OAuth security parameters for KafkaBinderConfigurationProperties, which is used in KafkaOAuth2AuthenticateCallbackHandler to enable Azure Identity.

For version after 4.4.0, this property will be added automatically for each Kafka binder environment, so there's no need for you to add it manually.

Samples

See the azure-spring-boot-samples repository on GitHub.

Use connection string authentication

You can use connection string authentication directly or use the Azure Resource Manager to retrieve the connection string.

Note

Since version of 4.3.0, connection string authentication is deprecated in favor of OAuth authentications.

Since version of 4.5.0, when using connection string authentication with Spring Cloud Stream framework, the following property is required to ensure that the connection string can take effect, where the <kafka-binder-name> placeholder has a value of kafka by default.

spring.cloud.stream.binders.<kafka-binder-name>.environment.spring.main.sources=com.azure.spring.cloud.autoconfigure.eventhubs.kafka.AzureEventHubsKafkaAutoConfiguration

Dependency setup

Add the following dependencies if you want to migrate your Apache Kafka application to use Azure Event Hubs for Kafka.

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter</artifactId>
</dependency>

If you want to retrieve the connection string using Azure Resource Manager, add the following dependency:

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-resourcemanager</artifactId>
</dependency>
Configuration
Use Event Hubs connection string directly

The simplest way to connect to Event Hubs for Kafka is with the connection string. Just add the following property.

spring.cloud.azure.eventhubs.connection-string=${AZURE_EVENTHUBS_CONNECTION_STRING}
Use Azure Resource Manager to retrieve connection string

If you don't want to configure the connection string in your application, you can use Azure Resource Manager to retrieve the connection string. To authenticate with Azure Resource Manager, you can also use credentials stored in Azure CLI or another local development tool such as Visual Studio Code or Intellij IDEA. Alternately, you can use Managed Identity if your application is deployed to Azure Cloud. Just be sure the principal has sufficient permission to read resource metadata.

Note

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, see the Authorize access with Azure Active Directory section to be sure the security principal has been granted the sufficient permission to access the Azure resource.

To use Azure Resource Manager to retrieve the connection string, just add the following property.

spring:
  cloud:
    azure:
      profile:
        subscription-id: ${AZURE_SUBSCRIPTION_ID}
      eventhubs:
        namespace: ${AZURE_EVENTHUBS_NAMESPACE}
        resource:
          resource-group: ${AZURE_EVENTHUBS_RESOURCE_GROUP}

Samples

See the azure-spring-boot-samples repository on GitHub.

Redis support

Connect to Azure Cache for Redis using Spring Redis libraries. With adding spring-cloud-azure-starter and spring-cloud-azure-resourcemanager to your application, it's possible to read the Azure Cache for Redis connection information through Azure Resource Manager and auto-configure the Redis properties.

Dependency setup

Add the following dependencies if you want to use the Spring Cloud Azure Redis support to your Spring Boot application using Redis.

<dependencies>
    <dependency>
      <groupId>com.azure.spring</groupId>
      <artifactId>spring-cloud-azure-starter</artifactId>
    </dependency>
    <dependency>
      <groupId>com.azure.spring</groupId>
      <artifactId>spring-cloud-azure-resourcemanager</artifactId>
    </dependency>
</dependencies>

Configuration

Note

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, refer to Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.

Configurable properties when using Redis support:

Property Description Default Value Required
spring.cloud.azure.redis.enabled Whether an Azure Cache for Redis is enabled. true No
spring.cloud.azure.redis.name Azure Cache for Redis instance name. Yes
spring.cloud.azure.redis.resource.resource-group The resource group of Azure Cache for Redis. Yes
spring.cloud.azure.profile.subscription-id The subscription ID. Yes

Note

Authentication information is also required for authenticating for Azure Resource Manager. The credential related configurations of Resource Manager should be configured under prefix spring.cloud.azure. For more information, see the Authentication section.

Basic usage

Add the following properties and you are good to go.

spring.cloud.azure.redis.name=${AZURE_CACHE_REDIS_NAME}
spring.cloud.azure.redis.resource.resource-group=${AZURE_CACHE_REDIS_RESOURCE_GROUP}

Samples

See azure-spring-boot-samples for more details.

Azure Resource Manager

Azure Resource Manager (ARM) is the deployment and management service for Azure. It provides a management layer that enables you to create, update, and delete resources in your Azure account. Spring Cloud Azure Resource Manager can help provision resources or retrieve resource metadata.

Dependency setup

<dependency>
  <groupId>com.azure.spring</groupId>
  <artifactId>spring-cloud-azure-resourcemanager</artifactId>
</dependency>

Configuration

Note

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, refer to Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.

Configurable properties of spring-cloud-azure-resourcemanager:

Property Description
spring.cloud.azure.resource-manager.enabled Whether the Resource Manager is enabled. Default is true.
spring.cloud.azure.credential.client-id Client ID to use when performing service principal authentication with Azure.
spring.cloud.azure.credential.client-secret Client secret to use when performing service principal authentication with Azure.
spring.cloud.azure.credential.client-certificate-path Path of a PEM certificate file to use when performing service principal authentication with Azure.
spring.cloud.azure.credential.client-certificate-password Password of the certificate file.
spring.cloud.azure.credential.username Username to use when performing username/password authentication with Azure.
spring.cloud.azure.credential.password Password to use when performing username/password authentication.
spring.cloud.azure.credential.managed-identity-enabled Whether to enable managed identity.
spring.cloud.azure.profile.cloud-type Name of the Azure cloud to connect to.
spring.cloud.azure.profile.environment.active-directory-endpoint The Azure Active Directory endpoint to connect to for authentication.
spring.cloud.azure.profile.subscription-id Subscription ID to use when connecting to Azure resources.
spring.cloud.azure.profile.tenant-id Tenant ID for Azure resources.
spring.cloud.azure.azure-service.namespace The namespace of the Azure service to provision resources with.
spring.cloud.azure.azure-service.resource.resource-group The resource group holding an Azure service resource.

Basic usage

Spring Cloud Azure Resource Manager can work together with specific Spring Cloud Azure starters to retrieve connection information, such as connection strings, to connect to Azure services. It can also work together with spring-cloud-azure-starter and third-party libraries to retrieve metadata like username/password, and to complete authentication. For more information, see the Kafka Support and Redis Support sections.

For example, to retrieve the connection string of an Azure Service, developers can use a service principal as the credential to authenticate and retrieve the connection string. The configuration is listed the follows. The provided service principal should be assigned a role of Contributor of the associated namespace at least. See Authorize access with Azure AD to make sure the principal has been granted the sufficient permission to access the Azure resource.

spring:
  cloud:
    azure:
      credential:
        client-id: ${AZURE_CLIENT_ID}
        client-secret: ${AZURE_CLIENT_SECRET}
      profile:
        tenant-id: ${AZURE_TENANT_ID}
        subscription-id: ${AZURE_SUBSCRIPTION_ID}
      <azure-service>:
        namespace: ${SERVICEBUS_NAMESPACE}
        resource:
          resource-group: ${RESOURCE_GROUP}

Samples

See azure-spring-boot-samples for more details.

Configuration properties

To see the list of all Spring Cloud Azure related configuration properties, see Spring Cloud Azure configuration properties.

Appendix