Unwanted Multiple Axon Server Connections on Boot-up

I’m trying to set up Axon in an existing application. The existing application has a Spring context, but is not a Spring boot application, so I’ve had to do a lot of the configuration myself.

I have a Bean for the following:

  • AxonServerConfiguration

  • AxonServerConnectionManager

  • EventStore

  • beans for serializers

  • CommandBus

  • CommandGateway

  • Configuration

The configuration then sets up the event processing configuration, the event store, the command bus, the serialization settings, and the aggregate.
Finally, as the application is booted up, the configuration Bean is fetched and start() is called.

There’s some oddities to how the system is running, but what’s the most baffling to me is that the logging is complaining that the application is failing to connect to a localhost instance of the event store. I have an event store configured and running separately from the host of the application (whether testing locally or deployed), and if I take down that server, I start getting error messages for a failure to connect to the deployed server as well as a localhost server. What I can’t figure out is why the system is trying to connect to a local instance of axon server. Digging into the configuration & axon system reveals there’s only one channel and only one event store related to the configuration. The spring context only has the one configuration (and only one of each other bean). Every place I check has the proper URL for the axon server (not localhost), but the connector keeps complaining with an IOException.

Any ideas on why two connections are being booted up?
Here’s an example failure message:

Dec 16 17:21:52.223 [AxonServerConne] WA [AxonServerConnection.getChannel: 217] - Connecting to AxonServer node [localhost]:[8124] failed: UNAVAILABLE: io exception

Hi Jake,

while reading your message, I thought that it’s impossible for two connections to be started to different hosts. But then I noticed your list of beans.
Here’s what happens:
Your beans correctly set up connectivity to the AxonServer. Most likely, to the non-localhost instance that you expect.
But also this:
The Configuration bean (assuming you’re referring to the Axon Configuration class, and are using the DefaultConfigurer) will also set up defaults. As the Configurer is not aware of the beans you have defined, it will attempt to set up a connection to a locally installed AxonServer.

2 ways to work around this:

  • register each of the specific beans you have defined with the Configurer instance. This will force the Configuration to use these classes instead of the defaults.
  • use the SpringAxonAutoConfigurer bean, which attempts to do this automatically. This bean does much of what AutoConfiguration will also do, without depending on Spring Boot. Because of that, it’s also less flexible, so we still recommend Spring Boot Autoconfiguration over the SpringAxonAutoConfigurer. To use it, add an @Import(SpringAxonAutoConfigurer.ImportSelector.class) to one of your Spring Configuration beans.

Hope this helps.
Cheers,

Hey Allard,

Thanks for the speedy reply! I started trying to play around with the different suggestions you offered, but ran into a couple small problems. For additional clarity though, I’ll include the configuration bean itself as I tried to be very explicit in my setup of it:

`

@Bean
public org.axonframework.config.Configuration configuration(
   EventStore eventStore,
   CommandBus commandBus,
   JacksonSerializer jacksonSerializer,
   XStreamSerializer xStreamSerializer,
   CommandGateway commandGateway
)
{
   return DefaultConfigurer.defaultConfiguration()
      .eventProcessing(EventProcessingConfigurer::usingTrackingEventProcessors)
      .eventProcessing(eventProcessingConfigurer -> eventProcessingConfigurer
         .registerEventHandler(c -> new FooExternalEventListener(commandGateway, new FooHelper())))
      .configureEventStore(c -> eventStore)
      .configureCommandBus(c -> commandBus)
      .configureSerializer(c -> xStreamSerializer)
      .configureMessageSerializer(c -> xStreamSerializer)
      .configureEventSerializer(c -> jacksonSerializer)
      .configureAggregate(AggregateConfigurer.defaultConfiguration(FooAggregate.class)
         .configureRepository(c -> EventSourcingRepository.builder(FooAggregate.class)
            .eventStore(c.eventStore())
            .build()))
      .configureAggregate(AggregateConfigurer.defaultConfiguration(BarAggregate.class)
         .configureRepository(c -> EventSourcingRepository.builder(BarAggregate.class)
            .eventStore(c.eventStore())
            .build()))
      .buildConfiguration();
}

`

I then call:

`

ApplicationContextProvider.getBean(Configuration.class).start();

`
And I do so around the same time as I boot up the server.

If I do not call the start() method, it will not boot up the localhost connection but also won’t properly set up the aggregates/processors when trying to use the command gateway. If I use start() it sets up both the connection to the external server as well as the localhost one. Setting the aggregates’ event store to the one injected into the bean (and set as the default event store) yields the exact same result.

Honestly, I’ve had some challenges with figuring out the documentation for configuring without spring boot. Is there a page which has a clearer indicator of the general layout for configuring with Spring (ex. the minimum beans, if the configuration should be a configurer or a configuration when handed out, etc). The code snippets in the documentation for how to use the default configurer have been useful, but I’m still not sure if I’ve found the right spot to actually put said configurer/configuration.

Also, when using the @Import(SpringAxonAutoConfigurer.ImportSelector.class) annotation on my custom axon configuration class, I ran into the issue of not having an event processing configuration bean, but I still have yet to figure out how to actually produce that bean.

I wish I could use spring boot to auto-configure it all, because it would make my life so much easier, but sadly the technical limitations of the pre-existing application I’m injecting Axon into don’t allow for it.

I got the setup working without the additional server connection. Thanks again Allard.

I managed to connect the SpringAxonAutoConfigurer in my configuration class with all my beans. The main problem I came across was the EventProcessingConfiguration, as it wasn’t being generated by the auto configurer. I couldn’t find a way build a configuration other than instantiating an EventProcessingModule & using it as one. I’m not sure if I’m supposed to use an EventProcessingModule as a configuration & configurer or if there’s a builder for a configurer hiding somewhere and I missed it. I also removed my DefaultConfigurer, since it’s auto-pulled together now.

Hi Jake,

glad you got it working. Autoconfiguration is always a bit tricky when not using (Spring Boot) Auto Configuration ;-).
It’s fine to define your own EventProcessingModule bean. In this particular case, the module is both the Configurer as well as the Configuration implementation. Just beware that the two interfaces operate in a different time-frame: configurer is to define the components, Configuration is where the components are constructed (and should not be changed anymore).

Cheers,