org.axonframework.examples.addressbook.web.ContactsController.java Source code

Java tutorial

Introduction

Here is the source code for org.axonframework.examples.addressbook.web.ContactsController.java

Source

/*
 * 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.examples.addressbook.web;

import org.axonframework.commandhandling.CommandBus;
import org.axonframework.commandhandling.GenericCommandMessage;
import org.axonframework.sample.app.api.AddressType;
import org.axonframework.sample.app.api.ChangeContactNameCommand;
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.command.ContactNameRepository;
import org.axonframework.sample.app.query.AddressEntry;
import org.axonframework.sample.app.query.ContactEntry;
import org.axonframework.sample.app.query.ContactRepository;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.List;
import javax.validation.Valid;

/**
 * @author Jettro Coenradie
 */
@Controller
@RequestMapping(value = "/contacts")
public class ContactsController {
    //    private final static Logger logger = LoggerFactory.getLogger(ContactsController.class);

    @Autowired
    private ContactRepository repository;

    @Autowired
    private ContactNameRepository contactNameRepository;

    @Autowired
    private CommandBus commandBus;

    @RequestMapping(method = RequestMethod.GET)
    public String list(Model model) {
        model.addAttribute("contacts", repository.findAllContacts());
        return "contacts/list";
    }

    @RequestMapping(value = "{identifier}", method = RequestMethod.GET)
    public String details(@PathVariable String identifier, Model model) {
        List<AddressEntry> addressesForContact = repository.findAllAddressesForContact(identifier);
        String name;
        if (addressesForContact.size() > 0) {
            name = addressesForContact.get(0).getName();
        } else {
            name = repository.loadContactDetails(identifier).getName();
        }
        model.addAttribute("addresses", addressesForContact);
        model.addAttribute("identifier", identifier);
        model.addAttribute("name", name);
        return "contacts/details";
    }

    @RequestMapping(value = "{identifier}/edit", method = RequestMethod.GET)
    public String formEdit(@PathVariable String identifier, Model model) {
        ContactEntry contactEntry = repository.loadContactDetails(identifier);
        model.addAttribute("contact", contactEntry);
        return "contacts/edit";
    }

    @RequestMapping(value = "{identifier}/edit", method = RequestMethod.POST)
    public String formEditSubmit(@ModelAttribute("contact") @Valid ContactEntry contact,
            BindingResult bindingResult) {
        // beware, we cannot support other updates since that would always give an error when the name is not changed
        if (contactHasErrors(contact, bindingResult)) {
            return "contacts/edit";
        }

        ChangeContactNameCommand command = new ChangeContactNameCommand();
        command.setContactNewName(contact.getName());
        command.setContactId(contact.getIdentifier());

        commandBus.dispatch(new GenericCommandMessage<Object>(command));

        return "contacts/edit";

    }

    @RequestMapping(value = "new", method = RequestMethod.GET)
    public String formNew(Model model) {
        ContactEntry attributeValue = new ContactEntry();
        model.addAttribute("contact", attributeValue);
        return "contacts/new";
    }

    /**
     * If we submit a new contact, we want immediate feedback if the contact could be added. If it could not be added
     * we want an error. Therefore we use the Future callback mechanism as provide by Axon.
     *
     * @param contact       ContactEntry object that contains the entered data
     * @param bindingResult BindingResult containing information about the binding of the form data to the ContactEntry
     * @return String representing the name of the view to present.
     */
    @RequestMapping(value = "new", method = RequestMethod.POST)
    public String formNewSubmit(@ModelAttribute("contact") @Valid ContactEntry contact,
            BindingResult bindingResult) {
        if (contactHasErrors(contact, bindingResult)) {
            return "contacts/new";
        }

        CreateContactCommand command = new CreateContactCommand();
        command.setNewContactName(contact.getName());

        commandBus.dispatch(new GenericCommandMessage<Object>(command));

        return "redirect:/contacts";
    }

    @RequestMapping(value = "{identifier}/delete", method = RequestMethod.GET)
    public String formDelete(@PathVariable String identifier, Model model) {
        ContactEntry contactEntry = repository.loadContactDetails(identifier);
        model.addAttribute("contact", contactEntry);
        return "contacts/delete";
    }

    @RequestMapping(value = "{identifier}/delete", method = RequestMethod.POST)
    public String formDelete(@ModelAttribute("contact") ContactEntry contact, BindingResult bindingResult) {
        if (!bindingResult.hasErrors()) {
            RemoveContactCommand command = new RemoveContactCommand();
            command.setContactId(contact.getIdentifier());
            commandBus.dispatch(new GenericCommandMessage<Object>(command));

            return "redirect:/contacts";
        }
        return "contacts/delete";

    }

    @RequestMapping(value = "{identifier}/address/new", method = RequestMethod.GET)
    public String formNewAddress(@PathVariable String identifier, Model model) {
        ContactEntry contactEntry = repository.loadContactDetails(identifier);
        AddressEntry addressEntry = new AddressEntry();
        addressEntry.setIdentifier(contactEntry.getIdentifier());
        addressEntry.setName(contactEntry.getName());
        model.addAttribute("address", addressEntry);
        return "contacts/address";
    }

    @RequestMapping(value = "{identifier}/address/new", method = RequestMethod.POST)
    public String formNewAddressSubmit(@ModelAttribute("address") @Valid AddressEntry address,
            BindingResult bindingResult) {
        if (!bindingResult.hasErrors()) {
            RegisterAddressCommand command = new RegisterAddressCommand();
            command.setAddressType(address.getAddressType());
            command.setCity(address.getCity());
            command.setContactId(address.getIdentifier());
            command.setStreetAndNumber(address.getStreetAndNumber());
            command.setZipCode(address.getZipCode());
            commandBus.dispatch(new GenericCommandMessage<Object>(command));

            return "redirect:/contacts/" + address.getIdentifier();
        }
        return "contacts/address";
    }

    @RequestMapping(value = "{identifier}/address/delete/{addressType}", method = RequestMethod.GET)
    public String formDeleteAddress(@PathVariable String identifier, @PathVariable AddressType addressType,
            Model model) {
        ContactEntry contactEntry = repository.loadContactDetails(identifier);
        AddressEntry addressEntry = new AddressEntry();
        addressEntry.setIdentifier(contactEntry.getIdentifier());
        addressEntry.setName(contactEntry.getName());
        addressEntry.setAddressType(addressType);
        model.addAttribute("address", addressEntry);
        return "contacts/removeAddress";
    }

    @RequestMapping(value = "{identifier}/address/delete/{addressType}", method = RequestMethod.POST)
    public String formDeleteAddressSubmit(@ModelAttribute("address") AddressEntry address,
            BindingResult bindingResult) {
        if (!bindingResult.hasErrors()) {
            RemoveAddressCommand command = new RemoveAddressCommand();
            command.setContactId(address.getIdentifier());
            command.setAddressType(address.getAddressType());
            commandBus.dispatch(new GenericCommandMessage<Object>(command));

            return "redirect:/contacts/" + address.getIdentifier();
        }
        return "contacts/removeAddress";
    }

    /**
     * Checks if the entered data for a contact is valid and if the provided contact has not yet been taken.
     *
     * @param contact       Contact to validate
     * @param bindingResult BindingResult that can contain error and can be used to store additional errors
     * @return true if the contact has errors, false otherwise
     */
    private boolean contactHasErrors(ContactEntry contact, BindingResult bindingResult) {
        if (bindingResult.hasErrors() || !contactNameRepository.vacantContactName(contact.getName())) {
            ObjectError error = new FieldError("contact", "name",
                    "The provided name \'" + contact.getName() + "\' already exists");
            bindingResult.addError(error);
            return true;
        }
        return false;
    }
}