Package org.axonframework.commandhandling.annotation

Source Code of org.axonframework.commandhandling.annotation.AnnotationCommandHandlerAdapter

/*
* Copyright (c) 2010-2014. Axon Framework
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.axonframework.commandhandling.annotation;

import org.axonframework.commandhandling.CommandBus;
import org.axonframework.commandhandling.CommandMessage;
import org.axonframework.commandhandling.NoHandlerForCommandException;
import org.axonframework.common.Assert;
import org.axonframework.common.Subscribable;
import org.axonframework.common.annotation.ClasspathParameterResolverFactory;
import org.axonframework.common.annotation.MethodMessageHandler;
import org.axonframework.common.annotation.MethodMessageHandlerInspector;
import org.axonframework.common.annotation.ParameterResolverFactory;
import org.axonframework.unitofwork.UnitOfWork;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
* Adapter that turns any {@link CommandHandler @CommandHandler} annotated bean into a {@link
* org.axonframework.commandhandling.CommandHandler CommandHandler} implementation. Each annotated method is subscribed
* as a CommandHandler at the {@link CommandBus} for the command type specified by the parameter of that method.
*
* @author Allard Buijze
* @see CommandHandler
* @since 0.5
*/
public class AnnotationCommandHandlerAdapter
        implements org.axonframework.commandhandling.CommandHandler<Object>, Subscribable {

    private final CommandBus commandBus;
    private final Map<String, MethodMessageHandler> handlers = new HashMap<String, MethodMessageHandler>();
    private final Object target;
    private final ParameterResolverFactory parameterResolverFactory;

    /**
     * Subscribe the annotated command handler to the given command bus.
     *
     * @param annotatedCommandHandler The annotated command handler that is to be subscribed to the command bus
     * @param commandBus              The command bus that gets the handler's subscription
     * @return the Adapter created for the command handler target. Can be used to unsubscribe.
     */
    public static AnnotationCommandHandlerAdapter subscribe(Object annotatedCommandHandler, CommandBus commandBus) {
        AnnotationCommandHandlerAdapter adapter = new AnnotationCommandHandlerAdapter(annotatedCommandHandler);
        for (String cmd : adapter.supportedCommands()) {
            commandBus.subscribe(cmd, adapter);
        }
        return adapter;
    }

    /**
     * Subscribe the given <code>annotationCommandHandler</code> to the given <code>commandBus</code>. The
     * command handler will be subscribed for each of the supported commands.
     *
     * @param annotationCommandHandler The fully configured AnnotationCommandHandlerAdapter instance to subscribe
     * @param commandBus               The command bus instance to subscribe to
     */
    public static void subscribe(AnnotationCommandHandlerAdapter annotationCommandHandler,
                                 CommandBus commandBus) {
        for (String supportedCommand : annotationCommandHandler.supportedCommands()) {
            commandBus.subscribe(supportedCommand, annotationCommandHandler);
        }
    }

    /**
     * Initialize the command handler adapter for the given <code>target</code> which is to be subscribed with the
     * given <code>commandBus</code>.
     * <p/>
     * Note that you need to call {@link #subscribe()} to actually subscribe the command handlers to the command bus.
     *
     * @param target     The object containing the @CommandHandler annotated methods
     * @param commandBus The command bus to which the handlers must be subscribed
     * @deprecated Use {@link #AnnotationCommandHandlerAdapter(Object)} and subscribe the handler to the command bus
     * using {@link org.axonframework.commandhandling.CommandBus#subscribe(String,
     * org.axonframework.commandhandling.CommandHandler)}.
     */
    @Deprecated
    public AnnotationCommandHandlerAdapter(Object target, CommandBus commandBus) {
        Assert.notNull(target, "target may not be null");
        this.parameterResolverFactory = ClasspathParameterResolverFactory.forClass(target.getClass());
        MethodMessageHandlerInspector inspector = MethodMessageHandlerInspector.getInstance(target.getClass(),
                                                                                            CommandHandler.class,
                                                                                            parameterResolverFactory,
                                                                                            true);
        for (MethodMessageHandler handler : inspector.getHandlers()) {
            String commandName = CommandMessageHandlerUtils.resolveAcceptedCommandName(handler);
            handlers.put(commandName, handler);
        }
        this.target = target;
        this.commandBus = commandBus;
    }

    /**
     * Wraps the given <code>annotatedCommandHandler</code>, allowing it to be subscribed to a Command Bus.
     *
     * @param annotatedCommandHandler The object containing the @CommandHandler annotated methods
     */
    public AnnotationCommandHandlerAdapter(Object annotatedCommandHandler) {
        this(annotatedCommandHandler, ClasspathParameterResolverFactory.forClass(annotatedCommandHandler.getClass()));
    }

    /**
     * Wraps the given <code>annotatedCommandHandler</code>, allowing it to be subscribed to a Command Bus.
     *
     * @param annotatedCommandHandler  The object containing the @CommandHandler annotated methods
     * @param parameterResolverFactory The strategy for resolving handler method parameter values
     */
    public AnnotationCommandHandlerAdapter(Object annotatedCommandHandler,
                                           ParameterResolverFactory parameterResolverFactory) {
        Assert.notNull(annotatedCommandHandler, "annotatedCommandHandler may not be null");
        MethodMessageHandlerInspector inspector = MethodMessageHandlerInspector.getInstance(annotatedCommandHandler
                                                                                                    .getClass(),
                                                                                            CommandHandler.class,
                                                                                            parameterResolverFactory,
                                                                                            true);
        for (MethodMessageHandler handler : inspector.getHandlers()) {
            String commandName = CommandMessageHandlerUtils.resolveAcceptedCommandName(handler);
            handlers.put(commandName, handler);
        }
        this.parameterResolverFactory = parameterResolverFactory;
        this.target = annotatedCommandHandler;
        this.commandBus = null;
    }

    /**
     * Invokes the @CommandHandler annotated method that accepts the given <code>command</code>.
     *
     * @param command    The command to handle
     * @param unitOfWork The UnitOfWork the command is processed in
     * @return the result of the command handling. Is <code>null</code> when the annotated handler has a
     * <code>void</code> return value.
     *
     * @throws NoHandlerForCommandException when no handler is found for given <code>command</code>.
     * @throws Throwable any exception occurring while handling the command
     */
    @Override
    public Object handle(CommandMessage<Object> command, UnitOfWork unitOfWork) throws Throwable {
        try {
            final MethodMessageHandler handler = handlers.get(command.getCommandName());
            if (handler == null) {
                throw new NoHandlerForCommandException("No handler found for command " + command.getCommandName());
            }
            if (unitOfWork != null) {
                unitOfWork.attachResource(ParameterResolverFactory.class.getName(), parameterResolverFactory);
            }
            return handler.invoke(target, command);
        } catch (InvocationTargetException e) {
            throw e.getCause();
        }
    }

    /**
     * Subscribe the command handlers to the command bus assigned during the initialization. A subscription is made
     * with the command bus for each accepted type of command.
     *
     * @deprecated Instead, subscribe this instance using {@link CommandBus#subscribe(String,
     * org.axonframework.commandhandling.CommandHandler)}, using {@link #supportedCommands()} to retrieve
     * the commands the annotated handler supports.
     */
    @Override
    @PostConstruct
    @Deprecated
    public void subscribe() {
        if (commandBus != null) {
            for (String acceptedCommand : handlers.keySet()) {
                commandBus.subscribe(acceptedCommand, this);
            }
        }
    }

    /**
     * Unsubscribe the command handlers from the command bus assigned during the initialization.
     *
     * @deprecated Instead, subscribe this instance using {@link CommandBus#subscribe(String,
     * org.axonframework.commandhandling.CommandHandler)}, using {@link #supportedCommands()} to retrieve
     * the commands the annotated handler supports.
     */
    @Override
    @PreDestroy
    @Deprecated
    public void unsubscribe() {
        if (commandBus != null) {
            for (String acceptedCommand : handlers.keySet()) {
                commandBus.unsubscribe(acceptedCommand, this);
            }
        }
    }

    /**
     * Returns the set of commands supported by the annotated command handler managed by this adapter.
     *
     * @return the set of commands supported by the annotated command handler
     */
    public Set<String> supportedCommands() {
        return handlers.keySet();
    }
}
TOP

Related Classes of org.axonframework.commandhandling.annotation.AnnotationCommandHandlerAdapter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.