Null pointer exception in DefaultUnitOfWork

Any thoughts / hints? I’m getting the following when running “live” (as opposed to in a unit test)

java.lang.NullPointerException
at org.axonframework.unitofwork.DefaultUnitOfWork.publishEvents(DefaultUnitOfWork.java:270) ~[axon-core-2.4.5.jar:2.4.5]
at org.axonframework.unitofwork.DefaultUnitOfWork.doCommit(DefaultUnitOfWork.java:140) ~[axon-core-2.4.5.jar:2.4.5]
at org.axonframework.unitofwork.NestableUnitOfWork.commit(NestableUnitOfWork.java:59) ~[axon-core-2.4.5.jar:2.4.5]
at org.axonframework.commandhandling.SimpleCommandBus.doDispatch(SimpleCommandBus.java:137) ~[axon-core-2.4.5.jar:2.4.5]
at org.axonframework.commandhandling.SimpleCommandBus.doDispatch(SimpleCommandBus.java:103) [axon-core-2.4.5.jar:2.4.5]
at org.axonframework.commandhandling.SimpleCommandBus.dispatch(SimpleCommandBus.java:70) [axon-core-2.4.5.jar:2.4.5]
at com.ascentis.benefits.controller.EnrollmentController.enroll(EnrollmentController.java:77) [EnrollmentController.class:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_66]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_66]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_66]
at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_66]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) [spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) [spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:111) [spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:806) [spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:729) [spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) [spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) [spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) [spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) [spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]

The failing code is in DefaultUnitOfWork (line 270), and the issue is that the key returned by “getKey()” is null

entry.getKey().publish(messages);

entry = {HashMap$Node@14154} "null" -> " size = 1"
key = null
value = {ArrayList@14155} size = 1
0 = {GenericDomainEventMessage@14166} "GenericDomainEventMessage[EnrollEvent{planId='plan51', planEnrollmentId='7a6d2beb-116e-425f-b5c3-297dc51803ff', startDate='2016-01-01T00:00:00.000-08:00', endDate='2016-12-31T00:00:00.000-08:00', eventDate='2016-05-23T11:28:28.933-07:00'}]"

public class Enrollment extends AbstractAnnotatedAggregateRoot {
    @AggregateIdentifier
    EnrollmentId id;
    
    public void enroll(EnrollData data) {
        apply(new EnrollEvent(id, data));
    }    // this method is hit
    @EventSourcingHandler
    public void onEnroll(EnrollEvent event) {
        // update end date of prior enrollment?
        // use another aggregate?
        this.eventDate = event.getEventDate();
        // Map<String, PlanEnrollment> enrollments = enrollees.get(event.getPersonId());

        logger.info(event);
    }
}

Thanks, Tim Irwin

Looks like I wasn’t setting the eventBus in the repository. Might throw an assertion in registerAggregate or similar to alert if eventBus == null (with an appropriate message) rather than using a null key in a map.

EventSourcingRepository<Enrollment> repository =  new EventSourcingRepository<>(Enrollment.class, eventStore());
--> repository.setEventBus(eventBus);
return repository;

Hi Tim,

Glad you found it.
This was an unfortunate design decision that I didn’t want to change in minor versions because of API compatibility. Axon 3 will require all parameters to be set in the constructor, avoiding this type of issue.

Cheers,

Allard