I have an abstract class
in a library project where I do:
this.eventGateway.publishEvent("SomeEvent", null);
and EventGateway
is this:
@MessagingGateway
public interface EventGateway {
@Gateway(requestChannel = "SomeChannel")
void publishEvent(@Header(value = "EventName") String event, @Payload Object payload);
}
and my SomeChannel
definition:
@Bean(name = "SomeChannel)
public MessageChannel someChannel() {
return new PublishSubscribeChannel(Executors.newCachedThreadPool());
}
Now it's been working fine until we wanted to use the library in a multi-tenant environment, where we want to add a header (say, "TenantId"
) to every message we send using EventGateway
. The obvious solution would be adding EventGateway
this method:
@Gateway(requestChannel = "SomeChannel")
void publishTenantEvent(@Header(value = "EventName") String event, @Header(value = "TenantId") String tenantId, @Payload Object payload);
and using it like:
final TenantContext context = TenantContextHolder.getContext();
final Tenant tenant = context.getTenant();
this.eventGateway.publishEvent("SomeEvent", tenant.getId(), null);
But changing every place where we do this.eventGateway.publishEvent("SomeEvent", null);
to above is almost equal to writing the library from scratch.
FWIW, my SomeChannel
definition is as follows:
Is there a way that I can add "TenantId"
header to every message I send if it's present in TenantContextHolder
(a class holding a thread local variable TenantContext
)?
CodePudding user response:
The @Gateway
has a:
/**
* Specify additional headers that will be added to the request message.
* @return the headers.
*/
GatewayHeader[] headers() default { };
That @GatewayHeader
has this:
/**
* @return The {@code Expression} to be evaluated to produce a value for the header.
*/
String expression() default "";
which you can declare for your use-case like:
@Gateway(requestChannel = "SomeChannel",
headers = @GatewayHeader(name = "TenantId",
expression = "T(TenantContextHolder).context.tenant.id"))
Where you have to use a fully-qualified class name for that TenantContextHolder
.
See more info about T
operator in SpEL docs: https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#expressions-types. The getters are resolved from the property names.