Class TenantRouter
- All Implemented Interfaces:
DescribableComponent
TenantResolver to resolve a Message (or
the ProcessingContext carrying it) to one of the known tenants, and yielding an Optional instead of
throwing when no known tenant matches.
Registered as a component, so every tenant-routing component decides the tenant of a message the same way, against one and the same set of known tenants.
The tenant may originate either from the ProcessingContext resource or from the message itself, depending on
how the message was dispatched and where in the handling chain resolution happens. Resolution only ever yields a
tenant present in the configured TenantDescriptors, so a stale or unknown tenant never routes.
- Since:
- 5.3.0
- Author:
- Jan Galinski, Laura Devriendt
-
Constructor Summary
ConstructorsConstructorDescriptionTenantRouter(TenantResolver tenantResolver, TenantDescriptors tenantDescriptors) Creates aTenantRouterwrapping the giventenantResolverand resolving against the giventenantDescriptors. -
Method Summary
Modifier and TypeMethodDescriptionattachTenant(Message message, TenantDescriptor tenant) Attaches the giventenantto the givenmessage, the inverse ofresolveFromMessage(Message), delegating to the wrappedTenantResolver.voiddescribeTo(ComponentDescriptor descriptor) Describe the properties ofthis DescribableComponentwith the givendescriptor.resolveFromContext(@Nullable ProcessingContext context) Resolves the tenant carried by the givencontext, taken from itstenant resourcewhen present, otherwise from the message the context carries.resolveFromMessage(Message message) Resolves the tenant of the givenmessage.resolveSharedTenant(Collection<? extends Message> messages) Resolves the single tenant shared by all givenmessages.
-
Constructor Details
-
TenantRouter
Creates aTenantRouterwrapping the giventenantResolverand resolving against the giventenantDescriptors.- Parameters:
tenantResolver- theTenantResolverto wraptenantDescriptors- the known tenants to resolve against
-
-
Method Details
-
resolveFromContext
Resolves the tenant carried by the givencontext, taken from itstenant resourcewhen present, otherwise from the message the context carries.A tenant resource that is present decides on its own. It is never overruled by the tenant named in the message, because that would let message metadata redirect an operation to another tenant's store whenever the resource names a tenant this application does not know. Only an absent resource falls back to the message.
- Parameters:
context- the processing context to resolve the tenant from- Returns:
- the known tenant of the context, or empty when none is available
- Throws:
TenantNotResolvedException- if the context carries a tenant that is not a known tenant
-
resolveFromMessage
Resolves the tenant of the givenmessage.Returns
Optional.empty()when the message cannot be attributed to a known tenant, so a message naming a tenant this application does not know never routes.- Parameters:
message- the message to resolve the tenant of- Returns:
- the known tenant of the message, or empty when none matches
-
attachTenant
Attaches the giventenantto the givenmessage, the inverse ofresolveFromMessage(Message), delegating to the wrappedTenantResolver.- Parameters:
message- the message to attach the giventenanttotenant- the tenant to attach to the givenmessage- Returns:
- a copy of the given
messagecarrying the giventenant
-
describeTo
Description copied from interface:DescribableComponentDescribe the properties ofthis DescribableComponentwith the givendescriptor.Components should call the appropriate
describePropertymethods on the descriptor to register their properties. The descriptor is responsible for determining how these properties are formatted and structured in the final output.Best Practices: As a general rule, all relevant fields of a
DescribableComponentimplementation should be described in this method. However, developers have discretion to include only the fields that make sense in the context. Not every field may be meaningful for description purposes, especially internal implementation details. Furthermore, components might want to expose different information based on their current state. The final decision on what properties to include lies with the person implementing thedescribeTomethod, who should focus on providing information that is useful for understanding the component's configuration and state.Example implementation:
public void describeTo(ComponentDescriptor descriptor) { descriptor.describeProperty("name", this.name); descriptor.describeProperty("enabled", this.enabled); descriptor.describeProperty("configuration", this.configuration); // A nested component descriptor.describeProperty("handlers", this.eventHandlers); // A collection }- Specified by:
describeToin interfaceDescribableComponent- Parameters:
descriptor- The component descriptor to describethis DescribableComponentn its properties in.
-