Tenant Details
Arconia Multitenancy provides an optional mechanism for managing tenant metadata and validating tenant identifiers against a known set of tenants.
TenantDetails
The TenantDetails interface represents the core information about a tenant:
public interface TenantDetails {
String identifier();
boolean enabled();
default Map<String, Object> attributes() {
return Map.of();
}
}
Arconia provides a default implementation (Tenant record) that supports all these properties and can be constructed using a builder pattern:
var tenant = Tenant.builder()
.identifier("acme")
.enabled(true)
.addAttribute("plan", "premium")
.build();
TenantDetailsService
The TenantDetailsService interface defines the contract for loading tenant information:
public interface TenantDetailsService {
List<? extends TenantDetails> loadAllTenants();
TenantDetails loadTenantByIdentifier(String identifier);
}
When a TenantDetailsService bean is available, a DefaultTenantVerifier is auto-configured that checks each resolved tenant identifier against the service. See Tenant Verification for details.
Properties-Based Tenant Details
For simple use cases, you can define tenants directly in your application configuration:
arconia:
multitenancy:
details:
source: properties
tenants:
- identifier: acme
enabled: true
attributes:
plan: premium
region: eu-nort-1
- identifier: beans
enabled: true
- identifier: pixie
enabled: false
attributes:
onboarding: true
When source is set to properties, Arconia auto-configures a PropertiesTenantDetailsService that loads tenant details from the configuration. Requests with a tenant identifier not in the list or for a disabled tenant will be rejected.
| Property | Default | Description |
|---|---|---|
|
|
The source of tenant details. Options: |
|
|
List of tenant configurations. |
|
Unique identifier for the tenant. Required. |
|
|
|
Whether the tenant is enabled. |
|
|
Additional metadata for the tenant as key-value pairs. |
Custom TenantDetailsService
For dynamic tenant management (e.g., loading tenants from a database), implement the TenantDetailsService interface and register it as a Spring bean:
import io.arconia.multitenancy.core.tenantdetails.TenantDetails;
import io.arconia.multitenancy.core.tenantdetails.TenantDetailsService;
@Bean
TenantDetailsService tenantDetailsService(TenantRepository tenantRepository) {
return new TenantDetailsService() {
@Override
public List<? extends TenantDetails> loadAllTenants() {
return tenantRepository.findAll();
}
@Override
public TenantDetails loadTenantByIdentifier(String identifier) {
return tenantRepository.findByIdentifier(identifier);
}
};
}
When a custom TenantDetailsService is registered, tenant verification is automatically enabled.
Tenant Verification
The TenantVerifier interface defines the contract for verifying that a resolved tenant identifier is valid and allowed to proceed. When a TenantDetailsService is available, Arconia auto-configures a DefaultTenantVerifier that checks the tenant exists and is enabled.
Entry points such as the TenantContextFilter call the verifier directly before establishing the tenant context. If verification fails, a TenantVerificationException is thrown, resulting in an HTTP 400 Bad Request response.
You can provide a custom TenantVerifier bean to implement your own verification logic:
import io.arconia.multitenancy.core.tenantdetails.TenantVerifier;
@Bean
TenantVerifier tenantVerifier() {
return tenantIdentifier -> {
// Custom verification logic (e.g., check quotas, feature flags)
};
}