Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Adding a tenant ID header to MessagingGateway for every message sent

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

@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)?

>Solution :

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading