/** * Create a SagaMethodMessageHandler for the given <code>methodHandler</code>. The * SagaMethodMessageHandler add information specific to the behavior of Sagas, such as the * association value and creation policy. * * @param methodHandler The handler for incoming events * @return a SagaMethodMessageHandler for the handler */ public static SagaMethodMessageHandler getInstance(MethodMessageHandler methodHandler) { Method handlerMethod = methodHandler.getMethod(); SagaEventHandler handlerAnnotation = handlerMethod.getAnnotation(SagaEventHandler.class); String associationPropertyName = handlerAnnotation.associationProperty(); Method associationProperty; try { associationProperty = methodHandler.getPayloadType().getMethod(methodForProperty(associationPropertyName)); } catch (NoSuchMethodException e) { throw new AxonConfigurationException( format( "SagaEventHandler %s.%s defines a property %s that is not " + "defined on the Event it declares to handle (%s)", methodHandler.getMethod().getDeclaringClass().getName(), methodHandler.getMethodName(), associationPropertyName, methodHandler.getPayloadType().getName()), e); } String associationKey = handlerAnnotation.keyName().isEmpty() ? associationPropertyName : handlerAnnotation.keyName(); StartSaga startAnnotation = handlerMethod.getAnnotation(StartSaga.class); SagaCreationPolicy sagaCreationPolicy; if (startAnnotation == null) { sagaCreationPolicy = SagaCreationPolicy.NONE; } else if (startAnnotation.forceNew()) { sagaCreationPolicy = SagaCreationPolicy.ALWAYS; } else { sagaCreationPolicy = SagaCreationPolicy.IF_NONE_FOUND; } return new SagaMethodMessageHandler( sagaCreationPolicy, methodHandler, associationKey, associationProperty); }
@PostConstruct @SuppressWarnings({"unchecked"}) @Override public synchronized void subscribe() { for (final MethodMessageHandler commandHandler : inspector.getHandlers()) { CommandHandler<Object> handler = new CommandHandler<Object>() { @Override public Object handle(CommandMessage<Object> command, UnitOfWork unitOfWork) throws Throwable { T aggregate = loadAggregate(command); try { return commandHandler.invoke(aggregate, command); } catch (InvocationTargetException e) { throw e.getCause(); } } }; commandBus.subscribe(commandHandler.getPayloadType(), handler); registeredCommandHandlers.put(commandHandler.getPayloadType(), handler); } for (final ConstructorCommandMessageHandler<T> handler : inspector.getConstructorHandlers()) { commandBus.subscribe( handler.getPayloadType(), new AnnotatedConstructorCommandHandler(handler)); } }
@Override public int compareTo(SagaMethodMessageHandler o) { if (this.handlerMethod == null && o.handlerMethod == null) { return 0; } else if (this.handlerMethod == null) { return -1; } else if (o.handlerMethod == null) { return 1; } return handlerMethod.compareTo(o.handlerMethod); }
@Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } SagaMethodMessageHandler that = (SagaMethodMessageHandler) o; return !(handlerMethod != null ? !handlerMethod.equals(that.handlerMethod) : that.handlerMethod != null); }
@Override public int hashCode() { return handlerMethod != null ? handlerMethod.hashCode() : 0; }
/** * Indicates whether this Handler is suitable for the given <code>message</code>. * * @param message The message to inspect * @return <code>true</code> if this handler can handle the message, otherwise <code>false</code>. */ public boolean matches(EventMessage message) { return handlerMethod != null && handlerMethod.matches(message); }
/** * Indicates whether the handler of the target event indicates an ending event handler (i.e. is * annotated with {@link EndSaga}). * * @param event The event to investigate the handler for * @return <code>true</code> if handling the given <code>event</code> should end the lifecycle of * the Saga, <code>false</code> otherwise. */ public boolean isEndingEvent(EventMessage event) { MethodMessageHandler handler = invoker.findHandlerMethod(event); return handler != null && handler.getMethod().isAnnotationPresent(EndSaga.class); }