This document is only for Spring Cloud Azure: 4.1.0. See 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 document, please ask by creating GitHub issues. And Pull Request is welcome.
GitHub repositories | Description |
---|---|
This repository used to hold the source code. |
|
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 migrate to 4.0, please check the Appendix page. |
The following list summarizes some of the changes that Spring Cloud Azure 4.0 provides:
-
A unified development experience, with unified project name, artifact ID, and properties.
-
Simplified dependency management using a single
spring-cloud-azure-dependencies
BOM. -
Expanded Azure support on Spring Initializr to cover Kafka, Event Hubs, Azure Cache for Redis, and Azure App Configuration.
-
Rearchitected Spring module dependencies to remove excess layers and entanglement.
-
Managed Identity support for Azure App Configuration, Event Hubs, Service Bus, Cosmos DB, Key Vault, Storage Blob, and Storage Queue.
-
Continued support for authentication methods in the underlying Azure SDK from our Spring libraries, such as SAS token and token credential authentication with Service Bus and Event Hubs.
-
Credential chain is now enabled by default, enabling applications to obtain credentials from application properties, environment variables, managed identity, IDEs, and so on.
-
Granular access control at the resource level (such as Service Bus queue) to enable better security governance and adherence to IT policies.
-
More options exposed in a Spring-idiomatic way through significantly improved auto-configuration coverage of Azure SDK clients for both synchronous and asynchronous scenarios.
-
Added health indicators for Azure App Configuration, Event Hubs, Cosmos DB, Key Vault, Storage Blob, Storage Queue, and Storage File.
-
Spring Cloud Sleuth support for all HTTP-based Azure SDKs.
3. Migration Guide for 4.0
To learn how to migrate 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>${spring.cloud.azure.version}</version> (1)
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
1 | The version for spring-cloud-azure-dependencies is 4.1.0. |
4.1.2. Starter Dependencies
Spring Cloud Azure Starters are a set of convenient dependency descriptors to include in your application. Each starter includes all the dependencies and transitive dependencies needed to begin using its corresponding Spring Cloud Azure module. They boost your Spring Boot application development with Azure services.
For example, if you want to get started using Azure Cosmos DB for data persistence, include the spring-cloud-azure-starter-cosmos
dependency in your project.
Spring Cloud Azure provides the following starters under the com.azure.spring
group:
Name | Description |
---|---|
spring-cloud-azure-starter |
Core starter, including autoconfiguration 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:
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:
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:
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 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. Spring Cloud Azure 4.0 provides five common categories of configuration properties, which could be specified to each Azure service.
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. The retry options has supported part of the SDKs, there’s no |
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 application developers to specify properties that apply to all Azure SDKs with the prefix spring.cloud.azure
.
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. |
Spring Cloud Azure unifies configuration properties' prefixes to spring.cloud.azure
since 4.0, which will make configuration properties more consistent and more intuitive. Here’s a quick review of the serivce specific properties.
Azure Service | Configuration Property Prefix | Configuration Properties Link |
---|---|---|
Azure App Configuration |
spring.cloud.azure.appconfiguration |
|
Azure Cosmos DB |
spring.cloud.azure.cosmos |
|
Azure Event Hubs |
spring.cloud.azure.eventhubs |
|
Azure Key Vault Certificates |
spring.cloud.azure.keyvault.certificate |
|
Azure Key Vault Secrets |
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 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.
-
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.
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 Identities
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 managed 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 Managed 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’s tied to the lifecycle of that service instance. So when the resource is deleted, Azure automatically deletes the identity for you. By design, only that Azure resource can use this identity to request tokens from Azure AD.
-
User-assigned You may also create a managed identity as a standalone Azure resource. You can create a user-assigned managed identity and assign it to one or more instances of an Azure service. In the case of user-assigned managed identities, the identity is managed separately from the resources that use it.
When using a user-assigned managed identity, you can specify the client ID by spring.cloud.azure.credential.client-id or spring.cloud.azure.<azure-service>.credential.client-id .
|
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 managed 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.
-
First, the security principal’s identity is authenticated, and an OAuth 2.0 token is returned.
-
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 AD authentication, below configurations could be set with prefix spring.cloud.azure.credential
or spring.cloud.azure.<azure-service>.credential
.
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 |
Path of a PEM certificate file 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-enabled |
Whether to enable managed identity. |
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 decide 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:
Role | Description |
---|---|
Allows full access to App Configuration data. |
|
Allows read access to App Configuration data. |
|
Allows for full access to Azure Event Hubs resources. |
|
Allows receive access to Azure Event Hubs resources. |
|
Allows send access to Azure Event Hubs resources. |
|
Allows for full access to Azure Service Bus resources. |
|
Allows for receive access to Azure Service Bus resources. |
|
Allows for send access to Azure Service Bus resources. |
|
Provides full access to Azure Storage blob containers and data, including assigning POSIX access control. |
|
Read and list Azure Storage containers and blobs. |
|
Read and list Azure Storage queues and queue messages. |
|
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 isn’t available yet. Check here for more details about the permission model, role definitions, and role assignment.
|
6.3.2. SAS tokens
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 Strings
Connection strings are supported by some Azure services to provide connection information as well as credentials. To connect to those Azure services using a 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
Spring Cloud Azure 4.0 supports health indicators for App Configuration, Event Hubs, Cosmos, Key Vault Certificate, Key Vault Secret, Storage Blob, Storage Queue, and Storage File Share. It also provides integrations with Spring Cloud Sleuth 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>
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 Certificate |
management.health.azure-keyvault-certificate.enabled |
Key Vault Secret |
management.health.azure-keyvault-secret.enabled |
Storage Blob |
management.health.azure-storage-blob.enabled |
Storage File Share |
management.health.azure-storage-fileshare.enabled |
Storage Queue |
management.health.azure-storage-queue.enabled |
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 Insights for such requirement. |
8. Autoconfigure Azure SDK Clients
Spring Boot simplifies the Spring Cloud Azure development experience. Spring Cloud Azure starters are a set of convenient dependency descriptors to include in your application. They 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-type: Azure (1)
credential:
client-id: ${AZURE_CLIENT_ID}
1 | cloud-type is optional for it has default value set to Azure . |
These properties are optional and, if not specified, Spring Boot will try to automatically find them for you. For details on how Spring Boot finds these properties, refer to the documentation.
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. For example with Cosmos DB:
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-cosmos</artifactId>
</dependency>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter</artifactId>
</dependency>
Or including the Spring Cloud Azure starter directly without adding Azure SDK dependencies. 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 Spring Cloud Azure supports. |
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.<azure-service>
.
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 clients 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 autoconfigure Azure Storage Blob and Azure Storage File Share.
Starter | Service | Description |
---|---|---|
spring-cloud-azure-starter-storage-blob |
Azure Storage Blob |
Allows unstructured data to be stored and accessed at a massive scale in block blobs. |
spring-cloud-azure-starter-storage-file-share |
Azure Storage File Share |
Offers fully managed cloud file shares that you can access from anywhere via the industry standard Server Message Block (SMB) protocol. |
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. |
Property | Default | Description |
---|---|---|
spring.cloud.azure.storage.blob.enabled |
true |
Whether to enable Azure Storage Blob. |
spring.cloud.azure.storage.blob.endpoint |
Endpoint for Azure Storage Blob service. |
|
spring.cloud.azure.storage.blob.account-key |
Private key to connect Azure Storage Blob. |
|
spring.cloud.azure.storage.blob.account-name |
Azure Storage Blob account name. |
Property | Default | Description |
---|---|---|
spring.cloud.azure.storage.fileshare.enabled |
true |
Whether to enable Azure Storage File Share. |
spring.cloud.azure.storage.fileshare.endpoint |
Endpoint for Azure Storage File Share service. |
|
spring.cloud.azure.storage.fileshare.account-key |
Private key to connect Azure Storage File Share. |
|
spring.cloud.azure.storage.fileshare.account-name |
Azure Storage File Share 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_KEY}
endpoint: ${STORAGE_BLOB_ENDPOINT}
fileshare:
account-name: ${STORAGE_ACCOUNT_NAME}
account-key: ${STORAGE_ACCOUNT_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 storageBlobResource;
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 storageFileResource;
Get a resource with ResourceLoader
@Autowired
private ResourceLoader resourceLoader;
...
// get a BlobResource
Resource storageBlobResource = resourceLoader.getResource("azure-blob://[your-container-name]/[your-blob-name]");
// get a FileResource
Resource storageFileResource = resourceLoader.getResource("azure-file://[your-fileshare-name]/[your-file-name]");
Get Resources by Searching Pattern
You can use implementation class of ResourcePatternResolver
to search resources. Use AzureStorageBlobProtocolResolver
to search blob
resources, and AzureStorageFileProtocolResolver
to search file
resources.
-
Pattern search, the searchPattern should start with
azure-blob://
orazure-file://
. Such asazure-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-folders. -
Location search, the searchLocation should start with
azure-blob://
orazure-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 Stroage Blob or File Share with the getInputStream()
method of Resource
.
@Value("azure-blob://[your-container-name]/[your-blob-name]")
private Resource storageBlobResource;
@Value("azure-file://[your-fileshare-name]/[your-file-name]")
private Resource storageFileResource;
....
// download data as 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 Storage Blob or File Share 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 construct PropertySource which holds secrets stored in Azure Key Vault Secrets.
10.1. Dependency Setup
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-keyvault-secrets</artifactId>
</dependency>
10.2. Basic Usage
If you want to authenticate by client-id
and client-secret
, the following properties are required:
10.2.1. Configuration Properties
spring:
cloud:
azure:
keyvault:
secret:
property-sources:
- name: key-vault-property-souece-1
endpoint: ${ENDPOINT_1}
- name: key-vault-property-souece-2
endpoint: ${ENDPOINT_2}
10.2.2. Java Code
@SpringBootApplication
public class SampleApplication implements CommandLineRunner {
@Value("${sampleProperty1}")
private String sampleProperty1;
@Value("${sampleProperty2}")
private String sampleProperty2;
@Value("${samplePropertyInMultipleKeyVault}")
private String samplePropertyInMultipleKeyVault;
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
public void run(String[] args) {
System.out.println("sampleProperty1: " + sampleProperty1);
System.out.println("sampleProperty2: " + sampleProperty2);
System.out.println("samplePropertyInMultipleKeyVault: " + samplePropertyInMultipleKeyVault);
}
}
10.3. Advanced Usage
10.3.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..
isn’t supported in secret name. If your application have property name which contains.
, likespring.datasource.url
, just replace.
to-
when save secret in Azure Key Vault. For example: Savespring-datasource-url
in Azure Key Vault. In your application, you can still usespring.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 isn’t supported. To handle this case, please refer to the following option: Use property placeholders.
|
-
Use property placeholders. For example: setting this property in your application.properties:
property.with.special.character_=${propertyWithoutSpecialCharacter}
. The application will getpropertyWithoutSpecialCharacter
key name and assign its value toproperty.with.special.character_
.
10.3.2. Case Sensitive
By default, the secret names are case-insensitive. To enable case-sensitive mode, just set the following property: spring.cloud.azure.keyvault.secret.property-sources[].case-sensitive=true
.
10.3.3. Not Retrieve All Secrets In Key Vault
If you stored 1000 secrets in the Key Vault, and you just want to use 3 of them. You can list the 3 secret names by spring.cloud.azure.keyvault.secret.property-sources[].secret-keys
.
10.3.4. Setting Refresh Interval
By default, the secrets in KeyVaultPropertySource
will refresh every 30 minutes. You can configure the time by spring.cloud.azure.keyvault.secret.property-sources[].refresh-interval
. For example: spring.cloud.azure.keyvault.secret.property-sources[].refresh-interval=60m
means refresh every 60 minutes. Set to 0
to disable auto refresh.
10.3.5. PropertySource Priority
If key exists in multiple PropertySources, which will take effect is decided by the priority.
-
If there is no
SystemEnvironmentPropertySource
in PropertySource list, thenKeyVaultPropertySource
will take the highest priority. -
If there is
SystemEnvironmentPropertySource
in PropertySource list, thenSystemEnvironmentPropertySource
have higher priority than KeyVaultPropertySource. Which means you can use environment variable to override the Key Vault secret value in your application. -
If there are multiple KeyVaultPropertySource in PropertySource list, then the definition order is the priority order. Take above sample as example,
key-vault-property-souece-1
has higher priority thankey-vault-property-souece-2
.
10.3.6. All Configurable Properties
Property | Default value | Description |
---|---|---|
spring.cloud.azure.keyvault.secret.property-source-enabled |
true |
Whether to enable the Key Vault property source. |
spring.cloud.azure.keyvault.secret.property-sources[].name |
Name of this property source. |
|
spring.cloud.azure.keyvault.secret.property-sources[].endpoint |
Azure Key Vault endpoint. |
|
spring.cloud.azure.keyvault.secret.property-sources[].case-sensitive |
false |
Whether the secret keys are case-sensitive. |
spring.cloud.azure.keyvault.secret.property-sources[].secret-keys |
The secret keys supported for this property source. All keys be retrieved if this property is missing. |
|
spring.cloud.azure.keyvault.secret.property-sources[].refresh-interval |
30m |
Time interval to refresh all Key Vault secrets. |
spring.cloud.azure.keyvault.secret.property-sources[].service-version |
Secret service version used when making API requests. |
|
spring.cloud.azure.keyvault.secret.property-sources[].client |
Client related properties. |
|
spring.cloud.azure.keyvault.secret.property-sources[].credential |
Credential related properties. |
|
spring.cloud.azure.keyvault.secret.property-sources[].profile |
Profile related properties. |
|
spring.cloud.azure.keyvault.secret.property-sources[].proxy |
Proxy related properties. |
|
spring.cloud.azure.keyvault.secret.property-sources[].retry |
Retry related properties. |
-
See Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure Key Vault Secrets.
-
If common properties like
client
,credential
,profile
,proxy
,retry
aren’t configured inspring.cloud.azure.keyvault.secret.property-sources[].xxx
,spring.cloud.azure.xxx
will be used. See Configuration to get more information about these common properties. -
See Configuration Properties to get more information about nested properties.
10.4. Samples
Sample project: property-source.
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.
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. |
Property | Default | Description |
---|---|---|
spring.cloud.azure.cosmos.enabled |
true |
Whether Azure Cosmos Service is enabled. |
spring.cloud.azure.cosmos.database |
The Cosmos DB database id. |
|
spring.cloud.azure.cosmos.endpoint |
Uri to connect Cosmos DB. |
|
spring.cloud.azure.cosmos.key |
Private key to connect Cosmos DB. |
|
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-enabled |
false |
Whether to enable managed identity. |
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 documentid
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.
Apart from using the spring-cloud-azure-starter-data-cosmos
library, you can directly use azure-spring-data-cosmos
library 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 Active Directory
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. Accessing a Web Application
This scenario uses The OAuth 2.0 authorization code grant flow to log in a user with a Microsoft account.
Create Required Resources in Azure
-
Read MS docs about register an application with the Microsoft identity platform.
-
Create app registration. Get
AZURE_TENANT_ID
,AZURE_CLIENT_ID
andAZURE_CLIENT_SECRET
. -
Set
redirect URI
toAPPLICATION_BASE_URI/login/oauth2/code/
, for examplelocalhost:8080/login/oauth2/code/
. The tailing/
is required.
Add Required Dependencies
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-active-directory</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
</dependencies>
Add Required Properties
spring:
cloud:
azure:
active-directory:
profile:
tenant-id: ${AZURE_TENANT_ID}
credential:
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
Now start you application and access your application by browser, then you will be redirected into Microsoft login page.
Advanced Usages
Add Extra Security Configurations
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AadOAuth2LoginSecurityConfig extends AadWebSecurityConfigurerAdapter {
/**
* Add configuration logic as needed.
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.anyRequest().authenticated();
// Do some custom configuration
}
}
Authorize Access by App Roles
-
Step 1: Create Required Resources in Azure
-
Read MS docs about Add app roles to your application and receive them in the token.
-
Create an app role with the following parameters:
-
Display name: Admin
-
Allowed member types: Users/Groups
-
Value: Admin
-
Do you want to enable this app role: yes
-
-
If you want to use app role based access control, you can’t put group names in role claim . Refs: Configuring groups optional claims.
|
-
Step 2: Protect specific method.
class Demo { @GetMapping("Admin") @ResponseBody @PreAuthorize("hasAuthority('APPROLE_Admin')") public String admin() { return "Admin message"; } }
Authorize Access by Group Name Or Group ID
-
Step 1: Add related configuration properties.
spring: cloud: azure: active-directory: user-group: allowed-group-names: group1_name_1, group2_name_2 # 1. If allowed-group-ids == all, then all group id will take effect. # 2. If "all" is used, we should not configure other group ids. # 3. "all" is only supported for allowed-group-ids, not supported for allowed-group-names. allowed-group-ids: group_id_1, group_id_2
-
Step 2: Protect specific method.
@Controller public class RoleController { @GetMapping("group1") @ResponseBody @PreAuthorize("hasRole('ROLE_group1')") public String group1() { return "group1 message"; } @GetMapping("group2") @ResponseBody @PreAuthorize("hasRole('ROLE_group2')") public String group2() { return "group2 message"; } @GetMapping("group1Id") @ResponseBody @PreAuthorize("hasRole('ROLE_<group1-id>')") public String group1Id() { return "group1Id message"; } @GetMapping("group2Id") @ResponseBody @PreAuthorize("hasRole('ROLE_<group2-id>')") public String group2Id() { return "group2Id message"; } }
Use National Azure Instead of Global Azure
Now except global Azure cloud, Azure Active Directory is deployed in the following national clouds:
-
Azure Government
-
Azure China 21Vianet
-
Azure Germany
Here is a sample of you want to use Azure China 21Vianet.
spring:
cloud:
azure:
active-directory:
base-uri: https://login.partner.microsoftonline.cn
graph-base-uri: https://microsoftgraph.chinacloudapi.cn
You can refer to these MS doc to get more information from MS docs about National cloud deployments.
Configure Redirect URI Template
Developers can customize the redirect-uri.
-
Step 1: Add
redirect-uri-template
properties in application.yml.
spring: cloud: azure: active-directory: redirect-uri-template: ${REDIRECT-URI-TEMPLATE}
-
Step 2: Update redirect-uri in Azure portal.
-
Step 3: Update WebSecurityConfigurerAdapter
After we set redirect-uri-template, we need to update WebSecurityConfigurerAdapter
:
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AadOAuth2LoginSecurityConfig extends AadWebSecurityConfigurerAdapter {
/**
* Add configuration logic as needed.
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.oauth2Login()
.loginProcessingUrl("${REDIRECT-URI-TEMPLATE}")
.and()
.authorizeRequests()
.anyRequest().authenticated();
}
}
Samples
Sample project: aad-web-application.
12.1.2. Web Application Accessing Resource Servers
Create Required Resources in Azure
-
Read MS docs about register an application with the Microsoft identity platform.
-
Create app registration. Get
AZURE_TENANT_ID
,AZURE_CLIENT_ID
andAZURE_CLIENT_SECRET
. -
Set
redirect URI
toAPPLICATION_BASE_URI/login/oauth2/code/
, for examplelocalhost:8080/login/oauth2/code/
. The tailing/
is required.
Add Required Dependencies
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-active-directory</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
</dependencies>
Add Required Properties
spring:
cloud:
azure:
active-directory:
profile:
tenant-id: ${AZURE_TENANT_ID}
credential:
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
authorization-clients:
graph:
scopes: https://graph.microsoft.com/Analytics.Read, email
Here, graph
is the name of OAuth2AuthorizedClient
, scopes
means the scopes need to consent when login.
Use OAuth2AuthorizedClient in Your Application
public class Demo {
@GetMapping("/graph")
@ResponseBody
public String graph(
@RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient graphClient) {
// toJsonString() is just a demo.
// oAuth2AuthorizedClient contains access_token. We can use this access_token to access resource server.
return toJsonString(graphClient);
}
}
Now start you application and access your application by browser, then you will be redirected into Microsoft login page.
Advanced Usages
Client Credential Flow
The default flow is authorization code flow, if you want to use client credentials flow, you can configure like this:
spring:
cloud:
azure:
active-directory:
profile:
tenant-id: ${AZURE_TENANT_ID}
credential:
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
authorization-clients:
graph:
authorization-grant-type: client_credentials # Change type to client_credentials
scopes: https://graph.microsoft.com/Analytics.Read, email
Access Multiple Resource Servers
In one web application, you can access multiple resource server by configuring like this:
spring:
cloud:
azure:
active-directory:
profile:
tenant-id: ${AZURE_TENANT_ID}
credential:
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
authorization-clients:
resource-server-1:
scopes: # Scopes for resource-server-1
resource-server-2:
scopes: # Scopes for resource-server-2
Then you can use OAuth2AuthorizedClient in application like this
public class Demo {
@GetMapping("/resource-server-1")
@ResponseBody
public String graph(
@RegisteredOAuth2AuthorizedClient("resource-server-1") OAuth2AuthorizedClient client) {
return callResourceServer1(client);
}
@GetMapping("/resource-server-2")
@ResponseBody
public String graph(
@RegisteredOAuth2AuthorizedClient("resource-server-2") OAuth2AuthorizedClient client) {
return callResourceServer2(client);
}
}
Incremental Consent
In previous sample, all scopes will be consented when customer first login, no matter it’s belong to resource-server-1 or resource-server-2. If you don’t want to let customer consent all scopes, you can do like this:
spring:
cloud:
azure:
active-directory:
profile:
tenant-id: ${AZURE_TENANT_ID}
credential:
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
authorization-clients:
resource-server-1:
scopes: # Scopes for resource-server-1
resource-server-2:
on-demand: true # means incremental consent
scopes: # Scopes for resource-server-2
Samples
Sample project: aad-web-application.
12.1.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.
Create Required Resources in Azure
-
Read MS docs about register an application with the Microsoft identity platform.
-
Create app registration. Get
AZURE_CLIENT_ID
. -
Read MS docs about configure an application to expose a web API.
-
Expose a web API with a scope named
Scope-1
.
Add Required Dependencies
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-active-directory</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
</dependencies>
Add Required Properties
spring:
cloud:
azure:
active-directory:
credential:
client-id: ${AZURE_CLIENT_ID}
Now start your application and access your application’s web api.
-
You will get 401 without an access token.
-
Access your application with an access token, the following claims in access token will be validated:
-
iss
: The access token must be issued by Azure AD. -
nbf
: Current time can not beforenbf
. -
exp
: Current time can not afterexp
. -
aud
: Ifspring.cloud.azure.active-directory.credential.client-id
orspring.cloud.azure.active-directory.credential.app-id-uri
configured, the audience must equal to the configuredclient-id
orapp-id-uri
. If the 2 properties are not configured, this claim will not be validated.
-
Refer to MS docs about Microsoft identity platform access tokens to get more information about access token.
Advanced Usages
Add Extra Security Configurations
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AadOAuth2ResourceServerSecurityConfig extends AadResourceServerWebSecurityConfigurerAdapter {
/**
* Add configuration logic as needed.
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests((requests) -> requests.anyRequest().authenticated());
}
}
Validate Permission by Scopes
-
Step 1: : Create Required Resources in Azure
-
Read MS docs about configure an application to expose a web API.
-
Expose a web API with a scope named
Scope1
.
-
-
Step 2: Protect specific method.
class Demo { @GetMapping("scope1") @ResponseBody @PreAuthorize("hasAuthority('SCOPE_Scope1')") public String scope1() { return "Congratulations, you can access `scope1` endpoint."; } }
By doing this, when access /scope1
endpoint, the following claims in access token will be validated:
-
scp
: The value must containsScope1
.
Validate Permission by App Roles
-
Step 1: Create Required Resources in Azure
-
Read MS docs about Add app roles to your application and receive them in the token.
-
Create an app role with the following parameters:
-
Display name: AppRole1
-
Allowed member types: Users/Groups
-
Value: AppRole1
-
Do you want to enable this app role: yes
-
-
-
Step 2: Protect specific method.
class Demo { @GetMapping("app-role1") @ResponseBody @PreAuthorize("hasAuthority('APPROLE_AppRole1')") public String appRole1() { return "Congratulations, you can access `app-role1` endpoint."; } }
By doing this, when access /app-role1
endpoint, the following claims in access token will be validated:
-
roles
: The value must containsAppRole1
.
Samples
Sample project: aad-resource-server.
12.1.4. Resource Server Visiting Other Resource Servers
Create Required Resources in Azure
-
Read MS docs about register an application with the Microsoft identity platform.
-
Create app registration. Get
AZURE_TENANT_ID
,AZURE_CLIENT_ID
andAZURE_CLIENT_SECRET
.
Add Required Dependencies
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-active-directory</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
</dependencies>
Add Required Properties
spring:
cloud:
azure:
active-directory:
profile:
tenant-id: ${AZURE_TENANT_ID}
credential:
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
authorization-clients:
graph:
scopes:
- https://graph.microsoft.com/User.Read
Use OAuth2AuthorizedClient in Your Application
public class SampleController {
@GetMapping("call-graph")
public String callGraph(@RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient graph) {
return callMicrosoftGraphMeEndpoint(graph);
}
}
Samples
Sample project: aad-resource-server-obo.
12.1.5. Web Application and Resource Server in One Application
Create Required Resources in Azure
-
Read MS docs about register an application with the Microsoft identity platform.
-
Create app registration. Get
AZURE_TENANT_ID
,AZURE_CLIENT_ID
andAZURE_CLIENT_SECRET
.
Add Required Dependencies
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-active-directory</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
</dependencies>
Add Required Properties
Set property spring.cloud.azure.active-directory.application-type
to web_application_and_resource_server
, and specify the authorization type for each authorization client.
spring:
cloud:
azure:
active-directory:
profile:
tenant-id: ${AZURE_TENANT_ID}
credential:
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
app-id-uri: ${WEB_API_ID_URI}
application-type: web_application_and_resource_server # This is required.
authorization-clients:
graph:
authorizationGrantType: authorization_code # This is required.
scopes:
- https://graph.microsoft.com/User.Read
- https://graph.microsoft.com/Directory.Read.All
Define SecurityConfigurationAdapter
Configure multiple HttpSecurity instances, AadWebApplicationAndResourceServerConfig
contain two security configurations for resource server and web application.
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AadWebApplicationAndResourceServerConfig {
@Order(1)
@Configuration
public static class ApiWebSecurityConfigurationAdapter extends AadResourceServerWebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
// All the paths that match `/api/**`(configurable) work as `Resource Server`, other paths work as `Web application`.
http.antMatcher("/api/**")
.authorizeRequests().anyRequest().authenticated();
}
}
@Configuration
public static class HtmlWebSecurityConfigurerAdapter extends AadWebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
// @formatter:off
http.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated();
// @formatter:on
}
}
}
12.1.6. Configuration
Name | Default | Description |
---|---|---|
spring.cloud.azure.active-directory.app-id-uri |
App ID URI which might be used in the "aud" claim of an id_token. |
|
spring.cloud.azure.active-directory.application-type |
Type of the AAD application. |
|
spring.cloud.azure.active-directory.authenticate-additional-parameters |
Add additional parameters to the Authorization URL. |
|
spring.cloud.azure.active-directory.authorization-clients |
The OAuth2 authorization clients. |
|
spring.cloud.azure.active-directory.credential.client-id |
Client id to use when performing service principal authentication with Azure. |
|
spring.cloud.azure.active-directory.credential.client-secret |
Client secret to use when performing service principal authentication with Azure. |
|
spring.cloud.azure.active-directory.jwk-set-cache-lifespan |
|
The lifespan of the cached JWK set before it expires, default is 5 minutes. |
spring.cloud.azure.active-directory.jwk-set-cache-refresh-time |
|
The refresh time of the cached JWK set before it expires, default is 5 minutes. |
spring.cloud.azure.active-directory.jwt-connect-timeout |
Connection Timeout for the JWKSet Remote URL call. |
|
spring.cloud.azure.active-directory.jwt-read-timeout |
Read Timeout for the JWKSet Remote URL call. |
|
spring.cloud.azure.active-directory.jwt-size-limit |
Size limit in Bytes of the JWKSet Remote URL call. |
|
spring.cloud.azure.active-directory.post-logout-redirect-uri |
The redirect uri after logout. |
|
spring.cloud.azure.active-directory.profile.cloud-type |
Name of the Azure cloud to connect to. Supported types are: AZURE, AZURE_CHINA, AZURE_GERMANY, AZURE_US_GOVERNMENT, OTHER. |
|
spring.cloud.azure.active-directory.profile.environment |
Properties to Azure Active Directory endpoints. |
|
spring.cloud.azure.active-directory.profile.tenant-id |
Azure Tenant ID. |
|
spring.cloud.azure.active-directory.redirect-uri-template |
|
Redirection Endpoint: Used by the authorization server to return responses containing authorization credentials to the client via the resource owner user-agent. |
spring.cloud.azure.active-directory.resource-server.claim-to-authority-prefix-map |
Configure which claim will be used to build GrantedAuthority, and prefix of the GrantedAuthority’s string value. Default value is: "scp" → "SCOPE_", "roles" → "APPROLE_". |
|
spring.cloud.azure.active-directory.resource-server.principal-claim-name |
Configure which claim in access token be returned in AuthenticatedPrincipal#getName. Default value is "sub". |
|
spring.cloud.azure.active-directory.session-stateless |
|
If true activates the stateless auth filter AadAppRoleStatelessAuthenticationFilter. The default is false which activates AadAuthenticationFilter. |
spring.cloud.azure.active-directory.user-group.allowed-group-ids |
The group ids can be used to construct GrantedAuthority. |
|
spring.cloud.azure.active-directory.user-group.allowed-group-names |
The group names can be used to construct GrantedAuthority. |
|
spring.cloud.azure.active-directory.user-group.use-transitive-members |
|
If "true", use "v1.0/me/transitiveMemberOf" to get members. Otherwise, use "v1.0/me/memberOf". |
spring.cloud.azure.active-directory.user-name-attribute |
Decide which claim to be principal’s name. |
Here are some examples about how to use these properties:
Application Type
THe application type can be inferred from the dependencies: spring-security-oauth2-client or spring-security-oauth2-resource-server. If the inferred value is not the value you want, you can specify the application type. Here is the table about valid values and inferred value:
Has dependency: spring-security-oauth2-client | Has dependency: spring-security-oauth2-resource-server | Valid values of application type | Inferred value |
---|---|---|---|
Yes |
No |
|
|
No |
Yes |
|
|
Yes |
Yes |
|
|
12.2. Spring Security With Azure Active Directory B2C
Azure Active Directory (Azure AD) B2C is an identity management service that enables you to customize and control how customers sign up, sign in, and manage their profiles when using your applications. Azure AD B2C enables these actions while protecting the identities of your customers at the same time.
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
Name | Default | Description |
---|---|---|
spring.cloud.azure.active-directory.b2c.app-id-uri |
App ID URI which might be used in the "aud" claim of a token. |
|
spring.cloud.azure.active-directory.b2c.authenticate-additional-parameters |
Additional parameters for authentication. |
|
spring.cloud.azure.active-directory.b2c.authorization-clients |
Specify client configuration. |
|
spring.cloud.azure.active-directory.b2c.base-uri |
AAD B2C endpoint base uri. |
|
spring.cloud.azure.active-directory.b2c.credential |
AAD B2C credential information. |
|
spring.cloud.azure.active-directory.b2c.jwt-connect-timeout |
Connection Timeout for the JWKSet Remote URL call. |
|
spring.cloud.azure.active-directory.b2c.jwt-read-timeout |
Read Timeout for the JWKSet Remote URL call. |
|
spring.cloud.azure.active-directory.b2c.jwt-size-limit |
Size limit in Bytes of the JWKSet Remote URL call. |
|
spring.cloud.azure.active-directory.b2c.login-flow |
|
Specify the primary sign-in flow key. |
spring.cloud.azure.active-directory.b2c.logout-success-url |
Redirect url after logout. |
|
spring.cloud.azure.active-directory.b2c.profile |
AAD B2C profile information. |
|
spring.cloud.azure.active-directory.b2c.reply-url |
|
Reply url after get authorization code. |
spring.cloud.azure.active-directory.b2c.user-flows |
User flows. |
|
spring.cloud.azure.active-directory.b2c.user-name-attribute-name |
User name attribute name. |
For full configurations, check 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:
-
Accessing a web application.
-
Web application accessing resource servers.
-
Accessing a resource server.
-
Resource server accessing other resource servers.
Usage 1: Accessing a Web Application
This scenario uses The OAuth 2.0 authorization code grant flow to log in a user with your Azure AD B2C user.
-
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
, addlocalhost:8080/login/oauth2/code/
for the Reply URL, record the Application ID as yourWEB_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.
-
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.
-
After your application is built and started by Maven, open
localhost:8080/
in a web browser; you should be redirected to login page. -
Click link with the login user flow, you should be redirected Azure AD B2C to start the authentication process.
-
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 yourWEB_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 following json segment into
appRoles
array, record the Application ID URI as yourWEB_API_A_APP_ID_URL
, record the value of the app role as yourWEB_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"
}
-
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.
-
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: See 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.
-
Step 1: Refer to Usage 2: Web Application Accessing Resource Servers to build your
WebApiA
permission. -
Step 2: Add
WebApiA
permission and grant admin consent for your web application. -
Step 3: Add the following dependencies in your pom.xml.
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>azure-spring-boot-starter-active-directory-b2c</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
-
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 permissionWebApiB.SampleScope
.
{
"allowedMemberTypes": [
"Application"
],
"description": "WebApiB.SampleScope",
"displayName": "WebApiB.SampleScope",
"id": "04989db0-3efe-4db6-b716-ae378517d2b7",
"isEnabled": true,
"lang": null,
"origin": "Application",
"value": "WebApiB.SampleScope"
}
-
Step 2: Grant admin consent for WebApiB permissions.
-
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
See spring-cloud-azure-starter-active-directory-b2c 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. We provide Spring Integration support for these Azure services: Event Hubs, Service Bus, Storage Queue. The following is a list of supported adapters:
-
spring-cloud-azure-starter-integration-eventhubs
-
spring-cloud-azure-starter-integration-servicebus
-
spring-cloud-azure-starter-integration-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 are dropped from version 4.0.0. See Javadoc for details. |
Consumer Group
Event Hubs provides similar support of consumer group as Apache Kafka, but with slight different logic. While Kafka stores all committed offsets in the broker, you have to store offsets of Event Hubs messages being processed manually. Event Hubs SDK provides the function to store such offsets inside Azure Storage.
Partitioning Support
Event Hubs provides a similar concept of physical partition as Kafka. But unlike Kafka’s auto re-balancing between consumers and partitions, Event Hubs provides a kind of preemptive mode. The storage account acts as a lease to determine which partition is owned by which consumer. When a new consumer starts, it will try to steal some partitions from most heavy-loaded consumers to achieve the workload balancing.
To specify the load balancing strategy, developers can use EventHubsContainerProperties
for the configuration. See the following section for an example of how to configure EventHubsContainerProperties
.
Batch Consumer Support
The EventHubsInboundChannelAdapter
supports the batch-consuming mode. To enable it, users can specify the listener mode as ListenerMode.BATCH
when constructing an EventHubsInboundChannelAdapter
instance.
When enabled, an Message of which the payload is a list of batched events will be received and passed to the downstream channel. Each message header is also converted as a list, of which the content is the associated header value parsed from each event. For the communal headers of partition id, checkpointer and last enqueued properties, they are presented as a single value for the entire batch of events shares the same one. See Event Hubs Message Headers for more details.
The checkpoint header only exists when MANUAL checkpoint mode is used. |
Checkpointing of batch consumer supports two modes: BATCH
and MANUAL
. BATCH
mode is an auto checkpointing mode to checkpoint the entire batch of events together once they are received. MANUAL
mode is to checkpoint the events by users. When used, the
Checkpointer will be passed into the message header, and users could use it to do checkpointing.
The batch consuming policy can be specified by properties of max-size
and max-wait-time
, where max-size
is a necessary property while max-wait-time
is optional.
To specify the batch consuming strategy, developers can use EventHubsContainerProperties
for the configuration. See the following section for an example of how to configure EventHubsContainerProperties
.
13.1.2. Dependency Setup
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-integration-eventhubs</artifactId>
</dependency>
13.1.3. Configuration
This starter provides the following 3 parts of configuration options:
Connection Configuration Properties
This section contains the configuration options used for connecting to Azure Event Hubs.
If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, see Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource. |
Property | Type | Description |
---|---|---|
spring.cloud.azure.eventhubs.enabled |
boolean |
Whether an Azure Event Hubs is enabled. |
spring.cloud.azure.eventhubs.connection-string |
String |
Event Hubs Namespace connection string value. |
spring.cloud.azure.eventhubs.namespace |
String |
Event Hubs Namespace value, which is the prefix of the FQDN. A FQDN should be composed of <NamespaceName>.<DomainName> |
spring.cloud.azure.eventhubs.domain-name |
String |
Domain name of an Azure Event Hubs Namespace value. |
spring.cloud.azure.eventhubs.custom-endpoint-address |
String |
Custom Endpoint address. |
spring.cloud.azure.eventhubs.shared-connection |
Boolean |
Whether the underlying EventProcessorClient and EventHubProducerAsyncClient use the same connection. By default, a new connection is constructed and used created for each Event Hub client created. |
Checkpoint Configuration Properties
This section contains the configuration options for the Storage Blobs service, which is used for persisting partition ownership and checkpoint information.
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. |
Property | Type | Description |
---|---|---|
spring.cloud.azure.eventhubs.processor.checkpoint-store.create-container-if-not-exists |
Boolean |
Whether to allow creating containers if not exists. |
spring.cloud.azure.eventhubs.processor.checkpoint-store.account-name |
String |
Name for the storage account. |
spring.cloud.azure.eventhubs.processor.checkpoint-store.account-key |
String |
Storage account access key. |
spring.cloud.azure.eventhubs.processor.checkpoint-store.container-name |
String |
Storage container name. |
Common Azure Service SDK configuration options are configurable for Storage Blob checkpoint store as well. The supported configuration options are introduced in the Configuration page, and could be configured with either the unified prefix spring.cloud.azure.
or the prefix of spring.cloud.azure.eventhubs.processor.checkpoint-store
.
Event Hub Processor Configuration Properties
The EventHubsInboundChannelAdapter
uses the EventProcessorClient
to consume messages from an event hub, to configure the overall properties of an EventProcessorClient
,
developers can use EventHubsContainerProperties
for the configuration. See the following section about how to work with EventHubsInboundChannelAdapter
.
13.1.4. Basic Usage
Send messages to Azure Event Hubs
Step 1. Fill the credential configuration options.
-
For credentials as connection string, configure the following properties in
application.yml
:
spring: cloud: azure: eventhubs: connection-string: ${AZURE_SERVICE_BUS_CONNECTION_STRING} processor: checkpoint-store: container-name: ${CHECKPOINT-CONTAINER} account-name: ${CHECKPOINT-STORAGE-ACCOUNT} account-key: ${CHECKPOINT-ACCESS-KEY}
-
For credentials as managed identities, configure the following properties in
application.yml
:
spring: cloud: azure: credential: managed-identity-enabled: true client-id: ${AZURE_CLIENT_ID} eventhubs: namespace: ${AZURE_SERVICE_BUS_NAMESPACE} processor: checkpoint-store: container-name: ${CONTAINER_NAME} account-name: ${ACCOUNT_NAME}
-
For credentials as service principal, configure the following properties in application.yml:
spring: cloud: azure: credential: client-id: ${AZURE_CLIENT_ID} client-secret: ${AZURE_CLIENT_SECRET} profile: tenant-id: ${AZURE_TENANT_ID} eventhubs: namespace: ${AZURE_SERVICE_BUS_NAMESPACE} processor: checkpoint-store: container-name: ${CONTAINER_NAME} account-name: ${ACCOUNT_NAME}
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 eventHubsTemplate) {
DefaultMessageHandler handler = new DefaultMessageHandler(EVENTHUB_NAME, eventHubsTemplate);
handler.setSendCallback(new ListenableFutureCallback<Void>() {
@Override
public void onSuccess(Void result) {
LOGGER.info("Message was sent successfully.");
}
@Override
public void onFailure(Throwable ex) {
LOGGER.error("There was an error sending the message.", ex);
}
});
return handler;
}
}
Step 3. Create a message gateway binding with the above message handler via a message channel.
class Demo {
@Autowired
EventHubOutboundGateway messagingGateway;
@MessagingGateway(defaultRequestChannel = OUTPUT_CHANNEL)
public interface EventHubOutboundGateway {
void send(String text);
}
}
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.
@Configuration
class Demo {
@Bean
public MessageChannel input() {
return new DirectChannel();
}
}
Step 3. Create EventHubsInboundChannelAdapter
with the bean of EventHubsMessageListenerContainer
to receive messages from Event Hubs.
@Configuration
class Demo {
private static final String INPUT_CHANNEL = "input";
private static final String EVENTHUB_NAME = "eh1";
private static final String CONSUMER_GROUP = "$Default";
@Bean
public EventHubsInboundChannelAdapter messageChannelAdapter(
@Qualifier(INPUT_CHANNEL) MessageChannel inputChannel,
EventHubsMessageListenerContainer listenerContainer) {
EventHubsInboundChannelAdapter adapter = new EventHubsInboundChannelAdapter(processorContainer);
adapter.setOutputChannel(inputChannel);
return adapter;
}
@Bean
public EventHubsMessageListenerContainer messageListenerContainer(EventHubsProcessorFactory processorFactory) {
EventHubsContainerProperties containerProperties = new EventHubsContainerProperties();
containerProperties.setEventHubName(EVENTHUB_NAME);
containerProperties.setConsumerGroup(CONSUMER_GROUP);
containerProperties.setCheckpointConfig(new CheckpointConfig(CheckpointMode.MANUAL));
return new EventHubsMessageListenerContainer(processorFactory, containerProperties);
}
}
Step 4. Create a message receiver binding with EventHubsInboundChannelAdapter via the message channel created before.
class Demo {
@ServiceActivator(inputChannel = INPUT_CHANNEL)
public void messageReceiver(byte[] payload, @Header(AzureHeaders.CHECKPOINTER) Checkpointer checkpointer) {
String message = new String(payload);
LOGGER.info("New message received: '{}'", message);
checkpointer.success()
.doOnSuccess(s -> LOGGER.info("Message '{}' successfully checkpointed", message))
.doOnError(e -> LOGGER.error("Error found", e))
.block();
}
}
Configure EventHubsMessageConverter to Customize ObjectMapper
EventHubsMessageConverter
is made as a configurable bean to allow users to customize ObjectMapper.
Batch Consumer Support
To consume messages from Event Hubs in batches is similar with the above sample, besides users should set the batch-consuming related configuration options for EventHubsInboundChannelAdapter
.
When create EventHubsInboundChannelAdapter
, the listener mode should be set as BATCH
. When create bean of EventHubsMessageListenerContainer
, set the checkpoint mode as either MANUAL
or BATCH
, and the batch options can be configured as needed.
@Configuration
class Demo {
private static final String INPUT_CHANNEL = "input";
private static final String EVENTHUB_NAME = "eh1";
private static final String CONSUMER_GROUP = "$Default";
@Bean
public EventHubsInboundChannelAdapter messageChannelAdapter(
@Qualifier(INPUT_CHANNEL) MessageChannel inputChannel,
EventHubsMessageListenerContainer listenerContainer) {
EventHubsInboundChannelAdapter adapter = new EventHubsInboundChannelAdapter(processorContainer, ListenerMode.BATCH);
adapter.setOutputChannel(inputChannel);
return adapter;
}
@Bean
public EventHubsMessageListenerContainer messageListenerContainer(EventHubsProcessorFactory processorFactory) {
EventHubsContainerProperties containerProperties = new EventHubsContainerProperties();
containerProperties.setEventHubName(EVENTHUB_NAME);
containerProperties.setConsumerGroup(CONSUMER_GROUP);
containerProperties.getBatch().setMaxSize(100);
containerProperties.setCheckpointConfig(new CheckpointConfig(CheckpointMode.MANUAL));
return new EventHubsMessageListenerContainer(processorFactory, containerProperties);
}
}
Event Hubs Message Headers
The following table illustrates how Event Hubs message properties are mapped to Spring message headers. For Azure Event Hubs, message is called as event
.
Event Hubs Event Properties | Spring Message Header Constants | Type | Description |
---|---|---|---|
Enqueued time |
EventHubsHeaders#ENQUEUED_TIME |
Instant |
The instant, in UTC, of when the event was enqueued in the Event Hub partition. |
Offset |
EventHubsHeaders#OFFSET |
Long |
The offset of the event when it was received from the associated Event Hub partition. |
Partition key |
AzureHeaders#PARTITION_KEY |
String |
The partition hashing key if it was set when originally publishing the event. |
Partition id |
AzureHeaders#RAW_PARTITION_ID |
String |
The partition id of the Event Hub. |
Sequence number |
EventHubsHeaders#SEQUENCE_NUMBER |
Long |
The sequence number assigned to the event when it was enqueued in the associated Event Hub partition. |
Last enqueued event properties |
EventHubsHeaders#LAST_ENQUEUED_EVENT_PROPERTIES |
LastEnqueuedEventProperties |
The properties of the last enqueued event in this partition. |
NA |
AzureHeaders#CHECKPOINTER |
Checkpointer |
The header for checkpoint the specific message. |
Users can parse the message headers for the related information of each event. To set a message header for the event, all customized headers will be put as an application property of an event, where the header is set as the property key. When events are received from Event Hubs, all application properties will be converted to the message header.
Message headers of partition key, enqueued time, offset and sequence number is not supported to be set manually. |
When the batch-consumer mode is enabled, the specific headers of batched messages are listed the following, which contains a list of values from each single Event Hubs event.
Event Hubs Event Properties | Spring Batch Message Header Constants | Type | Description |
---|---|---|---|
Enqueued time |
EventHubsHeaders#ENQUEUED_TIME |
List of Instant |
List of the instant, in UTC, of when each event was enqueued in the Event Hub partition. |
Offset |
EventHubsHeaders#OFFSET |
List of Long |
List of the offset of each event when it was received from the associated Event Hub partition. |
Partition key |
AzureHeaders#PARTITION_KEY |
List of String |
List of the partition hashing key if it was set when originally publishing each event. |
Sequence number |
EventHubsHeaders#SEQUENCE_NUMBER |
List of Long |
List of the sequence number assigned to each event when it was enqueued in the associated Event Hub partition. |
System properties |
EventHubsHeaders#BATCH_CONVERTED_SYSTEM_PROPERTIES |
List of Map |
List of the system properties of each event. |
Application properties |
EventHubsHeaders#BATCH_CONVERTED_APPLICATION_PROPERTIES |
List of Map |
List of the application properties of each event, where all customized message headers or event properties are placed. |
When publish messages, all the above batch headers will be removed from the messages if exist. |
13.1.5. Samples
See 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. See 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
This starter provides the following 2 parts of configuration options:
Connection Configuration Properties
This section contains the configuration options used for connecting to Azure Service Bus.
If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, see Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource. |
Property | Type | Description |
---|---|---|
spring.cloud.azure.servicebus.enabled |
boolean |
Whether an Azure Service Bus is enabled. |
spring.cloud.azure.servicebus.connection-string |
String |
Service Bus Namespace connection string value. |
spring.cloud.azure.servicebus.namespace |
String |
Service Bus Namespace value, which is the prefix of the FQDN. A FQDN should be composed of <NamespaceName>.<DomainName> |
spring.cloud.azure.servicebus.domain-name |
String |
Domain name of an Azure Service Bus Namespace value. |
Service Bus Processor Configuration Properties
The ServiceBusInboundChannelAdapter
uses the ServiceBusProcessorClient
to consume messages, to configure the overall properties of an ServiceBusProcessorClient
,
developers can use ServiceBusContainerProperties
for the configuration. See the following section about how to work with ServiceBusInboundChannelAdapter
.
13.2.4. Basic Usage
Send Messages to Azure Service Bus
Step 1. Fill the credential configuration options.
-
For credentials as connection string, configure the following properties in application.yml:
spring: cloud: azure: servicebus: connection-string: ${AZURE_SERVICE_BUS_CONNECTION_STRING}
-
For credentials as managed identities, configure the following properties in application.yml:
spring: cloud: azure: credential: managed-identity-enabled: true client-id: ${AZURE_CLIENT_ID} profile: tenant-id: ${AZURE_TENANT_ID} servicebus: namespace: ${AZURE_SERVICE_BUS_NAMESPACE}
-
For credentials as service principal, configure the following properties in application.yml:
spring: cloud: azure: credential: client-id: ${AZURE_CLIENT_ID} client-secret: ${AZURE_CLIENT_SECRET} profile: tenant-id: ${AZURE_TENANT_ID} servicebus: namespace: ${AZURE_SERVICE_BUS_NAMESPACE}
Step 2. Create DefaultMessageHandler
with the bean of ServiceBusTemplate
to send messages to Service Bus,
set the entity type for the ServiceBusTemplate. This sample takes Service Bus Queue as example.
class Demo {
private static final String OUTPUT_CHANNEL = "queue.output";
@Bean
@ServiceActivator(inputChannel = OUTPUT_CHANNEL)
public MessageHandler queueMessageSender(ServiceBusTemplate serviceBusTemplate) {
serviceBusTemplate.setDefaultEntityType(ServiceBusEntityType.QUEUE);
DefaultMessageHandler handler = new DefaultMessageHandler(QUEUE_NAME, serviceBusTemplate);
handler.setSendCallback(new ListenableFutureCallback<Void>() {
@Override
public void onSuccess(Void result) {
LOGGER.info("Message was sent successfully.");
}
@Override
public void onFailure(Throwable ex) {
LOGGER.info("There was an error sending the message.");
}
});
return handler;
}
}
Step 3. Create a message gateway binding with the above message handler via a message channel.
class Demo {
@Autowired
QueueOutboundGateway messagingGateway;
@MessagingGateway(defaultRequestChannel = OUTPUT_CHANNEL)
public interface QueueOutboundGateway {
void send(String text);
}
}
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.
@Configuration
class Demo {
private static final String INPUT_CHANNEL = "input";
@Bean
public MessageChannel input() {
return new DirectChannel();
}
}
Step 3. Create ServiceBusInboundChannelAdapter
with the bean of ServiceBusMessageListenerContainer
to receive messages to Service Bus. This sample takes Service Bus Queue as example.
@Configuration
class Demo {
private static final String QUEUE_NAME = "queue1";
@Bean
public ServiceBusMessageListenerContainer messageListenerContainer(ServiceBusProcessorFactory processorFactory) {
ServiceBusContainerProperties containerProperties = new ServiceBusContainerProperties();
containerProperties.setEntityName(QUEUE_NAME);
containerProperties.setAutoComplete(false);
return new ServiceBusMessageListenerContainer(processorFactory, containerProperties);
}
@Bean
public ServiceBusInboundChannelAdapter queueMessageChannelAdapter(
@Qualifier(INPUT_CHANNEL) MessageChannel inputChannel,
ServiceBusMessageListenerContainer listenerContainer) {
ServiceBusInboundChannelAdapter adapter = new ServiceBusInboundChannelAdapter(listenerContainer);
adapter.setOutputChannel(inputChannel);
return adapter;
}
}
Step 4. Create a message receiver binding with ServiceBusInboundChannelAdapter via the message channel we created before.
class Demo {
@ServiceActivator(inputChannel = INPUT_CHANNEL)
public void messageReceiver(byte[] payload, @Header(AzureHeaders.CHECKPOINTER) Checkpointer checkpointer) {
String message = new String(payload);
LOGGER.info("New message received: '{}'", message);
checkpointer.success()
.doOnSuccess(s -> LOGGER.info("Message '{}' successfully checkpointed", message))
.doOnError(e -> LOGGER.error("Error found", e))
.block();
}
}
Configure ServiceBusMessageConverter to Customize ObjectMapper
ServiceBusMessageConverter
is made as a configurable bean to allow users to customize ObjectMapper.
Service Bus Message Headers
For some Service Bus headers that can be mapped to multiple Spring header constants, the priority of different Spring headers is listed.
Service Bus Message Headers and Properties | Spring Message Header Constants | Type | Configurable | Description |
---|---|---|---|---|
Content type |
MessageHeaders#CONTENT_TYPE |
String |
Yes |
The RFC2045 Content-Type descriptor of the message. |
Correlation id |
ServiceBusMessageHeaders#CORRELATION_ID |
String |
Yes |
The correlation id of the message |
Message id |
ServiceBusMessageHeaders#MESSAGE_ID |
String |
Yes |
The message id of the message, this header has higher priority than |
Message id |
MessageHeaders#ID |
UUID |
Yes |
The message id of the message, this header has lower priority than |
Partition key |
ServiceBusMessageHeaders#PARTITION_KEY |
String |
Yes |
The partition key for sending the message to a partitioned entity. |
Reply to |
MessageHeaders#REPLY_CHANNEL |
String |
Yes |
The address of an entity to send replies to. |
Reply to session id |
ServiceBusMessageHeaders#REPLY_TO_SESSION_ID |
String |
Yes |
The ReplyToGroupId property value of the message. |
Scheduled enqueue time utc |
ServiceBusMessageHeaders#SCHEDULED_ENQUEUE_TIME |
OffsetDateTime |
Yes |
The datetime at which the message should be enqueued in Service Bus, this header has higher priority than |
Scheduled enqueue time utc |
AzureHeaders#SCHEDULED_ENQUEUE_MESSAGE |
Integer |
Yes |
The datetime at which the message should be enqueued in Service Bus, this header has lower priority than |
Session id |
ServiceBusMessageHeaders#SESSION_ID |
String |
Yes |
The session identifier for a session-aware entity. |
Time to live |
ServiceBusMessageHeaders#TIME_TO_LIVE |
Duration |
Yes |
The duration of time before this message expires. |
To |
ServiceBusMessageHeaders#TO |
String |
Yes |
The "to" address of the message, reserved for future use in routing scenarios and presently ignored by the broker itself. |
Subject |
ServiceBusMessageHeaders#SUBJECT |
String |
Yes |
The subject for the message. |
Dead letter error description |
ServiceBusMessageHeaders#DEAD_LETTER_ERROR_DESCRIPTION |
String |
No |
The description for a message that has been dead-lettered. |
Dead letter reason |
ServiceBusMessageHeaders#DEAD_LETTER_REASON |
String |
No |
The reason a message was dead-lettered. |
Dead letter source |
ServiceBusMessageHeaders#DEAD_LETTER_SOURCE |
String |
No |
The entity in which the message was dead-lettered. |
Delivery count |
ServiceBusMessageHeaders#DELIVERY_COUNT |
long |
No |
The number of the times this message was delivered to clients. |
Enqueued sequence number |
ServiceBusMessageHeaders#ENQUEUED_SEQUENCE_NUMBER |
long |
No |
The enqueued sequence number assigned to a message by Service Bus. |
Enqueued time |
ServiceBusMessageHeaders#ENQUEUED_TIME |
OffsetDateTime |
No |
The datetime at which this message was enqueued in Service Bus. |
Expires at |
ServiceBusMessageHeaders#EXPIRES_AT |
OffsetDateTime |
No |
The datetime at which this message will expire. |
Lock token |
ServiceBusMessageHeaders#LOCK_TOKEN |
String |
No |
The lock token for the current message. |
Locked until |
ServiceBusMessageHeaders#LOCKED_UNTIL |
OffsetDateTime |
No |
The datetime at which the lock of this message expires. |
Sequence number |
ServiceBusMessageHeaders#SEQUENCE_NUMBER |
long |
No |
The unique number assigned to a message by Service Bus. |
State |
ServiceBusMessageHeaders#STATE |
ServiceBusMessageState |
No |
The state of the message, which can be Active, Deferred, or Scheduled. |
Partition Key Support
This starter supports Service Bus partitioning by allowing setting partition key and session id in the message header. This section introduces how to set partition key for messages.
Recommended: Use ServiceBusMessageHeaders.PARTITION_KEY
as the key of the header.
public class SampleController {
@PostMapping("/messages")
public ResponseEntity<String> sendMessage(@RequestParam String message) {
LOGGER.info("Going to add message {} to Sinks.Many.", message);
many.emitNext(MessageBuilder.withPayload(message)
.setHeader(ServiceBusMessageHeaders.PARTITION_KEY, "Customize partition key")
.build(), Sinks.EmitFailureHandler.FAIL_FAST);
return ResponseEntity.ok("Sent!");
}
}
Not recommended but currently supported: AzureHeaders.PARTITION_KEY
as the key of the header.
public class SampleController {
@PostMapping("/messages")
public ResponseEntity<String> sendMessage(@RequestParam String message) {
LOGGER.info("Going to add message {} to Sinks.Many.", message);
many.emitNext(MessageBuilder.withPayload(message)
.setHeader(AzureHeaders.PARTITION_KEY, "Customize partition key")
.build(), Sinks.EmitFailureHandler.FAIL_FAST);
return ResponseEntity.ok("Sent!");
}
}
When both ServiceBusMessageHeaders.PARTITION_KEY and AzureHeaders.PARTITION_KEY are set in the message headers,
ServiceBusMessageHeaders.PARTITION_KEY is preferred.
|
Session Support
This example demonstrates how to manually set the session id of a message in the application.
public class SampleController {
@PostMapping("/messages")
public ResponseEntity<String> sendMessage(@RequestParam String message) {
LOGGER.info("Going to add message {} to Sinks.Many.", message);
many.emitNext(MessageBuilder.withPayload(message)
.setHeader(ServiceBusMessageHeaders.SESSION_ID, "Customize session id")
.build(), Sinks.EmitFailureHandler.FAIL_FAST);
return ResponseEntity.ok("Sent!");
}
}
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.2.5. Samples
See azure-spring-boot-samples for more details.
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
This starter provides the following configuration options:
Connection Configuration Properties
This section contains the configuration options used for connecting to Azure Storage Queue.
If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, see Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource. |
Property | Type | Description |
---|---|---|
spring.cloud.azure.storage.queue.enabled |
boolean |
Whether an Azure Storage Queue is enabled. |
spring.cloud.azure.storage.queue.connection-string |
String |
Storage Queue Namespace connection string value. |
spring.cloud.azure.storage.queue.accountName |
String |
Storage Queue account name. |
spring.cloud.azure.storage.queue.accountKey |
String |
Storage Queue account key. |
spring.cloud.azure.storage.queue.endpoint |
String |
Storage Queue service endpoint. |
spring.cloud.azure.storage.queue.sasToken |
String |
Sas token credential |
spring.cloud.azure.storage.queue.serviceVersion |
QueueServiceVersion |
QueueServiceVersion that is used when making API requests. |
spring.cloud.azure.storage.queue.messageEncoding |
String |
Queue message encoding. |
13.3.4. Basic Usage
Send messages to Azure Storage Queue
Step 1. Fill the credential configuration options.
-
For credentials as connection string, configure the following properties in application.yml:
spring: cloud: azure: storage: queue: connection-string: ${AZURE_SERVICE_BUS_CONNECTION_STRING}
-
For credentials as managed identities, configure the following properties in application.yml:
spring: cloud: azure: credential: managed-identity-enabled: true client-id: ${AZURE_CLIENT_ID} profile: tenant-id: ${AZURE_TENANT_ID} storage: queue: namespace: ${AZURE_SERVICE_BUS_NAMESPACE}
-
For credentials as service principal, configure the following properties in application.yml:
spring: cloud: azure: credential: client-id: ${AZURE_CLIENT_ID} client-secret: ${AZURE_CLIENT_SECRET} profile: tenant-id: ${AZURE_TENANT_ID} storage: queue: namespace: ${AZURE_SERVICE_BUS_NAMESPACE}
Step 2. Create DefaultMessageHandler
with the bean of StorageQueueTemplate
to send messages to Storage Queue.
class Demo {
private static final String STORAGE_QUEUE_NAME = "example";
private static final String OUTPUT_CHANNEL = "output";
@Bean
@ServiceActivator(inputChannel = OUTPUT_CHANNEL)
public MessageHandler messageSender(StorageQueueTemplate storageQueueTemplate) {
DefaultMessageHandler handler = new DefaultMessageHandler(STORAGE_QUEUE_NAME, storageQueueTemplate);
handler.setSendCallback(new ListenableFutureCallback<Void>() {
@Override
public void onSuccess(Void result) {
LOGGER.info("Message was sent successfully.");
}
@Override
public void onFailure(Throwable ex) {
LOGGER.info("There was an error sending the message.");
}
});
return handler;
}
}
Step 3. Create a Message gateway binding with the above message handler via a message channel.
class Demo {
@Autowired
StorageQueueOutboundGateway storageQueueOutboundGateway;
@MessagingGateway(defaultRequestChannel = OUTPUT_CHANNEL)
public interface StorageQueueOutboundGateway {
void send(String text);
}
}
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 StorageQueueTemplate
to receive messages to Storage Queue.
class Demo {
private static final String STORAGE_QUEUE_NAME = "example";
@Bean
@InboundChannelAdapter(channel = INPUT_CHANNEL, poller = @Poller(fixedDelay = "1000"))
public StorageQueueMessageSource storageQueueMessageSource(StorageQueueTemplate storageQueueTemplate) {
return new StorageQueueMessageSource(STORAGE_QUEUE_NAME, storageQueueTemplate);
}
}
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))
.block();
}
}
13.3.5. Samples
See 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 provides the function to store such offsets inside Azure Storage.
Partitioning Support
Event Hubs provides a similar concept of physical partition as Kafka. But unlike Kafka’s auto re-balancing between consumers and partitions, Event Hubs provides a kind of preemptive mode. The storage account acts as a lease to determine which partition is owned by which consumer. When a new consumer starts, it will try to steal some partitions from most heavy-loaded consumers to achieve the workload balancing.
To specify the load balancing strategy, properties of spring.cloud.stream.eventhubs.bindings.<binding-name>.consumer.load-balancing.*
are provided. See the consumer properties for more details.
Batch Consumer Support
Spring Cloud Azure Stream Event Hubs binder supports Spring Cloud Stream Batch Consumer feature.
To work with the batch-consumer mode, the property of spring.cloud.stream.bindings.<binding-name>.consumer.batch-mode
should be set as true
. When enabled, an Message of which the payload is a list of batched events will be received and passed to the Consumer
function. Each message header is also converted as a list, of which the content is the associated header value parsed from each event. For the communal headers of partition id, checkpointer and last enqueued properties, they are presented as a single value for the entire batch of events shares the same one. See Event Hubs Message Headers for more details.
The checkpoint header only exists when MANUAL checkpoint mode is used. |
Checkpointing of batch consumer supports two modes: BATCH
and MANUAL
. BATCH
mode is an auto checkpointing mode to checkpoint the entire batch of events together once they are received by the binder. MANUAL
mode is to checkpoint the events by users. When used, the
Checkpointer will be passed into the message header, and users could use it to do checkpointing.
The batch size can be specified by properties of max-size
and max-wait-time
with prefix as spring.cloud.stream.eventhubs.bindings.<binding-name>.consumer.batch.
, where max-size
is a necessary property while max-wait-time
is optional. See 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 Spring Cloud Azure Stream Event Hubs Starter, as shown in the following example for Maven:
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-stream-eventhubs</artifactId>
</dependency>
14.1.3. Configuration
The binder provides the following 3 parts of configuration options:
Connection Configuration Properties
This section contains the configuration options used for connecting to Azure Event Hubs.
If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, See Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource. |
Property | Type | Description |
---|---|---|
spring.cloud.azure.eventhubs.enabled |
boolean |
Whether an Azure Event Hubs is enabled. |
spring.cloud.azure.eventhubs.connection-string |
String |
Event Hubs Namespace connection string value. |
spring.cloud.azure.eventhubs.namespace |
String |
Event Hubs Namespace value, which is the prefix of the FQDN. A FQDN should be composed of <NamespaceName>.<DomainName> |
spring.cloud.azure.eventhubs.domain-name |
String |
Domain name of an Azure Event Hubs Namespace value. |
spring.cloud.azure.eventhubs.custom-endpoint-address |
String |
Custom Endpoint address. |
Common Azure Service SDK configuration options are configurable for the Spring Cloud Azure Stream Event Hubs binder as well. The supported configuration options are introduced in the Configuration page, and could be configured with either the unified prefix spring.cloud.azure. or the prefix of spring.cloud.azure.eventhubs. .
|
The binder also supports Spring Could Azure Resource Manager by default. To learn about how to retrieve the connection string with security principals that are not granted with Data
related roles, see the resource manager example for details.
Checkpoint Configuration Properties
This section contains the configuration options for the Storage Blobs service, which is used for persisting partition ownership and checkpoint information.
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. |
Property | Type | Description |
---|---|---|
spring.cloud.azure.eventhubs.processor.checkpoint-store.create-container-if-not-exists |
Boolean |
Whether to allow creating containers if not exists. |
spring.cloud.azure.eventhubs.processor.checkpoint-store.account-name |
String |
Name for the storage account. |
spring.cloud.azure.eventhubs.processor.checkpoint-store.account-key |
String |
Storage account access key. |
spring.cloud.azure.eventhubs.processor.checkpoint-store.container-name |
String |
Storage container name. |
Common Azure Service SDK configuration options are configurable for Storage Blob checkpoint store as well. The supported configuration options are introduced in the Configuration page, and could be configured with either the unified prefix spring.cloud.azure. or the prefix of spring.cloud.azure.eventhubs.processor.checkpoint-store .
|
Azure Event Hubs Binding Configuration Properties
The following options are divided into four sections: Consumer Properties, Advanced Consumer Configurations, Producer Properties and Advanced Producer Configurations.
Consumer Properties
These properties are exposed via EventHubsConsumerProperties
.
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 |
spring.cloud.stream.eventhubs.bindings.<binding-name>.consumer.checkpoint.interval |
Duration |
Decides the time interval to do one checkpoint. Will take effect only when |
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 |
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 StartPositionProperties which includes properties of offset, sequence number, enqueued date time and whether inclusive. For example, you can set it as
|
spring:
cloud:
stream:
eventhubs:
bindings:
<binding-name>:
consumer:
initial-partition-event-position:
0:
offset: earliest
1:
sequence-number: 100
2:
enqueued-date-time: 2022-01-12T13:32:47.650005Z
4:
inclusive: false
Advanced Consumer Configuration
The above connection, checkpoint and common Azure SDK client configuration are supported to be customized for each binder consumer, which can be configured with the prefix spring.cloud.stream.eventhubs.bindings.<binding-name>.consumer.
.
Producer Properties
These properties are exposed via EventHubsProducerProperties
.
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 the following properties in application.yml:
spring:
cloud:
azure:
eventhubs:
connection-string: ${EVENTHUB_NAMESPACE_CONNECTION_STRING}
processor:
checkpoint-store:
container-name: ${CHECKPOINT_CONTAINER}
account-name: ${CHECKPOINT_STORAGE_ACCOUNT}
account-key: ${CHECKPOINT_ACCESS_KEY}
stream:
function:
definition: consume;supply
bindings:
consume-in-0:
destination: ${EVENTHUB_NAME}
group: ${CONSUMER_GROUP}
supply-out-0:
destination: ${THE_SAME_EVENTHUB_NAME_AS_ABOVE}
eventhubs:
bindings:
consume-in-0:
consumer:
checkpoint:
mode: MANUAL
-
For credentials as service principal, configure the following properties in application.yml:
spring:
cloud:
azure:
credential:
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
profile:
tenant-id: ${AZURE_TENANT_ID}
eventhubs:
namespace: ${EVENTHUB_NAMESPACE}
processor:
checkpoint-store:
container-name: ${CONTAINER_NAME}
account-name: ${ACCOUNT_NAME}
stream:
function:
definition: consume;supply
bindings:
consume-in-0:
destination: ${EVENTHUB_NAME}
group: ${CONSUMER_GROUP}
supply-out-0:
destination: ${THE_SAME_EVENTHUB_NAME_AS_ABOVE}
eventhubs:
bindings:
consume-in-0:
consumer:
checkpoint:
mode: MANUAL
-
For credentials as managed identites, configure the following properties in application.yml:
spring:
cloud:
azure:
credential:
managed-identity-enabled: true
client-id: ${AZURE_MANAGED_IDENTITY_CLIENT_ID} # Only needed when using a user-assigned managed identity
eventhubs:
namespace: ${EVENTHUB_NAMESPACE}
processor:
checkpoint-store:
container-name: ${CONTAINER_NAME}
account-name: ${ACCOUNT_NAME}
stream:
function:
definition: consume;supply
bindings:
consume-in-0:
destination: ${EVENTHUB_NAME}
group: ${CONSUMER_GROUP}
supply-out-0:
destination: ${THE_SAME_EVENTHUB_NAME_AS_ABOVE}
eventhubs:
bindings:
consume-in-0:
consumer:
checkpoint:
mode: MANUAL
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))
.block();
};
}
@Bean
public Supplier<Message<String>> supply() {
return () -> {
LOGGER.info("Sending message, sequence " + i);
return MessageBuilder.withPayload("Hello world, " + i++).build();
};
}
Partitioning Support
A PartitionSupplier
with user-provided partition information will be created to configure the partition information about the message to be sent, the following is the process of obtaining different priorities of the partition ID and key:
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 the following code to send messages and consume in batches.
@Bean
public Consumer<Message<List<String>>> consume() {
return message -> {
for (int i = 0; i < message.getPayload().size(); i++) {
LOGGER.info("New message received: '{}', partition key: {}, sequence number: {}, offset: {}, enqueued time: {}",
message.getPayload().get(i),
((List<Object>) message.getHeaders().get(EventHubsHeaders.BATCH_CONVERTED_PARTITION_KEY)).get(i),
((List<Object>) message.getHeaders().get(EventHubsHeaders.BATCH_CONVERTED_SEQUENCE_NUMBER)).get(i),
((List<Object>) message.getHeaders().get(EventHubsHeaders.BATCH_CONVERTED_OFFSET)).get(i),
((List<Object>) message.getHeaders().get(EventHubsHeaders.BATCH_CONVERTED_ENQUEUED_TIME)).get(i));
}
};
}
@Bean
public Supplier<Message<String>> supply() {
return () -> {
LOGGER.info("Sending message, sequence " + i);
return MessageBuilder.withPayload("\"test"+ i++ +"\"").build();
};
}
For checkpointing mode as MANUAL
, you can use the following code to send messages and consume/checkpoint in batches.
@Bean
public Consumer<Message<List<String>>> consume() {
return message -> {
for (int i = 0; i < message.getPayload().size(); i++) {
LOGGER.info("New message received: '{}', partition key: {}, sequence number: {}, offset: {}, enqueued time: {}",
message.getPayload().get(i),
((List<Object>) message.getHeaders().get(EventHubHeaders.BATCH_CONVERTED_PARTITION_KEY)).get(i),
((List<Object>) message.getHeaders().get(EventHubHeaders.BATCH_CONVERTED_SEQUENCE_NUMBER)).get(i),
((List<Object>) message.getHeaders().get(EventHubHeaders.BATCH_CONVERTED_OFFSET)).get(i),
((List<Object>) message.getHeaders().get(EventHubHeaders.BATCH_CONVERTED_ENQUEUED_TIME)).get(i));
}
Checkpointer checkpointer = (Checkpointer) message.getHeaders().get(CHECKPOINTER);
checkpointer.success()
.doOnSuccess(success -> LOGGER.info("Message '{}' successfully checkpointed", message.getPayload()))
.doOnError(error -> LOGGER.error("Exception found", error))
.block();
};
}
@Bean
public Supplier<Message<String>> supply() {
return () -> {
LOGGER.info("Sending message, sequence " + i);
return MessageBuilder.withPayload("\"test"+ i++ +"\"").build();
};
}
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, see the official doc of Spring Cloud Stream Content Type Negotiation.
|
Error Channels
-
Consumer error channel
This channel is open by default, you can handle the error message in this way:
// Replace destination with spring.cloud.stream.bindings.input.destination
// Replace group with spring.cloud.stream.bindings.input.group
@ServiceActivator(inputChannel = "{destination}.{group}.errors")
public void consumerError(Message<?> message) {
LOGGER.error("Handling customer ERROR: " + message);
}
-
Producer error channel
This channel is not open by default. You need to add a configuration in your application.properties to enable it, like this:
spring.cloud.stream.default.producer.errorChannelEnabled=true
You can handle the error message in this way:
// Replace destination with spring.cloud.stream.bindings.output.destination
@ServiceActivator(inputChannel = "{destination}.errors")
public void producerError(Message<?> message) {
LOGGER.error("Handling Producer ERROR: " + message);
}
-
Global default error channel
A global error channel called "errorChannel" is created by default Spring Integration, which allows users to subscribe many endpoints to it.
@ServiceActivator(inputChannel = "errorChannel")
public void producerError(Message<?> message) {
LOGGER.error("Handling ERROR: " + message);
}
Event Hubs Message Headers
See the Event Hubs message headers for the basic message headers supported.
Multiple Binder Support
Connection to multiple Event Hubs namespaces is also supported by using multiple binders.This sample takes connection string as example. Credentials of service principals and managed identities are also supported, users can set related properties in each binder’s environment settings.
Step 1. To use multiple binders of EventHubs, we need to configure the following properties in application.yml
spring:
cloud:
stream:
function:
definition: consume1;supply1;consume2;supply2
bindings:
consume1-in-0:
destination: ${EVENTHUB_NAME_01}
group: ${CONSUMER_GROUP_01}
supply1-out-0:
destination: ${THE_SAME_EVENTHUB_NAME_01_AS_ABOVE}
consume2-in-0:
binder: eventhub-2
destination: ${EVENTHUB_NAME_02}
group: ${CONSUMER_GROUP_02}
supply2-out-0:
binder: eventhub-2
destination: ${THE_SAME_EVENTHUB_NAME_02_AS_ABOVE}
binders:
eventhub-1:
type: eventhubs
default-candidate: true
environment:
spring:
cloud:
azure:
eventhubs:
connection-string: ${EVENTHUB_NAMESPACE_01_CONNECTION_STRING}
processor:
checkpoint-store:
container-name: ${CHECKPOINT_CONTAINER_01}
account-name: ${CHECKPOINT_STORAGE_ACCOUNT}
account-key: ${CHECKPOINT_ACCESS_KEY}
eventhub-2:
type: eventhubs
default-candidate: false
environment:
spring:
cloud:
azure:
eventhubs:
connection-string: ${EVENTHUB_NAMESPACE_02_CONNECTION_STRING}
processor:
checkpoint-store:
container-name: ${CHECKPOINT_CONTAINER_02}
account-name: ${CHECKPOINT_STORAGE_ACCOUNT}
account-key: ${CHECKPOINT_ACCESS_KEY}
eventhubs:
bindings:
consume1-in-0:
consumer:
checkpoint:
mode: MANUAL
consume2-in-0:
consumer:
checkpoint:
mode: MANUAL
poller:
initial-delay: 0
fixed-delay: 1000
Step 2. we need define two suppliers and two consumers
@Bean
public Supplier<Message<String>> supply1() {
return () -> {
LOGGER.info("Sending message1, sequence1 " + i);
return MessageBuilder.withPayload("Hello world1, " + i++).build();
};
}
@Bean
public Supplier<Message<String>> supply2() {
return () -> {
LOGGER.info("Sending message2, sequence2 " + j);
return MessageBuilder.withPayload("Hello world2, " + j++).build();
};
}
@Bean
public Consumer<Message<String>> consume1() {
return message -> {
Checkpointer checkpointer = (Checkpointer) message.getHeaders().get(CHECKPOINTER);
LOGGER.info("New message1 received: '{}'", message);
checkpointer.success()
.doOnSuccess(success -> LOGGER.info("Message1 '{}' successfully checkpointed", message))
.doOnError(error -> LOGGER.error("Exception found", error))
.block();
};
}
@Bean
public Consumer<Message<String>> consume2() {
return message -> {
Checkpointer checkpointer = (Checkpointer) message.getHeaders().get(CHECKPOINTER);
LOGGER.info("New message2 received: '{}'", message);
checkpointer.success()
.doOnSuccess(success -> LOGGER.info("Message2 '{}' successfully checkpointed", message))
.doOnError(error -> LOGGER.error("Exception found", error))
.block();
};
}
Resource Provision
Event Hubs binder supports provisioning of event hub and consumer group, users could use the following properties to enable provisioning.
spring:
cloud:
azure:
credential:
tenant-id: ${AZURE_TENANT_ID}
profile:
subscription-id: ${AZURE_SUBSCRIPTION_ID}
eventhubs:
resource:
resource-group: ${AZURE_EVENTHUBS_RESOURECE_GROUP}
14.1.5. Samples
See 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 Spring Cloud Azure Stream Service Bus Starter, as shown in the following example for Maven:
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-stream-servicebus</artifactId>
</dependency>
14.2.3. Configuration
The binder provides the following 2 parts of configuration options:
Connection Configuration Properties
This section contains the configuration options used for connecting to Azure Service Bus.
If you choose to use a security principal to authenticate and authorize with Azure Active Directory for accessing an Azure resource, see Authorize access with Azure AD to make sure the security principal has been granted the sufficient permission to access the Azure resource. |
Property | Type | Description |
---|---|---|
spring.cloud.azure.servicebus.enabled |
boolean |
Whether an Azure Service Bus is enabled. |
spring.cloud.azure.servicebus.connection-string |
String |
Service Bus Namespace connection string value. |
spring.cloud.azure.servicebus.namespace |
String |
Service Bus Namespace value, which is the prefix of the FQDN. A FQDN should be composed of <NamespaceName>.<DomainName> |
spring.cloud.azure.servicebus.domain-name |
String |
Domain name of an Azure Service Bus Namespace value. |
Common Azure Service SDK configuration options are configurable for the Spring Cloud Azure Stream Service Bus binder as well. The supported configuration options are introduced in the Configuration page, and could be configured with either the unified prefix spring.cloud.azure. or the prefix of spring.cloud.azure.servicebus. .
|
The binder also supports Spring Could Azure Resource Manager by default. To learn about how to retrieve the connection string with security principals that are not granted with Data
related roles, see the resource manager example for details.
Azure Service Bus Binding Configuration Properties
The following options are divided into four sections: Consumer Properties, Advanced Consumer Configurations, Producer Properties and Advanced Producer Configurations.
Consumer Properties
These properties are exposed via ServiceBusConsumerProperties
.
Property | Type | Default | Description |
---|---|---|---|
spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.requeue-rejected |
boolean |
false |
If the failed messages are routed to the DLQ. |
spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.max-concurrent-calls |
Integer |
1 |
Max concurrent messages that the Service Bus processor client should process. |
spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.max-concurrent-sessions |
Integer |
null |
Maximum number of concurrent sessions to process at any given time. |
spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.session-enabled |
Boolean |
null |
Whether session is enabled. |
spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.prefetch-count |
Integer |
0 |
The prefetch count of the Service Bus processor client. |
spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.sub-queue |
SubQueue |
none |
The type of the sub queue to connect to. |
spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.max-auto-lock-renew-duration |
Duration |
5m |
The amount of time to continue auto-renewing the lock. |
spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.receive-mode |
ServiceBusReceiveMode |
peek_lock |
The receive mode of the Service Bus processor client. |
spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.auto-complete |
Boolean |
true |
Whether to settle messages automatically. If set as false, a message header of |
Advanced Consumer Configuration
The above connection and common Azure SDK client configuration are supported to be customized for each binder consumer, which can be configured with the prefix spring.cloud.stream.servicebus.bindings.<binding-name>.consumer.
.
Producer Properties
These properties are exposed via ServiceBusProducerProperties
.
Property | Type | Default | Description |
---|---|---|---|
spring.cloud.stream.servicebus.bindings.<binding-name>.producer.sync |
boolean |
false |
Switch flag for sync of producer. |
spring.cloud.stream.servicebus.bindings.<binding-name>.producer.send-timeout |
long |
10000 |
Timeout value for sending of producer. |
spring.cloud.stream.servicebus.bindings.<binding-name>.producer.entity-type |
ServiceBusEntityType |
null |
Service Bus entity type of the producer, required for the binding producer. |
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 the following properties in application.yml:
spring: cloud: azure: servicebus: connection-string: ${SERVICEBUS_NAMESPACE_CONNECTION_STRING} stream: function: definition: consume;supply bindings: consume-in-0: destination: ${SERVICEBUS_ENTITY_NAME} # If you use Service Bus Topic, please add the following configuration # group: ${SUBSCRIPTION_NAME} supply-out-0: destination: ${SERVICEBUS_ENTITY_NAME_SAME_AS_ABOVE} servicebus: bindings: consume-in-0: consumer: auto-complete: false supply-out-0: producer: entity-type: queue # set as "topic" if you use Service Bus Topic
-
For credentials as service principal, configure the following properties in application.yml:
spring: cloud: azure: credential: client-id: ${AZURE_CLIENT_ID} client-secret: ${AZURE_CLIENT_SECRET} profile: tenant-id: ${AZURE_TENANT_ID} servicebus: namespace: ${SERVICEBUS_NAMESPACE} stream: function: definition: consume;supply bindings: consume-in-0: destination: ${SERVICEBUS_ENTITY_NAME} # If you use Service Bus Topic, please add the following configuration # group: ${SUBSCRIPTION_NAME} supply-out-0: destination: ${SERVICEBUS_ENTITY_NAME_SAME_AS_ABOVE} servicebus: bindings: consume-in-0: consumer: auto-complete: false supply-out-0: producer: entity-type: queue # set as "topic" if you use Service Bus Topic
-
For credentials as managed identities, configure the following properties in application.yml:
spring: cloud: azure: credential: managed-identity-enabled: true client-id: ${MANAGED_IDENTITY_CLIENT_ID} # Only needed when using a user-assigned managed identity servicebus: namespace: ${SERVICEBUS_NAMESPACE} stream: function: definition: consume;supply bindings: consume-in-0: destination: ${SERVICEBUS_ENTITY_NAME} # If you use Service Bus Topic, please add the following configuration # group: ${SUBSCRIPTION_NAME} supply-out-0: destination: ${SERVICEBUS_ENTITY_NAME_SAME_AS_ABOVE} servicebus: bindings: consume-in-0: consumer: auto-complete: false supply-out-0: producer: entity-type: queue # set as "topic" if you use Service Bus Topic
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))
.block();
};
}
@Bean
public Supplier<Message<String>> supply() {
return () -> {
LOGGER.info("Sending message, sequence " + i);
return MessageBuilder.withPayload("Hello world, " + i++).build();
};
}
Partition Key Support
The binder supports Service Bus partitioning by allowing setting partition key and session id in the message header. This section introduces how to set partition key for messages.
Spring Cloud Stream provides a partition key SpEL expression property spring.cloud.stream.bindings.<binding-name>.producer.partition-key-expression
. For example, setting this property as "'partitionKey-' + headers[<message-header-key>]"
and add a header called <message-header-key>. Spring Cloud Stream will use the value for this header when evaluating the above expression to assign a partition key. Here is an example producer code:
@Bean
public Supplier<Message<String>> generate() {
return () -> {
String value = “random payload”;
return MessageBuilder.withPayload(value)
.setHeader("<message-header-key>", value.length() % 4)
.build();
};
}
Session Support
The binder supports message sessions of Service Bus. Session id of a message could be set via the message header.
@Bean
public Supplier<Message<String>> generate() {
return () -> {
String value = “random payload”;
return MessageBuilder.withPayload(value)
.setHeader(ServiceBusMessageHeaders.SESSION_ID, "Customize session id")
.build();
};
}
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.
|
Multiple Binder Support
Connection to multiple Service Bus namespaces is also supported by using multiple binders. This sample takes connection string as example. Credentials of service principals and managed identities are also supported, users can set related properties in each binder’s environment settings.
Step 1. To use multiple binders of ServiceBus, we need to configure the following properties in application.yml
spring:
cloud:
stream:
function:
definition: consume1;supply1;consume2;supply2
bindings:
consume1-in-0:
destination: ${SERVICEBUS_TOPIC_NAME}
group: ${SUBSCRIPTION_NAME}
supply1-out-0:
destination: ${SERVICEBUS_TOPIC_NAME_SAME_AS_ABOVE}
consume2-in-0:
binder: servicebus-2
destination: ${SERVICEBUS_QUEUE_NAME}
supply2-out-0:
binder: servicebus-2
destination: ${SERVICEBUS_QUEUE_NAME_SAME_AS_ABOVE}
binders:
servicebus-1:
type: servicebus
default-candidate: true
environment:
spring:
cloud:
azure:
servicebus:
connection-string: ${SERVICEBUS_NAMESPACE_01_CONNECTION_STRING}
servicebus-2:
type: servicebus
default-candidate: false
environment:
spring:
cloud:
azure:
servicebus:
connection-string: ${SERVICEBUS_NAMESPACE_02_CONNECTION_STRING}
servicebus:
bindings:
consume1-in-0:
consumer:
auto-complete: false
supply1-out-0:
producer:
entity-type: topic
consume2-in-0:
consumer:
auto-complete: false
supply2-out-0:
producer:
entity-type: queue
poller:
initial-delay: 0
fixed-delay: 1000
Step 2. we need define two suppliers and two consumers
@Bean
public Supplier<Message<String>> supply1() {
return () -> {
LOGGER.info("Sending message1, sequence1 " + i);
return MessageBuilder.withPayload("Hello world1, " + i++).build();
};
}
@Bean
public Supplier<Message<String>> supply2() {
return () -> {
LOGGER.info("Sending message2, sequence2 " + j);
return MessageBuilder.withPayload("Hello world2, " + j++).build();
};
}
@Bean
public Consumer<Message<String>> consume1() {
return message -> {
Checkpointer checkpointer = (Checkpointer) message.getHeaders().get(CHECKPOINTER);
LOGGER.info("New message1 received: '{}'", message);
checkpointer.success()
.doOnSuccess(s -> LOGGER.info("Message '{}' successfully checkpointed", message.getPayload()))
.doOnError(e -> LOGGER.error("Error found", e))
.block();
};
}
@Bean
public Consumer<Message<String>> consume2() {
return message -> {
Checkpointer checkpointer = (Checkpointer) message.getHeaders().get(CHECKPOINTER);
LOGGER.info("New message2 received: '{}'", message);
checkpointer.success()
.doOnSuccess(s -> LOGGER.info("Message '{}' successfully checkpointed", message.getPayload()))
.doOnError(e -> LOGGER.error("Error found", e))
.block();
};
}
Resource Provision
Service bus binder supports provisioning of queue, topic and subscription, users could use the following properties to enable provisioning.
spring:
cloud:
azure:
credential:
tenant-id: ${AZURE_TENANT_ID}
profile:
subscription-id: ${AZURE_SUBSCRIPTION_ID}
servicebus:
resource:
resource-group: ${AZURE_SERVICEBUS_RESOURECE_GROUP}
stream:
servicebus:
bindings:
<binding-name>:
consumer:
entity-type: ${SERVICEBUS_CONSUMER_ENTITY_TYPE}
14.2.5. Samples
See 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 the following dependencies if you want to migrate your Spring JMS application to use Azure Service Bus.
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-servicebus-jms</artifactId>
</dependency>
15.2. Configuration
Spring JMS general configuration is omitted for short. See Spring JMS Document 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 the following 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 . You can find other pooling configuration options (properties with prefix spring.jms.servicebus.pool. ) from the above
Configuration section.
|
15.4. Samples
See 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
Add the following dependencies if you want to migrate your Apache Kafka application to use Azure Event Hubs for Kafka.
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter</artifactId>
</dependency>
If you want to retrieve the connection string using Azure Resource Manager, 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. |
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 . For more information, see the Authentication section.
|
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 the following 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 the following 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
See 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
Add the following dependencies if you want to use the Spring Cloud Azure Redis support to your Spring Boot application using Redis.
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter</artifactId>
</dependency>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-resourcemanager</artifactId>
</dependency>
</dependencies>
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. |
Property | Description | Default Value | Required |
---|---|---|---|
spring.cloud.azure.redis.enabled |
A value that indicates whether the Azure Cache for Redis is enabled. |
true |
No |
spring.cloud.azure.redis.name |
Azure Cache for Redis instance name. |
Yes |
|
spring.cloud.azure.redis.resource.resource-group |
The resource group of Azure Cache for Redis. |
Yes |
|
spring.cloud.azure.profile.subscription-id |
The subscription id. |
Yes |
Authentication information is also required for authenticating for Azure Resource Manager. The credential related configurations of Resource Manager should be configured under prefix spring.cloud.azure . For more information, see the Authentication section.
|
17.3. Basic Usage
Add the following properties and you are good to go.
spring.cloud.azure.redis.name=${AZURE_CACHE_REDIS_NAME}
spring.cloud.azure.redis.resource.resource-group=${AZURE_CACHE_REDIS_RESOURCE_GROUP}
17.4. Samples
See azure-spring-boot-samples for more details.
18. Azure Resource Manager
Azure Resource Manager (ARM) is the deployment and management service for Azure. It provides a management layer that enables you to create, update, and delete resources in your Azure account. Spring Cloud Azure Resource Manager can help provision resources or retrieve resource metadata.
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. |
Property | Description |
---|---|
spring.cloud.azure.resource-manager.enabled |
Whether the Resource Manager is enabled. Default is true. |
spring.cloud.azure.credential.client-id |
Client id to use when performing service principal authentication with Azure. |
spring.cloud.azure.credential.client-secret |
Client secret to use when performing service principal authentication with Azure. |
spring.cloud.azure.credential.client-certificate-path |
Path of a PEM certificate file to use when performing service principal authentication with Azure. |
spring.cloud.azure.credential.client-certificate-password |
Password of the certificate file. |
spring.cloud.azure.credential.username |
Username to use when performing username/password authentication with Azure. |
spring.cloud.azure.credential.password |
Password to use when performing username/password authentication. |
spring.cloud.azure.credential.managed-identity-enabled |
Whether to enable managed identity. |
spring.cloud.azure.profile.cloud-type |
Name of the Azure cloud to connect to. |
spring.cloud.azure.profile.environment.active-directory-endpoint |
The Azure Active Directory endpoint to connect to for authentication. |
spring.cloud.azure.profile.subscription-id |
Subscription id to use when connecting to Azure resources. |
spring.cloud.azure.profile.tenant-id |
Tenant id for Azure resources. |
spring.cloud.azure.<azure-service>.namespace |
The namespace of the Azure service to provision resources with. |
spring.cloud.azure.<azure-service>.resource.resource-group |
The resource group holding an Azure service resource. |
18.3. Basic Usage
Spring Cloud Azure Resource Manager can work together with specific Spring Cloud Azure starters to retrieve connection information, such as connection strings, to connect to Azure services. It can also work together with spring-cloud-azure-starter
and third-party libraries to retrieve metadata like username/password, and to complete authentication, For more information, see the Kafka Support and Redis Support sections.
For example, to retrieve the connection string of an Azure Service, developers can use a service principal as the credential to authenticate and retrieve the connection string. The configuration is listed the follows. The provided service principal should
be assigned a role of Contributor
of the associated namespace at least. See Authorize access with Azure AD to make sure the principal has been granted the sufficient permission to access the Azure resource.
spring:
cloud:
azure:
credential:
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
profile:
tenant-id: ${AZURE_TENANT_ID}
subscription-id: ${AZURE_SUBSCRIPTION_ID}
<azure-service>:
namespace: ${SERVICEBUS_NAMESPACE}
resource:
resource-group: ${RESOURCE_GROUP}
18.4. Samples
See 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.