Exception when calling a command with targetAggregateIdentifier

Hi,
I have a simple application that has 2 command/events for creating/updating integration record as well as Rest APIs for issuing those commands, as shown below:

The aggregate class:

`


@Aggregate
@NoArgsConstructor
public class Integration {
    @AggregateIdentifier
    private String id;

    private String partner;
    private String name;

    public String getId() {
        return this.id;
    }

    public String getName() {
        return name;
    }

    public String getPartner() {
        return this.partner;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPartner(String partner) {
        this.partner = partner;
    }

    @CommandHandler
    public Integration(CreateIntegrationCommand command){
        apply(new IntegrationCreatedEvent(command.getIntegrationId(), command.getIntegrationName(), command.getPartner()));
    }

    @EventSourcingHandler
    public void on(IntegrationCreatedEvent event){
        this.id = event.getIntegrationId();
        this.name = event.getIntegrationName();
        this.partner = event.getPartner();
    }

    @CommandHandler
    public void handleUpdate(UpdateIntegrationCommand command){
        apply(new IntegrationUpdatedEvent(command.getIntegrationId(), command.getIntegrationName()));
    }

    @EventSourcingHandler
    public void on(IntegrationUpdatedEvent event){
        this.name = event.getIntegrationName();
    }
}

`

CommandController:

`

@RestController
@RequestMapping(value = "/integrationCommands")
public class IntegrationCommandController {

    private final CommandGateway commandGateway;

    public IntegrationCommandController(CommandGateway commandGateway){
        this.commandGateway = commandGateway;
    }
    @PostMapping
    public CompletableFuture<String> CreateIntegration(@RequestBody Map<String, String> request){
        return commandGateway.send(new CreateIntegrationCommand(request.get("integrationId"),
                request.get("integrationName"), request.get("partner")));
    }

    @PutMapping
    public CompletableFuture<String> UpdateIntegration(@RequestBody Map<String, String> request){
        return commandGateway.send(new UpdateIntegrationCommand(request.get("integrationId"),
                request.get("integrationName")));
    }
}

`

kotlin file that has the command/event declaration:

`

package com.ultimatesoftware.integrationservices.api;

import org.axonframework.commandhandling.TargetAggregateIdentifier;

class CreateIntegrationCommand(@TargetAggregateIdentifier val integrationId: String, val integrationName: String, val partner: String)

class IntegrationCreatedEvent(val integrationId: String, val integrationName: String, val partner: String)

class UpdateIntegrationCommand(@TargetAggregateIdentifier val integrationId: String, val integrationName: String)
class IntegrationUpdatedEvent(integrationId: String, val integrationName: String)

`

Now When i call the Push API (create command), everything works fine, but when i issue a put command with an existing integration id “aggregate identifier”, I get the following exception:

`

2017-11-10 18:21:48.731 WARN 17144 — [nio-8080-exec-1] o.a.c.gateway.DefaultCommandGateway : Command ‘com.ultimatesoftware.integrationservices.api.UpdateIntegrationCommand’ resulted in org.axonframework.messaging.annotation.MessageHandlerInvocationException(Error handling event of type [class com.ultimatesoftware.integrationservices.api.IntegrationCreatedEvent] in aggregate)
2017-11-10 18:21:48.764 ERROR 17144 — [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] threw exception

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.ultimatesoftware.integrationservices.api.IntegrationCreatedEvent: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: [B@547f7e95; line: 1, column: 2]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:270) ~[jackson-databind-2.8.10.jar:2.8.10]
at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:1456) ~[jackson-databind-2.8.10.jar:2.8.10]
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1012) ~[jackson-databind-2.8.10.jar:2.8.10]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1206) ~[jackson-databind-2.8.10.jar:2.8.10]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:314) ~[jackson-databind-2.8.10.jar:2.8.10]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:148) ~[jackson-databind-2.8.10.jar:2.8.10]
at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1626) ~[jackson-databind-2.8.10.jar:2.8.10]
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1237) ~[jackson-databind-2.8.10.jar:2.8.10]
at org.axonframework.serialization.json.JacksonSerializer.deserialize(JacksonSerializer.java:202) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.serialization.LazyDeserializingObject.getObject(LazyDeserializingObject.java:104) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.serialization.SerializedMessage.getPayload(SerializedMessage.java:76) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.messaging.MessageDecorator.getPayload(MessageDecorator.java:60) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.messaging.annotation.PayloadParameterResolver.resolveParameterValue(PayloadParameterResolver.java:41) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.messaging.annotation.AnnotatedMessageHandlingMember.resolveParameterValues(AnnotatedMessageHandlingMember.java:151) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.messaging.annotation.AnnotatedMessageHandlingMember.handle(AnnotatedMessageHandlingMember.java:127) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.model.inspection.ModelInspector.lambda$doPublish$7(ModelInspector.java:192) ~[axon-core-3.0.6.jar:3.0.6]
at java.util.Optional.ifPresent(Optional.java:159) ~[na:1.8.0_131]
at org.axonframework.commandhandling.model.inspection.ModelInspector.doPublish(ModelInspector.java:190) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.model.inspection.ModelInspector.publish(ModelInspector.java:185) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.model.inspection.AnnotatedAggregate.publish(AnnotatedAggregate.java:200) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.eventsourcing.EventSourcedAggregate.publish(EventSourcedAggregate.java:158) ~[axon-core-3.0.6.jar:3.0.6]
at java.util.Iterator.forEachRemaining(Iterator.java:116) ~[na:1.8.0_131]
at org.axonframework.eventsourcing.EventSourcedAggregate.lambda$initializeState$1(EventSourcedAggregate.java:212) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.model.inspection.AnnotatedAggregate.lambda$execute$2(AnnotatedAggregate.java:174) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.model.AggregateLifecycle.lambda$execute$2(AggregateLifecycle.java:186) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.model.AggregateLifecycle.executeWithResult(AggregateLifecycle.java:167) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.model.AggregateLifecycle.execute(AggregateLifecycle.java:185) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.model.inspection.AnnotatedAggregate.execute(AnnotatedAggregate.java:174) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.eventsourcing.EventSourcedAggregate.initializeState(EventSourcedAggregate.java:209) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.eventsourcing.EventSourcingRepository.doLoadWithLock(EventSourcingRepository.java:182) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.eventsourcing.EventSourcingRepository.doLoadWithLock(EventSourcingRepository.java:44) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.model.LockingRepository.doLoad(LockingRepository.java:139) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.model.LockingRepository.doLoad(LockingRepository.java:48) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.model.AbstractRepository.lambda$load$7(AbstractRepository.java:111) ~[axon-core-3.0.6.jar:3.0.6]
at java.util.HashMap.computeIfAbsent(HashMap.java:1126) ~[na:1.8.0_131]
at org.axonframework.commandhandling.model.AbstractRepository.load(AbstractRepository.java:110) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.AggregateAnnotationCommandHandler$AggregateCommandHandler.handle(AggregateAnnotationCommandHandler.java:192) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.AggregateAnnotationCommandHandler$AggregateCommandHandler.handle(AggregateAnnotationCommandHandler.java:186) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.AggregateAnnotationCommandHandler.handle(AggregateAnnotationCommandHandler.java:148) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.AggregateAnnotationCommandHandler.handle(AggregateAnnotationCommandHandler.java:40) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.messaging.DefaultInterceptorChain.proceed(DefaultInterceptorChain.java:57) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.messaging.interceptors.CorrelationDataInterceptor.handle(CorrelationDataInterceptor.java:55) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.messaging.DefaultInterceptorChain.proceed(DefaultInterceptorChain.java:55) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.messaging.unitofwork.DefaultUnitOfWork.executeWithResult(DefaultUnitOfWork.java:69) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.SimpleCommandBus.doDispatch(SimpleCommandBus.java:143) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.SimpleCommandBus.doDispatch(SimpleCommandBus.java:116) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.SimpleCommandBus.dispatch(SimpleCommandBus.java:86) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.gateway.AbstractCommandGateway.send(AbstractCommandGateway.java:79) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.gateway.DefaultCommandGateway.send(DefaultCommandGateway.java:95) ~[axon-core-3.0.6.jar:3.0.6]
at org.axonframework.commandhandling.gateway.DefaultCommandGateway.send(DefaultCommandGateway.java:143) ~[axon-core-3.0.6.jar:3.0.6]
at com.ultimatesoftware.integrationservices.Commands.Web.IntegrationCommandController.UpdateIntegration(IntegrationCommandController.java:31) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_131]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_131]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_131]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:883) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:664) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.20.jar:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1457) [tomcat-embed-core-8.5.20.jar:8.5.20]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.20.jar:8.5.20]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.20.jar:8.5.20]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]

`

My understanding is that since I’m using @TargetAggreateIdentifier , Axon should be able to load the aggregate and do the update, right? I’m not sure why i’m getting this exception. Any suggestions?

Thanks,
Amr.

I believe I found the issue but i still can’t understand why.
it turned out that Axon needs a default constructor for IntegrationCreatedEvent:

`

class IntegrationCreatedEvent(val integrationId: String, val integrationName: String, val partner: String){
    constructor() : this("", "", "")
}

`

I’m still not sure why this event is being called when the UpdateIntegrationCommand is being called?

Hello,
Yeah, not sure why you need a default constructor. Maybe it’s something to do with Kotlin? Aside from that, the reason for the Create event is because of the event sourcing. Anytime you load an aggregate, all the past events are going to be replayed in order to give you its current state. Also, while I realize this is probably just a simple app to learn the basics, if you find that your API consists of nothing but CRUD events, then you might want to re-think things. Not automatically saying that an Update(d) command/event is a bad thing (because I actually have a use-case where it just makes sense), but the purpose of commands and events are to express intents. For example, if you have an UpdateBankAccount/BankAccountUpdated command/event, then it’s pretty vague. Was money withdrawn/deposited, etc…?

Hi Amr, Brian,

The issue here is that the configuration is using the Jackson serializer, and Jackson doesn’t deal well with Kotlin classes out of the box.

There is this add-on module for Jackson that will fix this: https://github.com/FasterXML/jackson-module-kotlin

Kind regards,

Thank you Frans & Brian for your help and input!