Two eventhandler handle same event

i have event handler.

@Component
@ProcessingGroup("SampleProcessor")
class SampleEventHandler {

    constructor(){}

    @EventHandler
    fun handle(event: CreatedSampleEvent, @Autowired repository: SampleRepository) {...}
}
---
eventhandling:
    processors:
      "[SampleProcessor]":
        mode: tracking
        source: streamableKafkaMessageSource

if i use eventhandler once, it works fine.
but using eventhandler twice, it doesn’t work.

above code is using in first module.
and copy same code than using it also in second module.

i only can call first module’s eventhandler.
second module make error EventListener [SampleEventHandler] failed to handle event. Continuing processing with next listener .

how to fix it? is it possible to call eventhandler by single command?

Hi imnewone,

Could you please explain a bit what you want to achieve? From the logging it seems the problem is with the event handler method.

@gklijs
i want to call first eventhandler and second eventhandler both. this is my goal to achive.

but i can see only first eventhandler is called.

in first module, i have commandhandler that apply CreatedSampleEvent and first eventhandler that can handle CreatedSampleEvent.

in second module, i have second handler that can handle CreatedSampleEvent.

if i apply CreatedSampleEvent in first module, first and second eventhandler should be called.
still i don’t know why, it doesn’t work well.

here is my code.
in first module, i use below code.

@Component
@ProcessingGroup("SampleProcessor")
class SampleEventHandler {

    constructor(){}

    @EventHandler
    fun handle(event: CreatedSampleEvent, @Autowired repository: SampleRepository) {...}
}
axon:
  eventhandling:
      processors:
        "[SampleProcessor]":
          mode: tracking
          source: streamableKafkaMessageSource

in second module, i use below code.

@Component
@ProcessingGroup("SampleProcessor2")
class SampleEventHandler2 {

    constructor(){}

    @EventHandler
    fun handle(event: CreatedSampleEvent, @Autowired repository: SampleRepository) {...}
}
axon:
  eventhandling:
      processors:
        "[SampleProcessor2]":
          mode: tracking
          source: streamableKafkaMessageSource

first and second eventhandler handle same event(CreatedSampleEvent).

whole error in second module is this.

o.a.eventhandling.LoggingErrorHandler    : EventListener [SampleEventHandler2] failed to handle event [6cbfc779-c90b-42a2-b1a8-79d46defc5c8] (com.cqrs.axon.CreatedSampleEvent). Continuing processing with next listener

com.thoughtworks.xstream.io.StreamException: 
	at com.thoughtworks.xstream.io.xml.XppReader.pullNextEvent(XppReader.java:124) ~[xstream-1.4.18.jar:1.4.18]
	at com.thoughtworks.xstream.io.xml.AbstractPullReader.readRealEvent(AbstractPullReader.java:148) ~[xstream-1.4.18.jar:1.4.18]
	at com.thoughtworks.xstream.io.xml.AbstractPullReader.readEvent(AbstractPullReader.java:141) ~[xstream-1.4.18.jar:1.4.18]
	at com.thoughtworks.xstream.io.xml.AbstractPullReader.move(AbstractPullReader.java:118) ~[xstream-1.4.18.jar:1.4.18]
	at com.thoughtworks.xstream.io.xml.AbstractPullReader.moveDown(AbstractPullReader.java:103) ~[xstream-1.4.18.jar:1.4.18]
	at com.thoughtworks.xstream.io.xml.XppReader.<init>(XppReader.java:63) ~[xstream-1.4.18.jar:1.4.18]
	at com.thoughtworks.xstream.io.xml.AbstractXppDriver.createReader(AbstractXppDriver.java:54) ~[xstream-1.4.18.jar:1.4.18]
	at org.axonframework.serialization.xml.CompactDriver.createReader(CompactDriver.java:44) ~[axon-messaging-4.5.8.jar:4.5.8]
	at com.thoughtworks.xstream.XStream.fromXML(XStream.java:1261) ~[xstream-1.4.18.jar:1.4.18]
	at org.axonframework.serialization.xml.XStreamSerializer.doDeserialize(XStreamSerializer.java:141) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.serialization.AbstractXStreamSerializer.deserialize(AbstractXStreamSerializer.java:160) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.serialization.LazyDeserializingObject.getObject(LazyDeserializingObject.java:102) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.serialization.SerializedMessage.getPayload(SerializedMessage.java:77) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.messaging.MessageDecorator.getPayload(MessageDecorator.java:56) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.messaging.MessageDecorator.getPayload(MessageDecorator.java:56) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.messaging.annotation.PayloadParameterResolver.resolveParameterValue(PayloadParameterResolver.java:41) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.messaging.annotation.AnnotatedMessageHandlingMember.resolveParameterValues(AnnotatedMessageHandlingMember.java:168) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.messaging.annotation.AnnotatedMessageHandlingMember.handle(AnnotatedMessageHandlingMember.java:144) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.messaging.annotation.AnnotatedHandlerInspector$NoMoreInterceptors.handle(AnnotatedHandlerInspector.java:372) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.eventhandling.AnnotationEventHandlerAdapter.handle(AnnotationEventHandlerAdapter.java:94) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.eventhandling.SimpleEventHandlerInvoker.handle(SimpleEventHandlerInvoker.java:112) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.eventhandling.MultiEventHandlerInvoker.handle(MultiEventHandlerInvoker.java:89) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.eventhandling.AbstractEventProcessor.lambda$null$1(AbstractEventProcessor.java:165) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.messaging.DefaultInterceptorChain.proceed(DefaultInterceptorChain.java:57) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.messaging.interceptors.CorrelationDataInterceptor.handle(CorrelationDataInterceptor.java:65) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.messaging.DefaultInterceptorChain.proceed(DefaultInterceptorChain.java:55) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.eventhandling.TrackingEventProcessor.lambda$new$1(TrackingEventProcessor.java:185) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.messaging.DefaultInterceptorChain.proceed(DefaultInterceptorChain.java:55) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.eventhandling.AbstractEventProcessor.lambda$processInUnitOfWork$2(AbstractEventProcessor.java:173) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.messaging.unitofwork.BatchingUnitOfWork.executeWithResult(BatchingUnitOfWork.java:86) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.eventhandling.AbstractEventProcessor.processInUnitOfWork(AbstractEventProcessor.java:159) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.eventhandling.TrackingEventProcessor.processBatch(TrackingEventProcessor.java:462) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.eventhandling.TrackingEventProcessor.processingLoop(TrackingEventProcessor.java:294) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.eventhandling.TrackingEventProcessor$TrackingSegmentWorker.run(TrackingEventProcessor.java:1016) ~[axon-messaging-4.5.8.jar:4.5.8]
	at org.axonframework.eventhandling.TrackingEventProcessor$WorkerLauncher.run(TrackingEventProcessor.java:1162) ~[axon-messaging-4.5.8.jar:4.5.8]
	at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
Caused by: org.xmlpull.v1.XmlPullParserException: only whitespace content allowed before start tag and not { (position: START_DOCUMENT seen {... @1:2) 
	at io.github.xstream.mxparser.MXParser.parseProlog(MXParser.java:1528) ~[mxparser-1.2.2.jar:1.2.2]
	at io.github.xstream.mxparser.MXParser.nextImpl(MXParser.java:1406) ~[mxparser-1.2.2.jar:1.2.2]
	at io.github.xstream.mxparser.MXParser.next(MXParser.java:1104) ~[mxparser-1.2.2.jar:1.2.2]
	at com.thoughtworks.xstream.io.xml.XppReader.pullNextEvent(XppReader.java:109) ~[xstream-1.4.18.jar:1.4.18]
	... 35 common frames omitted

it works fine if i use only one module.
i mean if i make first and second event handler in single module, i can see that both event handler is called.

only if module splited as two, it doesn’t work.

after adding serializer, it works well!!

axon:
  serializer:
    general: jackson
    events: jackson
    messages: jackson

originally, in second module i have config code below.

@Configuration
class AxonConfiguration {


    @Bean
    fun tokenStore(client: MongoClient): MongoTokenStore {
        return MongoTokenStore.builder()
            .mongoTemplate(
                DefaultMongoTemplate.builder()
                    .mongoDatabase(client)
                    .build()
            )
            .serializer(JacksonSerializer.defaultSerializer())
            .build()
    }
}

i think because of not having custom serializer in second module, it didn’t work.

by the module, you mean another microservice?

@rsobies yes! two module means two instances.

The tokenstore should indeed always use the same serializer, good to see you solved it.

@imnewone
so it didn’t work because the second module didn’t have custom serializer and the first one did?
if you remove the custom serializer(jackson) from the first module, would it work without any additional configuration?

@rsobies
yes i use jackson serializer only in first module.
like this

   @Bean
    @Primary
    fun serializer(): Serializer {
        return JacksonSerializer
            .builder()
            .objectMapper(
                jacksonObjectMapper()
                    .registerModule(KotlinModule())
                    .registerModule(Jdk8Module())
                    .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
            )
            .build()
    }

second module doesn’t have any serializer like this so i added config than it works well.

well… if i remove custom serializer, it could use xstream as default serializer.
but i don’t know how to set this. below code is not working.

@Bean
@Primary
fun serializer(): Serializer {
    return XStreamSerializer.builder().build()
}

i don’t know xstreamSerializer setting. but if you set xstream well than it may be work fine without any additional cconfiguration.

For the latest releases you need something like:

    @Bean
    fun xStream(): XStream? {
        val xStream = XStream()
        xStream.allowTypesByWildcard(
            arrayOf(
                "tech.gklijs.api.**"
            )
        )
        return xStream
    }

Since XStream is using whitelisting instead of blacklisting in newer releases.

@gklijs thank you to let me know.
if i use xstream, i would use that config code!