Home > Back-end >  Adding a tenant ID header to MessagingGateway for every message sent
Adding a tenant ID header to MessagingGateway for every message sent

Time:09-01

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.

  • Related