How to properly use Interceptors on Axon 3?

Hello everybody,

How exactly I can create one HandlerInterceptor for a specific command on axon 3? Someone suggest me in another topic use HandlerInterceptor to prevalidate my commands before applying the event.

Also, how I could add some metadata (tenant name) to all my commands and events?

I saw some people using CommandHandlerInterceptor and UnitOfWorkListenerAdapter to do that but I dont find those classes on AXON3.

is this right?

Im using axon 3 , spring-boot-auto-configuration. Looks so weird to me.

@Configuration
public static class CustomAxonConfiguration {

   @Autowired
   public void registerInterceptors(@Autowired CommandBus commandBus) {
      if (commandBus instanceof SimpleCommandBus) {
         SimpleCommandBus simpleCommandBus = (SimpleCommandBus) commandBus;

         simpleCommandBus.registerHandlerInterceptor(((unitOfWork, interceptorChain) -> {

            unitOfWork.transformMessage(message ->
               message.andMetaData(Collections.singletonMap("tenant", TenantUtil.get()))
            );

            return interceptorChain.proceed();
         }));
      }
   }
}

Hi Mike,

unfortunately, that’s right. RegisterHandlerInterceptor is not (yet) part of the CommandBus interface.

By the way, you probably want to use the Dispatch Interceptor here, instead of the HandlerInterceptor. The Dispatch Interceptor is always invoked in the thread that dispatches the event (the thread that will also have the ThreadLocal TenantUtil).

Cheers,

Allard

Hi Allard,

Ty so much for the help. Really. Makes all difference know from you that I’m doing something right.

I will look the Dispatch now.

One last question:

am I missing some documentation for this kind of customization in axon 3? I’m talking about code snippet.

Right now, I’m looking the source code to try figure out this.

Using dispatch:

@Configuration
public class AxonConfiguration {

    @Autowired
    public void registerInterceptors(CommandBus commandBus) {
        if (commandBus instanceof SimpleCommandBus) {

            ((SimpleCommandBus) commandBus).registerDispatchInterceptor(
                    (messages) ->
                        (index, message) ->
                            message.andMetaData(
                                    ImmutableMap.<String, String>builder()
                                        .put("tenant", TenantUtil.get())
                                        .put("useruid", UserUtil.getUID())
                                        .build()
                            )
            );
        }
    }

}

For exemple with Distributed commandBus :

@Autowired
public void configureBeanValidation(DistributedCommandBus commandBus, @Qualifier("localSegment") SimpleCommandBus localSegment) {
  commandBus.registerDispatchInterceptor(new BeanValidationInterceptor());
  localSegment.registerHandlerInterceptor(new BeanValidationInterceptor());
}

Hi everyone,

Were there any updates regarding the use of command intercepters (or command interceptors)?

Is it possible to create beans of type MessageDispatchInterceptor and have these picked up by the auto configure automatically (similar to the CorrelationDataProvider for example)?

The examples shown here work, but these are depending on an instance of the command bus to be ready, which may cause cyclic dependencies when putting other AXON related stuff in the same configuration file.

Thank you in advance,
Albert Attard

Hi Albert,

interceptors aren’t automatically picked up from the application context, because there are so many places where interceptors can be configured, that it’s unlikely you want them everywhere.

The cyclic dependency problem is a known one. I have some ideas to work around them, which I hope to be able to implement in upcoming releases. I don’t expect it will make it in 3.2.

Cheers,

Allard

Thank you, Allard for your feedback.

Here I am spesifically referring to Spring and Spring boot configuration. Can we have a configurer instead (https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html) of using autowiring? I am no spring boot expert but used it in the past and works very well. In the spring boot project, you create a configurer which allows developers using the libraries to customise things as they need.

Following is a basic example

In the xxx-spring-boot-autoconfigure project, you create an interface which developers can implement.

public interface XxxConfigurationCustomizer {
void customize(XxxBuilder builder);
}

Then you pick it up in the auto-configuration and use it

@Configuration
@ConditionalOnClass({ Xxx.class })
public class XxxAutoConfiguration {

@Autowired(required = false)
private List configurationCustomizers;

@Bean
@ConditionalOnMissingBean
public XxxBuilder xxxBuilder(/* Pass other services here /) {
final DefaultXxx.Builder builder = DefaultXxx.builder();
/
Initilaise it with the defaults */
return builder;
}

@Bean
@ConditionalOnMissingBean
public Xxx xxx(final XxxBuilder builder) {
customize(builder);
return builder.build();
}

/* Loop thourgh each customizer */
private XxxBuilder customize(final XxxBuilder builder) {
if (this.configurationCustomizers != null) {
for (final XxxConfigurationCustomizer customizer : this.configurationCustomizers) {
customizer.customize(builder);
}
}
return builder;
}
}

I do not know if this fits your scenario or not, but we can take it off-line if you like to discuss it further.

Hi Albert,

that was exactly the approach we were planning to take. Such a Configurer allows us to better control when the exact configuration happens.

Cheers,

Allard