@RequestMapping(value = "/register.html", method = RequestMethod.POST)
  public String registerCustomer(
      @Valid @ModelAttribute("customer") SecuredShopPersistableCustomer customer,
      BindingResult bindingResult,
      Model model,
      HttpServletRequest request,
      final Locale locale)
      throws Exception {
    MerchantStore merchantStore = (MerchantStore) request.getAttribute(Constants.MERCHANT_STORE);
    Language language = super.getLanguage(request);

    ReCaptchaImpl reCaptcha = new ReCaptchaImpl();
    reCaptcha.setPublicKey(coreConfiguration.getProperty(Constants.RECAPATCHA_PUBLIC_KEY));
    reCaptcha.setPrivateKey(coreConfiguration.getProperty(Constants.RECAPATCHA_PRIVATE_KEY));

    String userName = null;
    String password = null;

    model.addAttribute(
        "recapatcha_public_key", coreConfiguration.getProperty(Constants.RECAPATCHA_PUBLIC_KEY));

    if (StringUtils.isNotBlank(customer.getRecaptcha_challenge_field())
        && StringUtils.isNotBlank(customer.getRecaptcha_response_field())) {
      ReCaptchaResponse reCaptchaResponse =
          reCaptcha.checkAnswer(
              request.getRemoteAddr(),
              customer.getRecaptcha_challenge_field(),
              customer.getRecaptcha_response_field());
      if (!reCaptchaResponse.isValid()) {
        LOGGER.debug("Captcha response does not matched");
        FieldError error =
            new FieldError(
                "recaptcha_challenge_field",
                "recaptcha_challenge_field",
                messages.getMessage("validaion.recaptcha.not.matched", locale));
        bindingResult.addError(error);
      }
    }

    if (StringUtils.isNotBlank(customer.getUserName())) {
      if (customerFacade.checkIfUserExists(customer.getUserName(), merchantStore)) {
        LOGGER.debug(
            "Customer with username {} already exists for this store ", customer.getUserName());
        FieldError error =
            new FieldError(
                "userName",
                "userName",
                messages.getMessage("registration.username.already.exists", locale));
        bindingResult.addError(error);
      }
      userName = customer.getUserName();
    }

    if (StringUtils.isNotBlank(customer.getPassword())
        && StringUtils.isNotBlank(customer.getCheckPassword())) {
      if (!customer.getPassword().equals(customer.getCheckPassword())) {
        FieldError error =
            new FieldError(
                "password",
                "password",
                messages.getMessage("message.password.checkpassword.identical", locale));
        bindingResult.addError(error);
      }
      password = customer.getPassword();
    }

    if (bindingResult.hasErrors()) {
      LOGGER.debug(
          "found {} validation error while validating in customer registration ",
          bindingResult.getErrorCount());
      StringBuilder template =
          new StringBuilder()
              .append(ControllerConstants.Tiles.Customer.register)
              .append(".")
              .append(merchantStore.getStoreTemplate());
      return template.toString();
    }

    @SuppressWarnings("unused")
    CustomerEntity customerData = null;
    try {
      customerData = customerFacade.registerCustomer(customer, merchantStore, language);
    } catch (CustomerRegistrationException cre) {
      LOGGER.error("Error while registering customer.. ", cre);
      ObjectError error =
          new ObjectError("registration", messages.getMessage("registration.failed", locale));
      bindingResult.addError(error);
      StringBuilder template =
          new StringBuilder()
              .append(ControllerConstants.Tiles.Customer.register)
              .append(".")
              .append(merchantStore.getStoreTemplate());
      return template.toString();
    } catch (Exception e) {
      LOGGER.error("Error while registering customer.. ", e);
      ObjectError error =
          new ObjectError("registration", messages.getMessage("registration.failed", locale));
      bindingResult.addError(error);
      StringBuilder template =
          new StringBuilder()
              .append(ControllerConstants.Tiles.Customer.register)
              .append(".")
              .append(merchantStore.getStoreTemplate());
      return template.toString();
    }

    /** Send registration email */
    emailTemplatesUtils.sendRegistrationEmail(
        customer, merchantStore, locale, request.getContextPath());

    /** Login user */
    try {

      // refresh customer
      Customer c = customerFacade.getCustomerByUserName(customer.getUserName(), merchantStore);
      // authenticate
      customerFacade.authenticate(c, userName, password);
      super.setSessionAttribute(Constants.CUSTOMER, c, request);

      return "redirect:/shop/customer/dashboard.html";

    } catch (Exception e) {
      LOGGER.error("Cannot authenticate user ", e);
      ObjectError error =
          new ObjectError("registration", messages.getMessage("registration.failed", locale));
      bindingResult.addError(error);
    }

    StringBuilder template =
        new StringBuilder()
            .append(ControllerConstants.Tiles.Customer.register)
            .append(".")
            .append(merchantStore.getStoreTemplate());
    return template.toString();
  }
  @RequestMapping(
      value = {"/shop/store/{storeCode}/contact"},
      method = RequestMethod.POST)
  public @ResponseBody String sendEmail(
      @ModelAttribute(value = "contact") ContactForm contact,
      BindingResult bindingResult,
      HttpServletRequest request,
      HttpServletResponse response,
      Locale locale)
      throws Exception {

    AjaxResponse ajaxResponse = new AjaxResponse();

    MerchantStore store = (MerchantStore) request.getAttribute(Constants.MERCHANT_STORE);

    try {

      if (StringUtils.isBlank(contact.getCaptchaResponseField())) {
        FieldError error =
            new FieldError(
                "captchaResponseField",
                "captchaResponseField",
                messages.getMessage("NotEmpty.contact.captchaResponseField", locale));
        bindingResult.addError(error);
        ajaxResponse.setErrorString(bindingResult.getAllErrors().get(0).getDefaultMessage());
        ajaxResponse.setStatus(AjaxResponse.RESPONSE_STATUS_FAIURE);
        return ajaxResponse.toJSONString();
      }

      ReCaptchaImpl reCaptcha = new ReCaptchaImpl();
      reCaptcha.setPublicKey(coreConfiguration.getProperty(Constants.RECAPATCHA_PUBLIC_KEY));
      reCaptcha.setPrivateKey(coreConfiguration.getProperty(Constants.RECAPATCHA_PRIVATE_KEY));

      if (StringUtils.isNotBlank(contact.getCaptchaChallengeField())
          && StringUtils.isNotBlank(contact.getCaptchaResponseField())) {
        ReCaptchaResponse reCaptchaResponse =
            reCaptcha.checkAnswer(
                request.getRemoteAddr(),
                contact.getCaptchaChallengeField(),
                contact.getCaptchaResponseField());
        if (!reCaptchaResponse.isValid()) {
          LOGGER.debug("Captcha response does not matched");
          FieldError error =
              new FieldError(
                  "captchaChallengeField",
                  "captchaChallengeField",
                  messages.getMessage("validaion.recaptcha.not.matched", locale));
          bindingResult.addError(error);
        }
      }

      if (bindingResult.hasErrors()) {
        LOGGER.debug(
            "found {} validation error while validating in customer registration ",
            bindingResult.getErrorCount());
        ajaxResponse.setErrorString(bindingResult.getAllErrors().get(0).getDefaultMessage());
        ajaxResponse.setStatus(AjaxResponse.RESPONSE_STATUS_FAIURE);
        return ajaxResponse.toJSONString();
      }

      emailTemplatesUtils.sendContactEmail(
          contact,
          store,
          LocaleUtils.getLocale(store.getDefaultLanguage()),
          request.getContextPath());

      ajaxResponse.setStatus(AjaxResponse.RESPONSE_STATUS_SUCCESS);
    } catch (Exception e) {
      LOGGER.error("An error occured while trying to send an email", e);
      ajaxResponse.setStatus(AjaxResponse.RESPONSE_STATUS_FAIURE);
    }

    return ajaxResponse.toJSONString();
  }