This doc is only for Spring Cloud Azure: 4.0.0-beta.3. Please refer to Spring Versions Mapping to get more information about supported versions.

© 2016-2022 the original authors.

Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.

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 services.

1. Getting Help

If you have any questions about this doc, please ask by creating GitHub issue. And Pull Request is welcome.

Table 1. GitHub repositories
GitHub repositories Description

Azure/azure-sdk-for-java

This repository used to hold the source code.

microsoft/spring-cloud-azure

This repository used to hold the document which is displaying in current page.

2. What is New in 4.0 since 3.10.x

This page covers changes made in 4.0 since 3.10. With this major release, we aim to bring better security, leaner dependencies, support for production readiness, and more.

To learn how to migration to 4.0, please check the Appendix page.

2.1. Unified Development Experience

We constantly challenge ourselves on how we can make things more consistent and easier to understand, so our customers are not confronted with haphazard development choices. This is a long and self-evolving journey as consistency is relative and there will be things that are outside our control. We now humbly take another step in this direction to improve to our developer experience by unifying project name, artifact ID and properties.

2.2. Simplified dependency management

Dependency management is one of the core value pillars that has helped Spring establish preeminence over to other Java frameworks. In that spirit, we have also been exploring ways to make dependency management easier for Spring developers on Azure. In this release, we have codified best practices and expertise from Spring experts and condensed all of our dependency BOMs into one, spring-cloud-azure-dependencies, which we believe will further bring down the learning curve and avoid ill-handling of dependencies.

2.3. Expanded support scope of Azure Support on start.spring.io

The Azure Support module in Spring Initializr provides auto-configuration of many Azure services.

In this release we have expanded the scope of Azure Support to cover the additional 4 more services:

  • Kafka

  • Event Hubs

  • Azure Cache for Redis

  • App Configuration

Our journey does end here and over time we will bring even more Azure services into the fold.

2.4. Untethered and unrestrained

One feedback that we consistently hear is our Spring modules are unnecessarily stacked on top of too many layers of dependencies, which has prevented broader adoption. As an example, all of our early Spring modules rely on Spring Boot, and many of our customers are running Spring MVC apps in Tomcat, leveraging nothing but Spring Data, as an example, to communicate with data services. We now realize the flaw in our original design, and have rearchitected our Spring module dependencies from the ground up, untethered from layers of excess and entanglement.

2.5. More control and secure

At the heart of every real-world application, is identity and secret management. Support for managed identity has become an Azure fundamental that are getting mandated as a security baseline at individual services. We believe aligning on those guidelines will also benefit Spring developers at large, and have added Managed Identity support for App Configuration, Event Hub, Service Bus, Cosmos, Key Vault, Storage Blob, and Storage Queue. This enables building credential-free applications, which is a pattern that has picked up tremendous momentum both at Microsoft and in the community. In addition to Managed Identity, you can use any authentication methods supported in the underlying Azure SDK from our Spring libraries. For instance, you use SAS token and token credential to authenticate with Service Bus and Event Hubs. Credential chain is now enabled by default, allowing applications to obtain credentials from application properties, environment variables, managed identity, IDEs, etc. Lastly providing granular level access control at the resource level (i.e.: Service Bus queue), is often of paramount importance when it comes to meeting the needs of our enterprise customers. We’ve now unlocked these controls to our customers for better security governance and adherence to IT policies.

2.6. More options exposed in a Spring idiomatic way

Spring developers have long enjoyed the convenience of defining client options in application configuration files. We certainly do not want to take that privilege away and burden Spring developers with setting options via client objects. To that end, we’ve significantly improved autoconfiguration coverage of Azure SDK clients for both synchronous and asynchronous scenarios.

2.7. More Production Ready

Lastly all the above would be in vain if we do not have enough feature coverage to support our customers in production. Many things come to my mind to make an application production-ready, but observability often arrives at the top. We’ve added health indicators for App Configuration, Event Hubs, Cosmos, Key Vault, Storage Blob, Storage Queue, Storage File, as well as Spring Cloud Sleuth support for all HTTP-based Azure SDKs. As an example, you now can prob if storage blob is up or down via Spring Boot actuator endpoint, as well as track dependencies and latencies going from your application to Cosmos DB.

3. Migration Guide for 4.0

To learn how to migration to 4.0, please check the Appendix page.

4. Getting Started

4.1. Setting up Dependencies

4.1.1. Bill of Material (BOM)

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

The version for spring-cloud-azure-dependencies is 4.0.0-beta.3.

4.1.2. 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.It boosts 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 application starters are provided by Spring Cloud Azure under the com.azure.spring group:

Table 2. Spring Cloud Azure starters
Name Description

spring-cloud-azure-starter

Core starter, including auto-configuration support

spring-cloud-azure-starter-active-directory

Starter for using Azure Active Directory with Spring Security

spring-cloud-azure-starter-active-directory-b2c

Starter for using Azure Active Directory B2C with Spring Security

spring-cloud-azure-starter-appconfiguration

Starter for using Azure App Configuration

spring-cloud-azure-starter-cosmos

Starter for using Azure Cosmos DB

spring-cloud-azure-starter-eventhubs

Starter for using Azure Event Hubs

spring-cloud-azure-starter-keyvault-secrets

Starter for using Azure Key Vault Secrets

spring-cloud-azure-starter-servicebus

Starter for using Azure Service Bus

spring-cloud-azure-starter-servicebus-jms

Starter for using Azure Service Bus and JMS

spring-cloud-azure-starter-storage-blob

Starter for using Azure Storage Blob

spring-cloud-azure-starter-storage-file-share

Starter for using Azure Storage File Share

spring-cloud-azure-starter-storage-queue

Starter for using Azure Storage Queue

spring-cloud-azure-starter-actuator

Starter for using Spring Boot’s Actuator which provides production ready features

Below are starters for Spring Data support:

Table 3. Spring Data related starters
Name Description

spring-cloud-azure-starter-data-cosmos

Starter for using Azure Cosmos DB and Spring Data Cosmos DB

Below are starters for Spring Integration support:

Table 4. Spring Integration related starters
Name Description

spring-cloud-azure-starter-integration-eventhubs

Starter for using Azure Event Hubs and Spring Integration

spring-cloud-azure-starter-integration-servicebus

Starter for using Azure Service Bus and Spring Integration

spring-cloud-azure-starter-integration-storage-queue

Starter for using Azure Storage Queue and Spring Integration

Below are starters for Spring Cloud Stream support:

Table 5. Spring Cloud Stream related starters
Name Description

spring-cloud-azure-starter-stream-eventhubs

Starters for using Azure Event Hubs and Spring Cloud Stream Binder

spring-cloud-azure-starter-stream-servicebus

Starter for using Azure Service Bus and Spring Cloud Stream Binder

4.2. Learning Spring Cloud Azure

We prepared a full list of samples to show the usages, can be found at Spring Cloud Azure Samples.

5. Configuration

Most of Azure Service SDKs could be divided into two categories by transport type, HTTP-based and 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, which could be specified to each Azure service.

Table 6. Service common properties
Property Description

spring.cloud.azure.<azure-service>.client

To configure the transport clients underneath one Azure service SDK.

spring.cloud.azure.<azure-service>.credential

To configure how to authenticate with Azure Active Directory for one Azure service SDK.

spring.cloud.azure.<azure-service>.profile

To configure the Azure cloud environment for one Azure service SDK.

spring.cloud.azure.<azure-service>.proxy

To configure the proxy options for one Azure service SDK.

spring.cloud.azure.<azure-service>.retry

To configure the retry options apply to one Azure service SDK.

There are some properties that could be shared among different Azure services, for example using the same service principal to access Azure Cosmos DB and Azure Event Hubs. Spring Cloud Azure 4.0 allows developers to define properties that apply to all Azure SDKs in the namespace spring.cloud.azure.

Table 7. Global properties
Property Description

spring.cloud.azure.client

To configure the transport clients apply to all Azure SDKs by default.

spring.cloud.azure.credential

To configure how to authenticate with Azure Active Directory for all Azure SDKs by default.

spring.cloud.azure.profile

To configure the Azure cloud environment for all Azure SDKs by default.

spring.cloud.azure.proxy

To configure the proxy options apply to all Azure SDK clients by default.

spring.cloud.azure.retry

To configure the retry options apply to all Azure SDK clients by default.

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

The configuration properties' prefixes have been unified to spring.cloud.azure namespace since Spring Cloud Azure 4.0, it will make configuration properties more consistent and more intuitive. Here’s a quick review of the prefixes of supported Azure services.

Table 8. Service specific properties
Azure Service Configuration Property Prefix

Azure App Configuration

spring.cloud.azure.appconfiguration

Azure Cosmos DB

spring.cloud.azure.cosmos

Azure Event Hubs

spring.cloud.azure.eventhubs

Azure Key Vault Certificate

spring.cloud.azure.keyvault.certificate

Azure Key Vault Secret

spring.cloud.azure.keyvault.secret

Azure Service Bus

spring.cloud.azure.servicebus

Azure Storage Blob

spring.cloud.azure.storage.blob

Azure Storage File Share

spring.cloud.azure.storage.fileshare

Azure Storage Queue

spring.cloud.azure.storage.queue

6. Authentication

6.1. DefaultAzureCredential

The DefaultAzureCredential is appropriate for most scenarios where the application is intended to ultimately 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.

DefaultAzureCredential is intended to simplify getting started with the SDK by handling common scenarios with reasonable default behaviors. Developers who want more control or whose scenario isn’t served by the default settings should use other credential types.

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

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 the developer has authenticated via Azure Toolkit for IntelliJ, the DefaultAzureCredential will authenticate with that account.

  • Visual Studio Code - If the developer has authenticated via the Visual Studio Code Azure Account plugin, the DefaultAzureCredential will authenticate with that account.

  • Azure CLI - If the developer has authenticated an account via the Azure CLI az login command, the DefaultAzureCredential will authenticate with that account.

There could be some ERROR logs be printed out while the DefaultAzureCredential running the chain and trying to find the first available credential.It doesn’t mean the DefaultAzureCredential is broken or unavailable.Meanwhile, we’ll keep improving this logging experience.
Please refer to Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.

6.2. Managed Identity

A common challenge for developers is the management of secrets and credentials used to secure communication between different components making up a solution. Managed identities eliminate the need for developers 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 developers can store credentials in a secure manner or to access storage accounts.

We encourage using manged identity instead of using connection string or key in your application for 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 and deploying the application to Azure Cloud and using Manged Identity.

6.2.1. 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 is 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. In the case of user-assigned managed identities, the identity is managed separately from the resources that use it.

When a user-assigned managed identity is used, you can specify it by spring.cloud.azure.credential.managed-identity-client-id or spring.cloud.azure.<azure-service>.credential.managed-identity-client-id. No credential configuration is needed if a system-assigned managed identity is used.
Please refer to Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.
Please refer to What are managed identities for Azure resources? for more details about manged identity.

6.3. Other Credential Types

Developers who want more control or whose scenario isn’t served by the DefaultAzureCredential or whose scenario isn’t served by the default settings should use other credential types.

6.3.1. 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

For applications want to connect to resources that support Azure Active Directory (Azure AD) authentication, below configurations could be set with prefix spring.cloud.azure.credential or spring.cloud.azure.<azure-service>.credential

Table 9. Authentication properties
Property Description

client-id

Client id to use when performing service principal authentication with Azure.

client-secret

Client secret to use when performing service principal authentication with Azure.

client-certificate-path

Client secret to use when performing service principal authentication with Azure.

client-certificate-password

Password of the certificate file.

username

Username to use when performing username/password authentication with Azure.

password

Password to use when performing username/password authentication with Azure.

managed-identity-client-id

Client id to use when using user-assigned managed identity or app registration (when working with AKS pod-identity) to authenticate with Azure.

To see the list of all Spring Cloud Azure related configuration properties please check the Appendix page.
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.

To see the list of all Azure built-in roles please check Azure built-in roles.

Following are the Azure built-in roles for authorizing access to Azure services supported in Spring Cloud Azure:

Table 10. Azure built-in roles
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 for 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 for full access to Azure Service Bus resources.

Azure Service Bus Data Receiver

Allows for receive access to Azure Service Bus resources.

Azure Service Bus Data Sender

Allows for 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.

When using Spring Cloud Azure Resource Manager to get the connection strings of Event Hubs, Service Bus, and Storage Queue, or 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.
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. Check here for more details.
Azure Cosmos DB exposes 2 built-in role definitions: Cosmos DB Built-in Data Reader and Cosmos DB Built-in Data Contributor. However, Azure portal support for role management is not available yet. Check here for more details about the permission model, role definitions, and role assignment.

6.3.2. SAS Token

It’s also configurable for services support authenticating with Shared Access Signature (SAS). spring.cloud.azure.<azure-service>.sas-token is the property to configure. For example, using spring.cloud.azure.storage.blob.sas-token to authenticate to Storage Blob service.

6.3.3. Connection String

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

7. Production Ready

We’ve added health indicators for App Configuration, Event Hubs, Cosmos, Key Vault, Storage Blob, Storage Queue, Storage File, as well as Spring Cloud Sleuth support for all HTTP-based Azure SDKs. As an example, you now can prob if 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.

7.1. Enable Health Indicator

Add the Spring Cloud Azure Actuator Starter dependency. This dependency will also include the spring-boot-starter-actuator.

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-actuator</artifactId>
</dependency>
Table 11. Configurable properties to enable or disable health indicators for each Azure services
Azure Service Property

App Configuration

management.health.azure-appconfiguration.enabled

Cosmos DB

management.health.azure-cosmos.enabled

Event Hubs

management.health.azure-eventhubs.enabled

Key Vault

management.health.azure-keyvault.enabled

Storage

management.health.azure-storage.enabled

Calling the health endpoint of Azure services may cause extra charge. For example, calling HOST_NAME:{port}/actuator/health/cosmos to get the Cosmos DB health info, it will calculate RUs.

7.2. Enable Sleuth

Add the Spring Cloud Azure Trace Sleuth dependency when you want to trace Azure SDK activities with using Spring Cloud Sleuth.

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-trace-sleuth</artifactId>
</dependency>
Only HTTP-based Azure SDK clients are supported now, for example, Eventhub and ServiceBus with AMQP transport are currently not supported, we recommend to use Azure Application Insight for such requirement.

8. Auto Configure Azure SDK Clients

Spring Boot greatly simplifies the Spring Cloud Azure experience. Spring Cloud Azure Starters are a set of convenient dependency descriptors to include in your application. Our starters handle the object instantiation and configuration logic, so you don’t have to. Every starter depends on the 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:

spring:
  cloud:
    azure:
      profile:
        tenant-id: ${AZURE_TENANT_ID}
        cloud: Azure
      credential:
        client-id: ${AZURE_CLIENT_ID}
  • cloud is optional.

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

8.1. Dependency Setup

There are two ways to use Spring Cloud Azure starters, one is using Azure SDKs with this spring-cloud-azure-starter dependency

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

or without adding Azure SDK dependencies and including the Spring Cloud Azure Starter for each Service directly. For example with Cosmos DB

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-cosmos</artifactId>
</dependency>
Please refer to Starter Dependencies for the list of starters we support.

8.2. Configuration

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

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

To see the list of all Spring Cloud Azure related configuration properties please check the Appendix page.

8.3. Basic Usage

Adding below properties to your application.yaml will autoconfigure the Cosmos Client for you, both CosmosClient and CosmosAsyncClient are available in the context and could be autowired.

spring:
  cloud:
    azure:
      cosmos:
        database: ${AZURE_COSMOS_DATABASE_NAME}
        endpoint: ${AZURE_COSMOS_ENDPOINT}
        consistency-level: eventual
        connection-mode: direct
class Demo {
    @Autowired
    private CosmosClient cosmosClient;

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

8.4. Samples

Please refer to azure-spring-boot-samples for more details.

9. Resource Handling

Spring project provides Spring Resources abstraction to access a number of low-level resources. It 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 Spring programming model. It 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.

Table 12. Azure Storage related libraries.
Starter Service Description

spring-cloud-azure-starter-storage-blob

Azure Blobs

Allows unstructured data to be stored and accessed at a massive scale in block blobs.

spring-cloud-azure-starter-storage-file-share

Azure Files

Offers fully managed cloud file shares that you can access from anywhere via the industry standard Server Message Block (SMB) protocol.

9.1. Dependency Setup

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-storage-blob</artifactId> (1)
    </dependency>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-storage-file-share</artifactId> (2)
    </dependency>
</dependencies>
1 Only required when you’re using Azure Storage Blob.
2 Only required when you’re using Azure Storage File Share.

9.2. Configuration

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, please refer to Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.
Table 13. Configurable properties of spring-cloud-azure-starter-storage-blob
Property Default Description

spring.cloud.azure.storage.blob.enabled

true

Whether an Azure Blob Storage Service is enabled

spring.cloud.azure.storage.blob.endpoint

Uri to connect Azure Blob Storage

spring.cloud.azure.storage.blob.account-key

Private key to connect Azure Blob Storage

spring.cloud.azure.storage.blob.account-name

Azure Storage Account Name

Table 14. Configurable properties of spring-cloud-azure-starter-storage-file-share
Property Default Description

spring.cloud.azure.storage.fileshare.enabled

true

Whether Azure File Storage Service is enabled

spring.cloud.azure.storage.fileshare.endpoint

Uri to connect Azure File Storage

spring.cloud.azure.storage.fileshare.account-key

Private key to connect Azure File Storage

spring.cloud.azure.storage.fileshare.account-name

Azure Storage Account Name

9.3. Basic Usage

Provide the properties below in your configuration file.

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

9.3.1. 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.

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

You can use the annotation of @Value("azure-file://[your-fileshare-name]/[your-file-name]") to autowire a file Resource.

@Value("azure-file://[your-fileshare-name]/[your-file-name]")
private Resource storageResource;
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 implementation class AzureStorageBlobProtocolResolver of ResourcePatternResolver to search blob resource, and AzureStorageFileProtocolResolver of ResourcePatternResolver to search file resource

  • Pattern search, the searchPattern should start with azure-blob:// or azure-file://. Such as azure-blob:///, it means list all blobs in all containers; azure-blob://demo-container/**, it means list all blobs in the demo-container container, including any sub-folder.

  • Location search, the searchLocation should start with azure-blob:// or azure-file://, 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");

9.3.2. Handling with resource

Download data from specific resource.

You can download a resource from Azure Blob or file storage 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 stream from blob resource
InputStream inputblobStream = storageBlobResource.getInputStream();
// download data as stream from 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.

@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 blob
try (OutputStream blobos = ((WritableResource) this.storageBlobResource).getOutputStream()) {
  blobos.write(data.getBytes());
}
// upload string data to file
try (OutputStream fileos = ((WritableResource) this.storageFileResource).getOutputStream()) {
  fileos.write(data.getBytes());
}

9.3.3. Multipart upload

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

9.4. Samples

Please refer to storage-blob-sample and storage-file-sample for more details.

10. Secret Management

spring-cloud-azure-starter-keyvault-secrets adds Azure Key Vault as one of the Spring PropertySource, so secrets stored in Azure Key Vault could be easily used and conveniently accessed like other externalized configuration property, e.g. properties in files.

10.1. Dependency Setup

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

10.2. Configuration

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, please refer to Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.
Table 15. Configurable properties of spring-cloud-azure-starter-keyvault-secrets
Property Description

spring.cloud.azure.keyvault.secret.endpoint

Key Vault uri

spring.cloud.azure.keyvault.secret.service-version

Service version

spring.cloud.azure.keyvault.secret.property-source-enabled

Enable this property source

spring.cloud.azure.keyvault.secret.property-sources

Multiple property source

spring.cloud.azure.keyvault.secret.property-sources[].name

Name of this property source

spring.cloud.azure.keyvault.secret.property-sources[].endpoint

Key Vault uri

spring.cloud.azure.keyvault.secret.property-sources[].service-version

Service version

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

Whether the secret name is case-sensitive

spring.cloud.azure.keyvault.secret.property-sources[].secret-keys

The supported secret names. If not configured, it will retrieve all secret names.

spring.cloud.azure.keyvault.secret.property-sources[].refresh-interval

Refresh interval

10.3. Basic Usage

10.3.1. One Property Source

Property Configuration

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

spring:
  cloud:
    azure:
      profile:
        tenant-id: ${AZURE_TENANT_ID}
      credential:
        client-id: ${AZURE_CLIENT_ID}
        client-secret: ${AZURE_CLIENT_SECRET}
      keyvault:
        secret:
          property-source-enabled: true
          endpoint: ${AZURE_KEYVAULT_ENDPOINT}

If your application is authenticated by other methods like Managed Identity or Azure CLI, properties like tenant-id, client-id, client-secret are not necessary. But if these properties are configured, then these properties have higher priority. Please refer to Authentication section to get more information.

Java Code
@SpringBootApplication
public class SampleApplication implements CommandLineRunner {

    @Value("${sampleProperty}")
    private String sampleProperty;

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

    @Override
    public void run(String... args) {
        System.out.println("sampleProperty: " + sampleProperty);
    }
}

10.3.2. Multiple Property Source

Property Configuration
spring:
  cloud:
    azure:
      keyvault:
        secret:
          property-source-enabled: true
          property-sources:
          -
            name: key-vault-1
            endpoint: ${ENDPOINT_1}
            profile:
              tenant-id: ${AZURE_TENANT_ID_1}
            credential:
              client-id: ${AZURE_CLIENT_ID_1}
              client-secret: ${AZURE_CLIENT_SECRET_1}
          -
            name: key-vault-2
            endpoint: ${ENDPOINT_2}
            profile:
              tenant-id: ${AZURE_TENANT_ID_2}
            credential:
              client-id: ${AZURE_CLIENT_ID_2}
              client-secret: ${AZURE_CLIENT_SECRET_2}

Same as above, properties like tenant-id, client-id, client-secret are not necessary if authenticate by other methods.

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);
    }

}

10.4. Advanced Usage

10.4.1. Special Characters in Property Name

Key Vault secret name only support characters in [0-9a-zA-Z-]. Refs: Vault-name and Object-name. If your property name contains other characters, you can use these workarounds:

Use - Instead of . In Secret Name

. is not supported in secret name. If your application have property name which contain ., like spring.datasource.url, just replace . to - when save 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 property value.

This method can not satisfy 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 property value, spring.datasource-url is not supported. To handle this case, please refer to the following section: Use property placeholders.
Use Property Placeholders

For example: setting this property in your application.properties:

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

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

10.4.2. Case Sensitive

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

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

11. Spring Data Support

11.1. Spring Data CosmosDB Support

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

Connect to Cosmos DB using Spring Data and CosmosDB libraries.

11.2. Dependency Setup

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

11.3. Configuration

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, please refer to Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.
Table 16. Configurable properties of spring-cloud-azure-starter-data-cosmos
Property Default Description

spring.cloud.azure.cosmos.enabled

true

Whether Azure Cosmos Service is enabled.

spring.cloud.azure.cosmos.database

The CosmosDB database id

spring.cloud.azure.cosmos.endpoint

Uri to connect CosmosDB

spring.cloud.azure.cosmos.key

PrivateKey to connect CosmosDB

spring.cloud.azure.cosmos.credential.client-certificate-password

Password of the certificate file.

spring.cloud.azure.cosmos.credential.client-certificate-path

Path of a PEM certificate file to use when performing service principal authentication with Azure.

spring.cloud.azure.cosmos.credential.client-id

Client id to use when performing service principal authentication with Azure.

spring.cloud.azure.cosmos.credential.client-secret

Client secret to use when performing service principal authentication with Azure.

spring.cloud.azure.cosmos.credential.managed-identity-client-id

Client id to use when using managed identity to authenticate with Azure.

spring.cloud.azure.cosmos.credential.password

Password to use when performing username/password authentication with Azure.

spring.cloud.azure.cosmos.credential.username

Username to use when performing username/password authentication with Azure.

spring.cloud.azure.cosmos.populate-query-metrics

false

Populate Diagnostics Strings and Query metrics.

spring.cloud.azure.cosmos.consistency-level

Consistency levels in Azure Cosmos DB

11.4. Key concepts

  • Spring Data CrudRepository and ReactiveCrudRepository basic CRUD functionality

    • save

    • findAll

    • findOne by Id

    • deleteAll

    • delete by Id

    • delete entity

  • Spring Data @Id annotation. There’re 2 ways to map a field in domain class to id of Azure Cosmos DB document.

    • annotate a field in domain class with @Id, this field will be mapped to document id in Cosmos DB.

    • set name of this field to id, this field will be mapped to document id in Cosmos DB. [Note] if both way applied,

  • Custom collection Name. 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 partition key field, just annotate it with @PartitionKey. When you do CRUD operation, please specify your partition value. For more sample on partition CRUD, please refer to test here

  • Supports Spring Data custom query find operation.

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

  • Supports List and nested type in domain class.

11.5. Basic Usage

11.5.1. Use private key to access CosmosDB

The simplest way to connect CosmosDB with spring-cloud-azure-starter-data-cosmos is primary key, add below properties, and you are good to go.

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

11.5.2. Define an entity

Define a simple entity as Document in Cosmos DB.

@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);
    }
}

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

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

11.5.3. Create repositories

Extends ReactiveCosmosRepository interface, which provides Spring Data repository support.

@Repository
public interface UserRepository extends ReactiveCosmosRepository<User, String> {

    Flux<User> findByFirstName(String firstName);
}

So far ReactiveCosmosRepository provides basic save, delete and find operations. More operations will be supported later.

11.5.4. Create an Application class

Here create 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 is not 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();
    }
}

Autowired UserRepository interface, then can do save, delete and find operations.

11.6. Samples

Please refer to azure-spring-boot-samples for more details.

Besides, using this Azure Cosmos DB Spring Boot Starter, you can directly use Spring Data for Azure Cosmos DB package for more complex scenarios. Please refer to Spring Data for Azure Cosmos DB for more details.

12. Spring Security Support

12.1. Spring Security With Azure AD

When you are 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 (aad-starter for short) provides the most optimal way to connect your web application to an Azure Active Directory(AAD for short) tenant and protect resource server with AAD. It uses the Oauth 2.0 protocol to protect web applications and resource servers.

12.1.1. Dependency Setup

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

12.1.2. Configuration

Table 17. Configurable properties of spring-cloud-azure-starter-active-directory
Property Description

spring.cloud.azure.active-directory.app-id-uri

It used in resource server, used to validate the audience in access_token. access_token is valid only when the audience in access_token equal to client-id or app-id-uri

spring.cloud.azure.active-directory.application-type

Refer to Application type.

spring.cloud.azure.active-directory.authorization-clients

A map configure the resource APIs the application is going to visit. Each item corresponding to one resource API the application is going to visit. In Spring code, each item corresponding to one OAuth2AuthorizedClient object

spring.cloud.azure.active-directory.authorization-clients.AZURE_CLIENT_NAME.authorization-grant-type

Type of authorization client. Supported types are authorization_code (default type for webapp), on_behalf_of (default type for resource-server), client_credentials.

spring.cloud.azure.active-directory.authorization-clients.AZURE_CLIENT_NAME.on-demand

This is used for incremental consent. The default value is false. If it’s true, it’s not consent when user login, when application needs the additional permission, incremental consent is performed with one OAuth2 authorization code flow.

spring.cloud.azure.active-directory.authorization-clients.AZURE_CLIENT_NAME.scopes

API permissions of a resource server that the application is going to acquire.

spring.cloud.azure.active-directory.credential.client-id

Registered application ID in Azure AD.

spring.cloud.azure.active-directory.credential.client-secret

Client secret of the registered application.

spring.cloud.azure.active-directory.post-logout-redirect-uri

Redirect uri for posting log-out.

spring.cloud.azure.active-directory.profile.environment.active-directory-endpoint

Base uri for authorization server, the default value is login.microsoftonline.com/.

spring.cloud.azure.active-directory.profile.environment.microsoft-graph-endpoint

Microsoft graph endpoint. The default value is graph.microsoft.com/.

spring.cloud.azure.active-directory.profile.tenant-id

Azure Tenant ID.

spring.cloud.azure.active-directory.redirect-uri-template

Used by the authorization server to return responses containing authorization credentials to the client via the resource owner user-agent.

spring.cloud.azure.active-directory.resource-server.claim-to-authority-prefix-map

Claim to authority prefix map. Default map is: "scp" -> "SCOPE_", "roles" -> APPROLE_.

spring.cloud.azure.active-directory.resource-server.principal-claim-name

Principal claim name. Default value is "sub".

spring.cloud.azure.active-directory.user-group.allowed-group-ids

Users' group id can be use in @PreAuthorize("hasRole('ROLE_group_id_1')"). Not all group id will take effect, only group id configured in this property will take effect. If this property’s value is all, then all group id will take effect.

spring.cloud.azure.active-directory.user-group.allowed-group-names

Users' group name can be use in @PreAuthorize("hasRole('ROLE_group_name_1')"). Not all group name will take effect, only group names configured in this property will take effect.

spring.cloud.azure.active-directory.user-group.use-transitive-members

Whether to use /v1.0/me/transitiveMemberOf instead of /v1.0/me/memberOf to get groups.

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:

Property Example 1: Application Type

This property(spring.cloud.azure.active-directory.application-type) is optional, its value can be inferred by dependencies, only web_application_and_resource_server must be configured manually: spring.cloud.azure.active-directory.application-type=web_application_and_resource_server.

Table 18. 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 Default 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

Property Example 2: Use Azure China Instead of Azure Global
  • Step 1: Add property in application.yml

spring:
  cloud:
    azure:
      active-directory:
        base-uri: https://login.partner.microsoftonline.cn
        graph-base-uri: https://microsoftgraph.chinacloudapi.cn
Property Example 3: Use Group Name Or Group ID To Protect Some Method in Web Application
  • Step 1: Add property in application.yml

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
  • Step 2: Add @EnableGlobalMethodSecurity(prePostEnabled == true) in web application:

@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
    }
}

Then we can protect the method by @PreAuthorize annotation:

@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";
    }
}
  • Step 1: Add property in application.yml

spring:
  cloud:
    azure:
      active-directory:
        authorization-clients:
          graph:
            scopes: https://graph.microsoft.com/Analytics.Read, email
          arm: # client registration id
            on-demand: true  # means incremental consent
            scopes: https://management.core.windows.net/user_impersonation
  • Step 2: Write Java code:

After these steps. arm’s scopes (management.core.windows.net/user_impersonation) doesn’t need to be consented at login time. When user request `/arm endpoint, user need to consent the scope. That’s incremental consent means.

After the scopes have been consented, AAD server will remember that this user has already granted the permission to the web application. So incremental consent will not happen anymore after user consented.

Property Example 5: Client credential flow In Resource Server Visiting Resource Servers
  • Step 1: Add property in application.yml

spring:
  cloud:
    azure:
      active-directory:
        authorization-clients:
          webapiC:                          # When authorization-grant-type is null, on behalf of flow is used by default
            authorization-grant-type: client_credentials
            scopes:
                - <Web-API-C-app-id-url>/.default
  • Step 2: Write Java code:

12.1.3. Basic Usage

Usage 1: 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:

Standalone Web Application

The tailing / cannot be omitted.

web-application-set-redirect-uri-1.png web-application-set-redirect-uri-2.png

  • Step 2: Add the following dependencies in your pom.xml.

<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>
  • Step 3: Add properties in application.yml.

spring:
  cloud:
    azure:
      active-directory:
        profile:
          tenant-id: ${AZURE_TENANT_ID}
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
  • Step 4: Write your Java code:

The AADWebSecurityConfigurerAdapter contains necessary web security configuration for aad-starter.

(A). DefaultAADWebSecurityConfigurerAdapter is configured automatically if you not provide one.

(B). You can provide one by extending AADWebSecurityConfigurerAdapter and call super.configure(http) explicitly in the configure(HttpSecurity http) function. Here is an example:

    @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
        }
    }
Usage 2: Web Application Accessing Resource Servers

System diagram:

web-application-visiting-resource-servers.png

  • Step 1: Make sure redirect URI has been set.

  • Step 2: Add the following dependencies in you pom.xml.

<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>
  • Step 3: Add properties in application.yml:

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.

  • Step 4: Write your Java code:

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);
    }
}

Here, graph is the client name configured in step 2. OAuth2AuthorizedClient contains access_token. access_token can be used to access resource server.

Usage 3: 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:

Standalone resource server usage

To use aad-starter in this scenario, we need these steps:

  • Step 1: Add the following dependencies in you pom.xml.

<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>
  • Step 2: Add properties in application.yml:

spring:
  cloud:
    azure:
      active-directory:
        client-id: <client-id>
        app-id-uri: <app-id-uri>

Both client-id and app-id-uri can be used to verify access token. app-id-uri can be got in Azure Portal:

get-app-id-uri-1.png get-app-id-uri-2.png

  • Step 3: Write Java code:

The AADResourceServerWebSecurityConfigurerAdapter contains necessary web security configuration for resource server.

(A). DefaultAADResourceServerWebSecurityConfigurerAdapter is configured automatically if you not provide one.

(B). You can provide one by extending AADResourceServerWebSecurityConfigurerAdapter and call super.configure(http) explicitly in the configure(HttpSecurity http) function. Here is an example:

@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());
    }
}
Usage 4: Resource Server Visiting Other Resource Servers

This scenario support visit other resource servers in resource servers.

System diagram:

resource-server-visiting-other-resource-servers.png

To use aad-starter in this scenario, we need these steps:

  • Step 1: Add the following dependencies in you pom.xml.

<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>
  • Step 2: Add properties in application.yml:

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}
        authorization-clients:
          graph:
            scopes:
              - https://graph.microsoft.com/User.Read
  • Step 3: Write Java code:

Using @RegisteredOAuth2AuthorizedClient to access related resource server:

public class SampleController {
    @PreAuthorize("hasAuthority('SCOPE_Obo.Graph.Read')")
    @GetMapping("call-graph")
    public String callGraph(@RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient graph) {
        return callMicrosoftGraphMeEndpoint(graph);
    }
}
Usage 5: Web Application and Resource Server in One Application

This scenario supports Web application and Resource server in one application.

To use aad-starter in this scenario, we need these steps:

  • Step 1: Add the following dependencies in you pom.xml.

<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>
  • Step 2: Add properties in application.yml:

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
  • Step 3: Write Java code:

Configure multiple HttpSecurity instances, AADOAuth2SecurityMultiConfig 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
        }
    }
}

12.1.4. Advanced Features

Support Access Control by ID Token in Web Application

This starter supports creating GrantedAuthority from id_token’s roles claim to allow using id_token for authorization in web application. Developers can use the appRoles feature of Azure Active Directory to create roles claim and implement access control.

The roles claim generated from appRoles is decorated with prefix APPROLE_. When using appRoles as roles claim, please avoid configuring group attribute as roles at the same time. The latter will override the claim to contain group information instead of appRoles. Below configuration in manifest should be avoided:
{
    "optionalClaims": {
        "idtoken": [{
            "name": "groups",
            "additionalProperties": ["emit_as_roles"]
        }]
    }
}

Follow the guide to add app roles in your application and assign to users or groups.

  • Step 1: Add below appRoles configuration in your application’s manifest:

{
    "appRoles": [
        {
        "allowedMemberTypes": [
          "User"
        ],
        "displayName": "Admin",
        "id": "2fa848d0-8054-4e11-8c73-7af5f1171001",
        "isEnabled": true,
        "description": "Full admin access",
        "value": "Admin"
        }
    ]
}
  • Step 2: Write Java code:

class Demo {
    @GetMapping("Admin")
    @ResponseBody
    @PreAuthorize("hasAuthority('APPROLE_Admin')")
    public String admin() {
        return "Admin message";
    }
}
Support Conditional Access in Web Application

This starter supports Conditional Access policy. By using Conditional Access policies, you can apply the right access controls when needed to keep your organization secure. Access controls has many concepts, Block Access and Grant Access are important. In some scenarios, this stater will help you complete Grant Access controls.

In Resource server visiting other resource server scenario(For better description, we think that resource server with OBO function as webapiA and the other resource servers as webapiB), When we configure the webapiB application with Conditional Access(such as multi-factor authentication), this stater will help us send the Conditional Access information of the webapiA to the web application and the web application will help us complete the Conditional Access Policy. As shown below:

aad-conditional-access-flow.png

We can use our sample to create a Conditional Access scenario.

  • Step 1: Follow the guide to create conditional access policy for webapiB.

aad-create-conditional-access

aad-conditional-access-add-application

aad-create-conditional-access

Support Setting Redirect-URI-Template

Developers can customize the redirect-uri.

redirect-uri

  • Step 1: Add redirect-uri-template properties in application.yml.

spring:
  cloud:
    azure:
      active-directory
        redirect-uri-template: ${REDIRECT-URI-TEMPLATE}
  • Step 2: Update the configuration of the azure cloud platform in the portal.

We need to configure the same redirect-uri as application.yml:

web-application-config-redirect-uri

  • Step 3: Write your Java code:

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

@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();
    }
}

12.1.5. Samples

Please refer to azure-spring-boot-samples for more details.

12.2. Spring Security With Azure AD 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.

12.2.1. Dependency Setup

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

12.2.2. Configuration

Table 19. Configurable properties of spring-cloud-azure-starter-active-directory-b2c
Parameter Description

spring.cloud.azure.active-directory.b2c.base-uri

Base uri for authorization server, if both tenant and baseUri are configured at the same time, only baseUri takes effect.

spring.cloud.azure.active-directory.b2c.client-id

The registered application ID in Azure AD B2C.

spring.cloud.azure.active-directory.b2c.client-secret

The client secret of a registered application.

spring.cloud.azure.active-directory.b2c.authorization-clients

A map to list all authorization clients created on Azure Portal.

spring.cloud.azure.active-directory.b2c.login-flow

The key name of sign in user flow.

spring.cloud.azure.active-directory.b2c.logout-success-url

The target URL after a successful logout.

spring.cloud.azure.active-directory.b2c.tenant(Deprecated)

The Azure AD B2C’s tenant name, this is only suitable for Global cloud.

spring.cloud.azure.active-directory.b2c.tenant-id

The Azure AD B2C’s tenant id.

spring.cloud.azure.active-directory.b2c.user-flows

A map to list all user flows defined on Azure Portal.

spring.cloud.azure.active-directory.b2c.user-name-attribute-name

The attribute name of the username.

For full configurations, check the Appendix page.

12.2.3. Basic Usage

A web application is any web based application that allows user to login 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.

B2C Web application & Web Api Overall

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.

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

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

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

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

  • Step 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.

  • Step 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.

  • Step 7: Grant admin consent for Graph permissions. Add Graph permissions

  • Step 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>
  • Step 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}
  • Step 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.

  • Step 11: Build and test your app

Let Webapp run on port 8080.

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

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

  3. 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.

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

  • Step 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.

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

  • Step 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.

  • Step 5: Select Manifest on your left, and then paste the below 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"
}

Configure WebApiA appRoles

  • Step 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.

  • Step 7: Grant admin consent for WebApiA permissions. Add WebApiA permission

  • Step 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>
  • Step 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
  • Step 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();
    }
}
  • Step 11: Please refer to Accessing a resource server section to write your WebApiA Java code.

  • Step 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 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.

<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>
  • Step 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 are using v1.0 token, please configure app-id-uri for `aud` verification
          credential:
            client-id: ${AZURE_CLIENT_ID}           # If you are using v2.0 token, please configure client-id for `aud` verification
  • Step 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());
    }
}
  • Step 6: Build and test your app

Let WebApiA run on port 8081. Get the access token for webApiA resource and access 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.

  • Step 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"
}

Configure WebApiB appRoles

  • Step 2: Grant admin consent for WebApiB permissions. Add WebApiB permission

  • Step 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>
  • Step 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
  • Step 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();
    }
}
  • Step 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 localhost:8081/webApiA/webApiB/sample as the Bearer authorization header.

12.2.4. Samples

Please refer to azure-spring-boot-samples for more details.

13. Spring Integration Support

Spring Integration Extension for Azure provides Spring Integration adapters for the various services provided by the Azure SDK for Java. Below is a list of supported adapters:

  • spring-cloud-azure-starter-integration-eventhbus

  • spring-cloud-azure-starter-integration-servicebus

  • spring-cloud-azure-starter-integration-storage-queue

Provide Spring Integration support for these Azure services: Event Hubs, Service Bus, Storage Queue.

13.1. Spring Integration with Azure Event Hubs

13.1.1. 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.

RxJava support APIs is dropped from version 4.0.0. Please refer to Javadoc for details.

13.1.2. Dependency Setup

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

13.1.3. Configuration

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

This starter provides the following 2 parts of configuration options:

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.azure.eventhubs.event-hub-name.
Azure Common Configuration Options

Below properties can also be configured with the default Spring Cloud Azure unified properties by changing the prefix from spring.cloud.azure.eventhubs to spring.cloud.azure.

Table 20. Common configurable properties of spring-cloud-azure-starter-integration-eventhubs
Property Type Description

spring.cloud.azure.eventhubs.enabled

boolean

Whether Azure Event Hubs service is enabled.

spring.cloud.azure.eventhubs.credential.*

NA

Properties used for getting token credential.

spring.cloud.azure.eventhubs. credential.clientId

String

Client id to use when performing service principal authentication with Azure.

spring.cloud.azure.eventhubs. credential.clientSecret

String

Client secret to use when performing service principal authentication with Azure.

spring.cloud.azure.eventhubs. credential.clientCertificatePath

String

Path of a PEM certificate file to use when performing service principal authentication with Azure.

spring.cloud.azure.eventhubs. credential.clientCertificatePassword

String

Password of the certificate file.

spring.cloud.azure.eventhubs. credential.username

String

Username to use when performing username/password authentication with Azure.

spring.cloud.azure.eventhubs. credential.password

String

Password to use when performing username/password authentication with Azure.

spring.cloud.azure.eventhubs. credential.managedIdentityClientId

String

Client id to use when using managed identity to authenticate with Azure.

spring.cloud.azure.eventhubs.profile.*

String

Properties related to an Azure subscription.

spring.cloud.azure.eventhubs.profile.tenantId

String

Tenant id for Azure resources.

spring.cloud.azure.eventhubs. profile.subscriptionId

String

Subscription id to use when connecting to Azure resources.

spring.cloud.azure.eventhubs.profile.cloud

AzureProfileAware.CloudType

Name of the Azure cloud to connect to.

spring.cloud.azure.eventhubs. profile.environment.*

NA

Properties to Azure services, such as endpoints, resource ids, etc.

spring.cloud.azure.eventhubs. profile.environment.activeDirectoryEndpoint

String

The Azure Active Directory endpoint to connect to.

spring.cloud.azure.eventhubs.resource.*

String

Metadata defining an Azure resource.

spring.cloud.azure.eventhubs. resource.resourceGroup

String

Name of the Azure resource group.

spring.cloud.azure.eventhubs. resource.resourceId

String

ID of the Azure resource group.

spring.cloud.azure.eventhubs.resource.region

String

Name of region.

spring.cloud.azure.eventhubs. client.transportType

AmqpTransportType

Transport type switches available for AMQP protocol.

spring.cloud.azure.eventhubs.retry.*

NA

Retry properties.

spring.cloud.azure.eventhubs. retry.backoff.*

NA

Backoff properties when a retry fails.

spring.cloud.azure.eventhubs. retry.backoff.delay

Duration

Amount of time to wait between retry attempts.

spring.cloud.azure.eventhubs. retry.backoff.maxDelay

Duration

Maximum permissible amount of time between retry attempts.

spring.cloud.azure.eventhubs. retry.backoff.multiplier

Double

Multiplier used to calculate the next backoff delay. If positive, then used as a multiplier for generating the next delay for backoff.

spring.cloud.azure.eventhubs. retry.maxAttempts

Integer

The maximum number of attempts.

spring.cloud.azure.eventhubs.retry.timeout

Duration

Amount of time to wait until a timeout.

spring.cloud.azure.eventhubs.proxy.*

NA

Common proxy properties.

spring.cloud.azure.eventhubs.proxy.type

String

Type of the proxy.

spring.cloud.azure.eventhubs.proxy.hostname

String

The host of the proxy.

spring.cloud.azure.eventhubs.proxy.port

Integer

The port of the proxy.

spring.cloud.azure.eventhubs. proxy.authenticationType

String

Authentication type used against the proxy.

spring.cloud.azure.eventhubs.proxy.username

String

Username used to authenticate with the proxy.

spring.cloud.azure.eventhubs.proxy.password

String

Password used to authenticate with the proxy.

Azure Event Hubs Client Configuration Options

Below options are used to configure Azure Event Hubs SDK Client.

Table 21. Client configurable properties of spring-cloud-azure-starter-integration-storage-queue
Property Type Description

spring.cloud.azure.eventhubs.connection-string

String

Event Hubs Namespace connection string value.

spring.cloud.azure.eventhubs.namespace

String

Event Hubs Namespace value.

spring.cloud.azure.eventhubs.domainName

String

Domain name of an Azure Event Hubs Namespace value.

spring.cloud.azure.eventhubs.eventHubName

String

Name of an Event Hub entity.

spring.cloud.azure.eventhubs.customEndpointAddress

String

Custom Endpoint address.

spring.cloud.azure.eventhubs.isSharedConnection

Boolean

Whether to use the same connection for different Event Hub producer / consumer client.

spring.cloud.azure.eventhubs. processor.checkpointStore.*

NA

Blob checkpoint store configuration options.

spring.cloud.azure.eventhubs. processor.checkpointStore.createContainerIfNotExists

Boolean

If allowed creating container if not exists.

spring.cloud.azure.eventhubs. processor.checkpointStore.customerProvidedKey

String

Base64 encoded string of the encryption key.

spring.cloud.azure.eventhubs. processor.checkpointStore.encryptionScope

String

Encryption scope to encrypt blob contents on the server.

spring.cloud.azure.eventhubs. processor.checkpointStore.serviceVersion

BlobServiceVersion

The versions of Azure Storage Blob supported by this client library.

spring.cloud.azure.eventhubs. processor.checkpointStore.blobName

String

Storage blob name.

spring.cloud.azure.eventhubs. processor.checkpointStore.containerName

String

Storage container name.

13.1.4. Basic Usage

Send messages to Azure Event Hubs

Step 1. Fill the credential configuration options.

  • For credentials as connection string, configure below properties in application.yml:

spring:
  cloud:
    azure:
      eventhubs:
        connection-string: ${AZURE_SERVICE_BUS_CONNECTION_STRING}
  • For credentials as MSI, configure below properties in application.yml:

spring:
  cloud:
    azure:
      credential:
        managed-identity-client-id: ${AZURE_CLIENT_ID}
      profile:
        tenant-id: ${AZURE_TENANT_ID}
      eventhubs:
        namespace: ${AZURE_SERVICE_BUS_NAMESPACE}
  • For credentials as service principal, configure below 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}

Step 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 queueOperation) {
        DefaultMessageHandler handler = new DefaultMessageHandler(EVENTHUB_NAME, queueOperation);
        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;
    }
}

Step 3. Create a Message gateway binding with the message handler created in the last step via a message channel

class Demo{
    @Autowired
    EventHubOutboundGateway messagingGateway;

    @MessagingGateway(defaultRequestChannel = OUTPUT_CHANNEL)
    public interface EventHubOutboundGateway {
        void send(String text);
    }
}

Step 4. Send messages using the gateway

class Demo{
    public void demo() {
        this.messagingGateway.send(message);
    }
}
Receive messages from Azure Event Hubs

Step 1. Fill the credential configuration options.

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

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 MessageChannel input() {
        return new DirectChannel();
    }
}

Step 3. Create EventHubsInboundChannelAdapter with the bean of EventHubsProcessorContainer to receive messages to Event Hubs.

@Bean
class Demo{
    public EventHubsInboundChannelAdapter messageChannelAdapter(
            @Qualifier(INPUT_CHANNEL) MessageChannel inputChannel,
            EventHubsProcessorContainer processorContainer) {
        CheckpointConfig config = new CheckpointConfig(CheckpointMode.MANUAL);

        EventHubsInboundChannelAdapter adapter =
                new EventHubsInboundChannelAdapter(processorContainer, EVENTHUB_NAME,
                        CONSUMER_GROUP, config);
        adapter.setOutputChannel(inputChannel);
        return adapter;
    }
}

Step 4. Create a message receiver binding with EventHubsInboundChannelAdapter 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()
                .doOnSuccess(s -> LOGGER.info("Message '{}' successfully checkpointed", message))
                .doOnError(e -> LOGGER.error("Error found", e))
                .subscribe();
    }
}
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.

Table 22. Mapping between Event Hubs Properties and Spring Headers
Event Hubs Event Properties Spring Message Header Constants Type Description

Enqueued time

com.azure.spring.eventhubs.support.EventHubsHeaders#ENQUEUED_TIME

Instant

The instant, in UTC, of when the event was enqueued in the Event Hub partition.

Offset

com.azure.spring.eventhubs.support.EventHubsHeaders#OFFSET

Long

The offset of the event when it was received from the associated Event Hub partition.

Partition key

com.azure.spring.messaging.AzureHeaders#PARTITION_KEY

String

The partition hashing key if it was set when originally publishing the event.

Partition id

com.azure.spring.messaging.AzureHeaders#RAW_PARTITION_ID

String

The partition id of the Event Hub.

Sequence number

com.azure.spring.eventhubs.support.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

com.azure.spring.eventhubs.support.EventHubsHeaders#LAST_ENQUEUED_EVENT_PROPERTIES

LastEnqueuedEventProperties

The properties of the last enqueued event in this partition.

NA

com.azure.spring.messaging.AzureHeaders#CHECKPOINTER

com.azure.spring.messaging.checkpoint.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.

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

13.1.5. Samples

Please refer to azure-spring-boot-samples for more details.

13.2. Spring Integration with Azure Service Bus

13.2.1. 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.

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

13.2.2. Dependency Setup

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

13.2.3. Configuration

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

Below properties can also be configured with the default Spring Cloud Azure unified properties by changing the prefix from spring.cloud.azure.servicebus to spring.cloud.azure.

Table 23. Common 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.credential.*

NA

Properties used for getting token credential.

spring.cloud.azure.servicebus. credential.clientId

String

Client id to use when performing service principal authentication with Azure.

spring.cloud.azure.servicebus. credential.clientSecret

String

Client secret to use when performing service principal authentication with Azure.

spring.cloud.azure.servicebus. credential.clientCertificatePath

String

Path of a PEM certificate file to use when performing service principal authentication with Azure.

spring.cloud.azure.servicebus. credential.clientCertificatePassword

String

Password of the certificate file.

spring.cloud.azure.servicebus. credential.username

String

Username to use when performing username/password authentication with Azure.

spring.cloud.azure.servicebus. credential.password

String

Password to use when performing username/password authentication with Azure.

spring.cloud.azure.servicebus. credential.managedIdentityClientId

String

Client id to use when using managed identity to authenticate with Azure.

spring.cloud.azure.servicebus.profile.*

String

Properties related to an Azure subscription.

spring.cloud.azure.servicebus. profile.tenantId

String

Tenant id for Azure resources.

spring.cloud.azure.servicebus. profile.subscriptionId

String

Subscription id to use when connecting to Azure resources.

spring.cloud.azure.servicebus.profile.cloud

AzureProfileAware.CloudType

Name of the Azure cloud to connect to.

spring.cloud.azure.servicebus. profile.environment.*

NA

Properties to Azure services, such as endpoints, resource ids, etc.

spring.cloud.azure.servicebus. profile.environment.activeDirectoryEndpoint

String

The Azure Active Directory endpoint to connect to.

spring.cloud.azure.servicebus.resource.*

String

Metadata defining an Azure resource.

spring.cloud.azure.servicebus. resource.resourceGroup

String

Name of the Azure resource group.

spring.cloud.azure.servicebus. resource.resourceId

String

ID of the Azure resource group.

spring.cloud.azure.servicebus.resource.region

String

Name of region.

spring.cloud.azure.servicebus. client.transportType

AmqpTransportType

Transport type switches available for AMQP protocol.

spring.cloud.azure.servicebus.retry.*

NA

Retry properties.

spring.cloud.azure.servicebus. retry.backoff.*

NA

Backoff properties when a retry fails.

spring.cloud.azure.servicebus. retry.backoff.delay

Duration

Amount of time to wait between retry attempts.

spring.cloud.azure.servicebus. retry.backoff.maxDelay

Duration

Maximum permissible amount of time between retry attempts.

spring.cloud.azure.servicebus. retry.backoff.multiplier

Double

Multiplier used to calculate the next backoff delay. If positive, then used as a multiplier for generating the next delay for backoff.

spring.cloud.azure.servicebus. retry.maxAttempts

Integer

The maximum number of attempts.

spring.cloud.azure.servicebus.retry.timeout

Duration

Amount of time to wait until a timeout.

spring.cloud.azure.servicebus.proxy.*

NA

Common proxy properties.

spring.cloud.azure.servicebus.proxy.type

String

Type of the proxy.

spring.cloud.azure.servicebus.proxy.hostname

String

The host of the proxy.

spring.cloud.azure.servicebus.proxy.port

Integer

The port of the proxy.

spring.cloud.azure.servicebus. proxy.authenticationType

String

Authentication type used against the proxy.

spring.cloud.azure.servicebus.proxy.username

String

Username used to authenticate with the proxy.

spring.cloud.azure.servicebus.proxy.password

String

Password used to authenticate with the proxy.

Azure Service Bus Client Configuration Options

Below options are used to configure Azure Service Bus SDK Client.

Table 24. Client configurable properties of spring-cloud-azure-starter-integration-servicebus
Property Type Description

spring.cloud.azure.servicebus.connection-string

String

Service Bus Namespace connection string value.

spring.cloud.azure.servicebus.namespace

String

Service Bus Namespace value.

spring.cloud.azure.servicebus.domainName

String

Domain name of an Azure Service Bus Namespace value.

spring.cloud.azure.servicebus.entityName

String

Entity name of Azure Service Bus queue or topic.

spring.cloud.azure.servicebus.entityType

ServiceBusEntityType

Entity type of Azure Service Bus queue or topic.

spring.cloud.azure.servicebus. crossEntityTransactions

Boolean

Enable cross entity transaction on the connection to Service bus.

13.2.4. Basic Usage

Send messages to Azure Service Bus

Step 1. Fill the credential configuration options.

  • For credentials as connection string, configure below properties in application.yml:

spring:
  cloud:
    azure:
      servicebus:
        connection-string: ${AZURE_SERVICE_BUS_CONNECTION_STRING}
  • For credentials as MSI, configure below properties in application.yml:

spring:
  cloud:
    azure:
      credential:
        managed-identity-client-id: ${AZURE_CLIENT_ID}
      profile:
        tenant-id: ${AZURE_TENANT_ID}
      servicebus:
        namespace: ${AZURE_SERVICE_BUS_NAMESPACE}
  • For credentials as service principal, configure below 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}

Step 2. Create DefaultMessageHandler with the bean of ServiceBusTemplate to send messages to Service Bus, set the entity type for the ServiceBusTemplate.

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;
    }
}

Step 3. Create a Message gateway binding with the message handler created in the last stop via a message channel

class Demo{
    @Autowired
    QueueOutboundGateway messagingGateway;

    @MessagingGateway(defaultRequestChannel = OUTPUT_CHANNEL)
    public interface QueueOutboundGateway {
        void send(String text);
    }
}

Step 4. Send messages using the gateway

class Demo{
    public void demo() {
        this.messagingGateway.send(message);
    }
}
Receive messages from Azure Service Bus

Step 1. Fill the credential configuration options.

Step 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();
    }
}

Step 3. Create ServiceBusInboundChannelAdapter with the bean of ServiceBusProcessorContainer to receive messages to Service Bus.

class Demo{
    private static final String QUEUE_NAME = "queue1";

    @Bean
    public ServiceBusInboundChannelAdapter queueMessageChannelAdapter(
        @Qualifier(INPUT_CHANNEL) MessageChannel inputChannel, ServiceBusProcessorContainer processorContainer) {
        ServiceBusInboundChannelAdapter adapter = new ServiceBusInboundChannelAdapter(processorContainer, QUEUE_NAME,
            new CheckpointConfig(CheckpointMode.MANUAL));
        adapter.setOutputChannel(inputChannel);
        return adapter;
    }
}

Step 4. Create a message receiver binding with ServiceBusInboundChannelAdapter 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()
                .doOnSuccess(s -> LOGGER.info("Message '{}' successfully checkpointed", message))
                .doOnError(e -> LOGGER.error("Error found", e))
                .subscribe();
    }
}
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.

Table 25. Mapping between Service Bus Headers and Spring Headers
Service Bus Message Headers and Properties Spring Message Header Constants Type Priority Number (Descending priority)

ContentType

org.springframework.messaging.MessageHeaders.CONTENT_TYPE

String

N/A

CorrelationId

com.azure.spring.servicebus.support.ServiceBusMessageHeaders.CORRELATION_ID

String

N/A

MessageId

com.azure.spring.servicebus.support.ServiceBusMessageHeaders.MESSAGE_ID

String

1

MessageId

com.azure.spring.messaging.AzureHeaders.RAW_ID

String

2

MessageId

org.springframework.messaging.MessageHeaders.ID

UUID

3

PartitionKey

com.azure.spring.servicebus.support.ServiceBusMessageHeaders.PARTITION_KEY

String

N/A

ReplyTo

org.springframework.messaging.MessageHeaders.REPLY_CHANNEL

String

N/A

ReplyToSessionId

com.azure.spring.servicebus.support.ServiceBusMessageHeaders.REPLY_TO_SESSION_ID

String

N/A

ScheduledEnqueueTimeUtc

com.azure.spring.messaging.AzureHeaders.SCHEDULED_ENQUEUE_MESSAGE

Integer

1

ScheduledEnqueueTimeUtc

com.azure.spring.servicebus.support.ServiceBusMessageHeaders.SCHEDULED_ENQUEUE_TIME

Instant

2

SessionID

com.azure.spring.servicebus.support.ServiceBusMessageHeaders.SESSION_ID

String

N/A

TimeToLive

com.azure.spring.servicebus.support.ServiceBusMessageHeaders.TIME_TO_LIVE

Duration

N/A

To

com.azure.spring.servicebus.support.ServiceBusMessageHeaders.TO

String

N/A

13.2.5. Samples

Please refer to azure-spring-boot-samples for more details.

Example: Manually set the partition key for the message

This example demonstrates how to manually set the partition key for the message in the application.

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!");
    }
}
When both ServiceBusMessageHeaders.PARTITION_KEY and AzureHeaders.PARTITION_KEY are set in the message headers, ServiceBusMessageHeaders.PARTITION_KEY is preferred.

Example: Set the session id for the message

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!");
    }
}
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.

13.3. Spring Integration with Azure Storage Queue

13.3.1. 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.

13.3.2. Dependency Setup

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

13.3.3. Configuration

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

Below properties can also be configured with the default Spring Cloud Azure unified properties, by changing the prefix from spring.cloud.azure.storage.queue to spring.cloud.azure.

Table 26. Common 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.credential.*

NA

Properties used for getting token credential.

spring.cloud.azure.storage.queue. credential.clientId

String

Client id to use when performing service principal authentication with Azure.

spring.cloud.azure.storage.queue. credential.clientSecret

String

Client secret to use when performing service principal authentication with Azure.

spring.cloud.azure.storage.queue. credential.clientCertificatePath

String

Path of a PEM certificate file to use when performing service principal authentication with Azure.

spring.cloud.azure.storage.queue. credential.clientCertificatePassword

String

Password of the certificate file.

spring.cloud.azure.storage.queue. credential.username

String

Username to use when performing username/password authentication with Azure.

spring.cloud.azure.storage.queue. credential.password

String

Password to use when performing username/password authentication with Azure.

spring.cloud.azure.storage.queue. credential.managedIdentityClientId

String

Client id to use when using managed identity to authenticate with Azure.

spring.cloud.azure.storage.queue.profile.*

String

Properties related to an Azure subscription.

spring.cloud.azure.storage.queue. profile.tenantId

String

Tenant id for Azure resources.

spring.cloud.azure.storage.queue. profile.subscriptionId

String

Subscription id to use when connecting to Azure resources.

spring.cloud.azure.storage.queue.profile.cloud

AzureProfileAware.CloudType

Name of the Azure cloud to connect to.

spring.cloud.azure.storage.queue. profile.environment.*

NA

Properties to Azure services, such as endpoints, resource ids, etc.

spring.cloud.azure.storage.queue. profile.environment.activeDirectoryEndpoint

String

The Azure Active Directory endpoint to connect to.

spring.cloud.azure.storage.queue.resource.*

String

Metadata defining an Azure resource.

spring.cloud.azure.storage.queue. resource.resourceGroup

String

Name of the Azure resource group.

spring.cloud.azure.storage.queue. resource.resourceId

String

ID of the Azure resource group.

spring.cloud.azure.storage.queue.resource.region

String

Name of region.

spring.cloud.azure.storage.queue. client.transportType

AmqpTransportType

Transport type switches available for AMQP protocol.

spring.cloud.azure.storage.queue.retry.*

NA

Retry properties.

spring.cloud.azure.storage.queue. retry.backoff.*

NA

Backoff properties when a retry fails.

spring.cloud.azure.storage.queue. retry.backoff.delay

Duration

Amount of time to wait between retry attempts.

spring.cloud.azure.storage.queue. retry.backoff.maxDelay

Duration

Maximum permissible amount of time between retry attempts.

spring.cloud.azure.storage.queue. retry.backoff.multiplier

Double

Multiplier used to calculate the next backoff delay. If positive, then used as a multiplier for generating the next delay for backoff.

spring.cloud.azure.storage.queue. retry.maxAttempts

Integer

The maximum number of attempts.

spring.cloud.azure.storage.queue. retry.timeout

Duration

Amount of time to wait until a timeout.

spring.cloud.azure.storage.queue.proxy.*

NA

Common proxy properties.

spring.cloud.azure.storage.queue.proxy.type

String

Type of the proxy.

spring.cloud.azure.storage.queue. proxy.hostname

String

The host of the proxy.

spring.cloud.azure.storage.queue.proxy.port

Integer

The port of the proxy.

spring.cloud.azure.storage.queue. proxy.authenticationType

String

Authentication type used against the proxy.

spring.cloud.azure.storage.queue. proxy.username

String

Username used to authenticate with the proxy.

spring.cloud.azure.storage.queue. proxy.password

String

Password used to authenticate with the proxy.

Azure Storage Queue Client Configuration Options

Below options are used to configure Azure Storage Queue SDK Client.

Table 27. Client configurable properties of spring-cloud-azure-starter-integration-storage-queue
Property Type Description

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.

13.3.4. Basic Usage

Send messages to Azure Storage Queue

Step 1. Fill the credential configuration options.

  • For credentials as connection string, configure below properties in application.yml:

spring:
  cloud:
    azure:
      storage:
        queue:
          connection-string: ${AZURE_SERVICE_BUS_CONNECTION_STRING}
  • For credentials as MSI, configure below properties in application.yml:

spring:
  cloud:
    azure:
      credential:
        managed-identity-client-id: ${AZURE_CLIENT_ID}
      profile:
        tenant-id: ${AZURE_TENANT_ID}
      storage:
        queue:
          namespace: ${AZURE_SERVICE_BUS_NAMESPACE}
  • For credentials as service principal, configure below 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}

Step 2. Create DefaultMessageHandler with the bean of StorageQueueOperation 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(StorageQueueOperation storageQueueOperation) {
        DefaultMessageHandler handler = new DefaultMessageHandler(STORAGE_QUEUE_NAME, storageQueueOperation);
        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;
    }
}

Step 3. Create a Message gateway binding with the message handler created in the last stop via a message channel

class Demo{
    @Autowired
    StorageQueueOutboundGateway storageQueueOutboundGateway;

    @MessagingGateway(defaultRequestChannel = OUTPUT_CHANNEL)
    public interface StorageQueueOutboundGateway {
        void send(String text);
    }
}

Step 4. Send messages using the gateway

class Demo{
    public void demo() {
        this.storageQueueOutboundGateway.send(message);
    }
}
Receive messages from Azure Storage Queue

Step 1. Fill the credential configuration options.

Step 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();
    }
}

Step 3. Create StorageQueueMessageSource with the bean of StorageQueueOperation 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(StorageQueueOperation storageQueueOperation) {
        storageQueueOperation.setCheckpointMode(CheckpointMode.MANUAL);
        storageQueueOperation.setVisibilityTimeoutInSeconds(10);

        return new StorageQueueMessageSource(STORAGE_QUEUE_NAME, storageQueueOperation);
    }
}

Step 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))
            .subscribe();
    }
}

13.3.5. Samples

Please refer to azure-spring-boot-samples for more details.

14. 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-azure-stream-binder-eventhubs

  • spring-cloud-azure-stream-binder-servicebus

14.1. Spring Cloud Stream Binder for Azure Event Hubs

14.1.1. 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 provide the function to store such offsets inside Azure Storage Account. So that’s why you have to fill spring.cloud.eventhubs.processor.checkpoint-store.*.

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 the consumer properties for more details.

Batch Consumer Support

Azure Spring Cloud 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 org.springframework.messaging.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.

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 com.azure.spring.messaging.checkpoint.Checkpointer will be passes 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 the consumer properties for more details.

14.1.2. Dependency Setup

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

Alternatively, you can also use the Azure Spring Cloud 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>

14.1.3. Configuration

The binder provides the following 3 parts of configuration options:

Connection Configuration Properties

These properties are exposed via com.azure.spring.cloud.autoconfigure.eventhubs.properties.AzureEventHubsProperties.

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, please refer to Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.
Table 28. 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.

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.

Common Azure Service SDK configuration options are configurable for the Azure Spring Cloud 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..
Checkpoint Configuration Properties

These properties are exposed via com.azure.spring.cloud.autoconfigure.eventhubs.properties.AzureEventHubsProperties.Processor.BlobCheckpointStore for the configuration of BlobCheckpointStore, which is the default implementation of CheckpointStore to use Storage Blobs for persisting partition ownership and checkpoint information.

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.
Table 29. 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

If allowed 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.
The default maximum connection pool size of the Storage Blob client is changed from 500 in version 3.x to 16 now, and the pending acquire queue size which is double of pool size is then 32 now. To override them, please set the property spring.cloud.azure.eventhubs.processor.checkpoint-store.client.maximum-connection-pool-size.
Azure Event Hubs Binding Configuration Properties

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

Consumer Properties
Table 30. 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.

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 com.azure.spring.service.eventhubs.properties.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
Table 31. 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..

14.1.4. Basic Usage

Sending and receiving messages from/to Event Hubs

Step 1. Fill the configuration options with credential information.

  • For credentials as connection string, configure below 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 below properties in application.yml:

spring:
  cloud:
    azure:
      credential:
        client-id: ${SERVICE_PRINCIPAL_ID}
        client-secret: ${SERVICE-PRINCIPAL_SECRET}
      profile:
        tenant-id: ${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 MSI, configure below properties in application.yml:

spring:
  cloud:
    azure:
      credential:
        managed-identity-client-id: ${AZURE_MANAGED_IDENTITY_CLIENT_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

Step2. 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))
                .subscribe();
    };
}

@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:

145347877 fa8afa90 ec28 4c0a 8277 63b9fdaa5d0f

Batch Consumer Support

Step 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

Step2. Define supplier and consumer.

For checkpointing mode as BATCH, you can use below 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 below 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))
                    .subscribe();
    };
}

@Bean
public Supplier<Message<String>> supply() {
    return () -> {
        LOGGER.info("Sending message, sequence " + i);
        return MessageBuilder.withPayload("\"test"+ i++ +"\"").build();
    };
}
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, please 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.

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

Table 32. Mapping between Batch Event Hubs Properties and Spring Headers
Event Hubs Event Properties Spring Batch Message Header Constants Type Description

Enqueued time

com.azure.spring.eventhubs.support.EventHubsHeaders#BATCH_CONVERTED_ENQUEUED_TIME

List of Instant

List of the instant, in UTC, of when each event was enqueued in the Event Hub partition.

Offset

com.azure.spring.eventhubs.support.EventHubsHeaders#BATCH_CONVERTED_OFFSET

List of Long

List of the offset of each event when it was received from the associated Event Hub partition.

Partition key

com.azure.spring.messaging.AzureHeaders#BATCH_CONVERTED_PARTITION_KEY

List of String

List of the partition hashing key if it was set when originally publishing each event.

Sequence number

com.azure.spring.eventhubs.support.EventHubsHeaders#BATCH_CONVERTED_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

com.azure.spring.eventhubs.support.EventHubsHeaders#BATCH_CONVERTED_SYSTEM_PROPERTIES

List of Map

List of the system properties of each event.

Application properties

com.azure.spring.eventhubs.support.EventHubsHeaders#BATCH_CONVERTED_APPLICATION_PROPERTIES

List of Map

List of the applocation properties of each event, where all customized message headers or event properties are placed.

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

14.1.5. Samples

Please refer to azure-spring-boot-samples for more details.

14.2. Spring Cloud Stream Binder for Azure Service Bus

14.2.1. 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.

14.2.2. Dependency Setup

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

Alternatively, you can also use the Azure Spring Cloud 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>

14.2.3. Configuration

The binder provides the following 3 parts of configuration options:

Connection Configuration Properties

These properties are exposed via com.azure.spring.cloud.autoconfigure.servicebus.properties.AzureServiceBusProperties.

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, please refer to Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.
Table 33. Common 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.

spring.cloud.azure.servicebus.domain-name

String

Domain name of an Azure Service Bus Namespace value.

Common Azure Service SDK configuration options are configurable for the Azure Spring Cloud 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..
Azure Service Bus Binding Configuration Properties

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

Consumer Properties
Table 34. Consumer configurable properties of spring-cloud-azure-stream-binder-servicebus
Property Type Description

spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.requeue-rejected

boolean

If the failed messages are routed to the DLQ.

spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.checkpoint-mode

CheckpointMode

The checkpoint mode of checkpointing message. The supported modes are MANUAL and RECORD.

spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.max-concurrent-calls

Integer

Max concurrent messages that the Service Bus processor client should process.

spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.max-concurrent-sessions

Integer

Maximum number of concurrent sessions to process at any given time.

spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.session-aware

Boolean

Whether session is enabled.

spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.prefetch-count

Integer

The prefetch count of the Service Bus processor client.

spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.sub-queue

SubQueue

The type of the sub queue to connect to.

spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.max-auto-lock-renew-duration

Duration

The amount of time to continue auto-renewing the lock.

spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.receive-mode

ServiceBusReceiveMode

The receive mode of the Service Bus processor client.

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
Table 35. Producer configurable properties of spring-cloud-azure-stream-binder-servicebus
Property Type Description

spring.cloud.stream.servicebus.bindings.<binding-name>.producer.sync

boolean

Switch flag for sync of producer.

spring.cloud.stream.servicebus.bindings.<binding-name>.producer.send-timeout

long

Timeout value for sending of producer.

spring.cloud.stream.servicebus.bindings.<binding-name>.producer.entity-type

ServiceBusEntityType

Service Bus entity type of the producer, required for the binding producer.

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..

14.2.4. Basic Usage

Sending and receiving messages from/to Service Bus

Step 1. Fill the configuration options with credential information.

  • For credentials as connection string, configure below 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, please add below configuration
          # group: ${SUBSCRIPTION_NAME}
        supply-out-0:
          destination: ${SERVICEBUS_ENTITY_NAME_SAME_AS_ABOVE}
      servicebus:
        bindings:
          consume-in-0:
            consumer:
              checkpoint-mode: MANUAL
          supply-out-0:
            producer:
              entity-type: queue # set as "topic" if you use Service Bus Topic
  • For credentials as service principal, configure below properties in application.yml:

spring:
  cloud:
    azure:
      credential:
        client-id: ${CLIENT_ID}
        client-secret: ${CLIENT_SECRET}
      profile:
        tenant-id: ${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, please add below configuration
          # group: ${SUBSCRIPTION_NAME}
        supply-out-0:
          destination: ${SERVICEBUS_ENTITY_NAME_SAME_AS_ABOVE}
      servicebus:
        bindings:
          consume-in-0:
            consumer:
              checkpoint-mode: MANUAL
          supply-out-0:
            producer:
              entity-type: queue # set as "topic" if you use Service Bus Topic
  • For credentials as MSI, configure below properties in application.yml:

spring:
  cloud:
    azure:
      credential:
        managed-identity-client-id: ${MANAGED_IDENTITY_CLIENT_ID}
      servicebus:
        namespace: ${SERVICEBUS_NAMESPACE}
    stream:
      function:
        definition: consume;supply
      bindings:
        consume-in-0:
          destination: ${SERVICEBUS_ENTITY_NAME}
          # If you use Service Bus Topic, please add below configuration
          # group: ${SUBSCRIPTION_NAME}
        supply-out-0:
          destination: ${SERVICEBUS_ENTITY_NAME_SAME_AS_ABOVE}
      servicebus:
        bindings:
          consume-in-0:
            consumer:
              checkpoint-mode: MANUAL
          supply-out-0:
            producer:
              entity-type: queue # set as "topic" if you use Service Bus Topic

Step 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))
                .subscribe();
    };
}

@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 properts 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();
    };
}
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.

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.

14.2.5. Samples

Please refer to azure-spring-boot-samples for more details.

15. 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.

15.1. Dependency Setup

Adding below 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>

15.2. Configuration

Table 36. 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 clientID. 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.

Spring JMS general configuration is omited for short. Please refer to Spring JMS Doc for more details.

15.3. Basic Usage

15.3.1. Use Service Bus Connection String

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

Add below properties and you are good to go.

spring:
  jms:
    servicebus:
      connection-string: ${AZURE_SERVICEBUS_CONNECTION_STRING}
      pricing-tier: ${PRICING_TIER}
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. The other pooling configuration options(spring.jms.servicebus.pool.* prefix) can be found in the above Configuration section.

15.4. Samples

Please refer to azure-spring-boot-samples for more details.

16. Kafka Support

Connect to Azure Event Hubs (Basic pricing tier is not supported) using Spring Kafka libraries. There are two approaches to connect to Azure Event Hubs for Kafka, the first one is to provide the Azure Event Hubs connection string directly, the other is to use Azure Resource Manager to retrieve the connection string.

16.1. Dependency Setup

Adding below 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, please also add below dependency

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

16.2. Configuration

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, please refer to Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.
Table 37. Configurable properties when using Kafka support
Property Description

spring.cloud.azure.eventhubs.kafka.enabled

Whether to enable the Azure Event Hubs Kafka support, default to true.

spring.cloud.azure.eventhubs.connection-string

Azure Event Hubs connection string. Should be provided when want to provide the connection string directly.

spring.cloud.azure.eventhubs.namespace

Azure Event Hubs namespace. Should be provided when 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. Should be provided when want to retrieve the connection information through Azure Resource Manager.

spring.cloud.azure.profile.subscription-id

The subscription id. Should be provided when want to retrieve the connection information through Azure Resource Manager.

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. Please refer to Authentication for more details.

16.3. Basic Usage

16.3.1. Use Event Hubs connection string

The simplest way to connect to Event Hubs for Kafka is with the connection string.

Add below properties and you are good to go.

spring:
  cloud:
    azure:
      eventhubs:
        connection-string: ${AZURE_EVENTHUBS_CONNECTION_STRING}

16.3.2. Use Azure Resource Manager to retrieve connection string

If you don’t want to configure connection string in your application, it’s also possible to use Azure Resource Manager to retrieve the connection string. And you could use credentials stored in Azure CLI or other local development tool, like Visual Studio Code or Intellij IDEA to authenticate with Azure Resource Manager. Or Managed Identity if your application is deployed to Azure Cloud. Just make sure the principal have sufficient permission to read resource metadata.

Add below properties and you are good to go.

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

16.4. Samples

Please refer to azure-spring-boot-samples for more details.

17. 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.

17.1. Dependency Setup

Adding below 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>

17.2. Configuration

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, please refer to Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.
Table 38. Configurable properties when using Redis support
Property Description Default Value Required

spring.cloud.azure.redis.enabled

Azure Cache for Redis instance name.

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

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. Please refer to Authentication for more details.

17.3. Basic Usage

Add below 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}

17.4. Samples

Please refer to azure-spring-boot-samples for more details.

18. Resource Manager

Connect to Azure Resources for All Azure SDKs service, which Spring Cloud used. Construct TokenCredential by using various credential information, and then construct AzureResourceManager to help Azure SDKs Client to authenticate and authorize.

18.1. Dependency Setup

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

18.2. Configuration

If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, please refer to Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource.
Table 39. 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-certificate-password

Password of the certificate file.

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-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.managed-identity-client-id

Client id to use when using managed identity to authenticate with Azure.

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.profile.cloud

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.

18.3. Basic Usage

Azure Resource Manger helps the Azure SDK client to complete authentication and authorization. It can be integrated into a specific Spring Cloud Azure Starter and work together, or it can be used with Spring Cloud Azure auto-configuration modules and third-party libraries to complete authentication, such as: Kafka Support, Redis Support.

18.4. Samples

Please refer to azure-spring-boot-samples for more details.

19. Configuration Properties

To see the list of all Spring Cloud Azure related configuration properties please check the Appendix page.

20. Appendix