Package org.axonframework.sample.app.command

Source Code of org.axonframework.sample.app.command.ContactCommandHandler

/*
* Copyright (c) 2010. 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.sample.app.command;

import org.axonframework.commandhandling.annotation.CommandHandler;
import org.axonframework.repository.Repository;
import org.axonframework.sample.app.api.Address;
import org.axonframework.sample.app.api.ChangeContactNameCommand;
import org.axonframework.sample.app.api.ContactNameAlreadyTakenException;
import org.axonframework.sample.app.api.CreateContactCommand;
import org.axonframework.sample.app.api.RegisterAddressCommand;
import org.axonframework.sample.app.api.RemoveAddressCommand;
import org.axonframework.sample.app.api.RemoveContactCommand;
import org.axonframework.sample.app.query.ContactEntry;
import org.axonframework.sample.app.query.ContactRepository;
import org.axonframework.unitofwork.UnitOfWork;
import org.axonframework.unitofwork.UnitOfWorkListenerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import java.util.UUID;

/**
* <p>Command handler that can be used to create and update Contacts. It can also be used to register and remove
* addresses.</p>
* <p>The provided repository is used to store the changes.</p>
*
* @author Allard Buijze
*/
public class ContactCommandHandler {

    private final static Logger logger = LoggerFactory.getLogger(ContactCommandHandler.class);
    private Repository<Contact> repository;
    private ContactNameRepository contactNameRepository;
    private ContactRepository contactRepository;

    /**
     * Sets the contact domain event repository.
     *
     * @param repository the contact repository
     */
    public void setRepository(Repository<Contact> repository) {
        this.repository = repository;
    }

    /**
     * Sets the contact name repository used to maintain unique contact names
     *
     * @param contactNameRepository the contact name repository
     */
    public void setContactNameRepository(ContactNameRepository contactNameRepository) {
        this.contactNameRepository = contactNameRepository;
    }

    /**
     * Sets the query repository for contacts
     *
     * @param contactRepository for the query database
     */
    public void setContactRepository(ContactRepository contactRepository) {
        this.contactRepository = contactRepository;
    }

    /**
     * Creates a new contact based on the provided data. The provided user name is tested for uniqueness before
     * continuing.
     * <p/>
     * BEWARE
     * The mechanism to guarantee uniqueness is not a best practice for axon. This is a pretty expensive operation
     * especially when the number of contacts increases. It is better to make the client responsible for guaranteeing
     * unique contact names and make an explicit process to overcome the very rare situation where a duplicate contact
     * name is entered.
     *
     * @param command    CreateContactCommand object that contains the needed data to create a new contact
     * @param unitOfWork Unit of work for the current running thread
     */
    @CommandHandler
    public void handle(final CreateContactCommand command, UnitOfWork unitOfWork) {
        logger.debug("Received a command for a new contact with name : {}", command.getNewContactName());
        Assert.notNull(command.getNewContactName(), "Name may not be null");

        if (contactNameRepository.claimContactName(command.getNewContactName())) {
            registerUnitOfWorkListenerToCancelClaimingName(command.getNewContactName(), unitOfWork);
            String contactId = command.getContactId();
            if (contactId == null) {
                contactId = UUID.randomUUID().toString();
            }
            Contact contact = new Contact(contactId, command.getNewContactName());
            repository.add(contact);
        } else {
            throw new ContactNameAlreadyTakenException(command.getNewContactName());
        }
    }

    /**
     * Changes the provided data for the contact found based on the provided identifier
     * <p/>
     * An {@code AggregateNotFoundException} is thrown if the identifier does not represent a valid contact.
     *
     * @param command    ChangeContactNameCommand that contains the identifier and the data to be updated
     * @param unitOfWork Unit of work for the current running thread
     */
    @CommandHandler
    public void handle(final ChangeContactNameCommand command, UnitOfWork unitOfWork) {
        Assert.notNull(command.getContactId(), "ContactIdentifier may not be null");
        Assert.notNull(command.getContactNewName(), "Name may not be null");
        if (contactNameRepository.claimContactName(command.getContactNewName())) {
            registerUnitOfWorkListenerToCancelClaimingName(command.getContactNewName(), unitOfWork);
            Contact contact = repository.load(command.getContactId());
            contact.changeName(command.getContactNewName());

            cancelClaimedContactName(command.getContactId(), unitOfWork);
        } else {
            throw new ContactNameAlreadyTakenException(command.getContactNewName());
        }
    }

    /**
     * Removes the contact belonging to the contactId as provided by the command.
     *
     * @param command    RemoveContactCommand containing the identifier of the contact to be removed
     * @param unitOfWork Unit of work for the current running thread
     */
    @CommandHandler
    public void handle(RemoveContactCommand command, UnitOfWork unitOfWork) {
        Assert.notNull(command.getContactId(), "ContactIdentifier may not be null");
        Contact contact = repository.load(command.getContactId());
        contact.delete();

        cancelClaimedContactName(command.getContactId(), unitOfWork);
    }

    /**
     * Registers an address for the contact with the provided identifier. If the contact already has an address with the
     * provided type, this address will be updated. An {@code AggregateNotFoundException} is thrown if the provided
     * identifier does not exist.
     *
     * @param command RegisterAddressCommand that contains all required data
     */
    @CommandHandler
    public void handle(RegisterAddressCommand command) {
        Assert.notNull(command.getContactId(), "ContactIdentifier may not be null");
        Assert.notNull(command.getAddressType(), "AddressType may not be null");
        Address address = new Address(command.getStreetAndNumber(), command.getZipCode(), command.getCity());
        Contact contact = repository.load(command.getContactId());
        contact.registerAddress(command.getAddressType(), address);
    }

    /**
     * Removes the address with the specified type from the contact with the provided identifier. If the identifier
     * does not exist, an {@code AggregateNotFoundException} is thrown. If the contact does not have an address with
     * specified type nothing happens.
     *
     * @param command RemoveAddressCommand that contains all required data to remove an address from a contact
     */
    @CommandHandler
    public void handle(RemoveAddressCommand command) {
        Assert.notNull(command.getContactId(), "ContactIdentifier may not be null");
        Assert.notNull(command.getAddressType(), "AddressType may not be null");
        Contact contact = repository.load(command.getContactId());
        contact.removeAddress(command.getAddressType());
    }

    private void cancelClaimedContactName(String contactIdentifier, UnitOfWork unitOfWork) {
        final ContactEntry contactEntry = contactRepository.loadContactDetails(contactIdentifier);
        unitOfWork.registerListener(new UnitOfWorkListenerAdapter() {
            @Override
            public void afterCommit(UnitOfWork uow) {
                logger.debug("About to cancel the name {}", contactEntry.getName());
                contactNameRepository.cancelContactName(contactEntry.getName());
            }
        });
    }

    private void registerUnitOfWorkListenerToCancelClaimingName(final String name, UnitOfWork unitOfWork) {
        unitOfWork.registerListener(new UnitOfWorkListenerAdapter() {
            @Override
            public void onRollback(UnitOfWork uow, Throwable failureCause) {
                contactNameRepository.cancelContactName(name);
            }
        });
    }
}
TOP

Related Classes of org.axonframework.sample.app.command.ContactCommandHandler

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.