@RequestMapping("/register")
 public String register(
     @RequestParam(value = "productCode") String productCode,
     @AuthenticationPrincipal LoginUser user,
     Model model) {
   // Modelの情報を再取得してレジ画面を表示する
   Product product = productService.findStockProductByProductCode(productCode);
   Customer customer = customerService.findCustomerWithCreditByMail(user.getUsername());
   CashRegisterCustomerView customerView = createCustomerView(customer);
   model.addAttribute("product", product);
   model.addAttribute("customerView", customerView);
   return "register";
 }
 @RequestMapping("/detail")
 public String detail(@RequestParam(value = "productCode") String productCode, Model model) {
   Product product = productService.findStockProductByProductCode(productCode);
   // Cacheの取得を行う。cacheが存在しない場合はサービス経由でReviewを取得し、キャッシュに反映する。
   List<Review> reviews = reviewCache.get(productCode);
   if (reviews == null) {
     reviews = reviewService.findReviewByProductCode(productCode);
     // 結果が0件であった場合も空であった結果をCacheする.
     reviewCache.put(productCode, reviews);
   }
   model.addAttribute("product", product);
   model.addAttribute("reviews", createProductReviewView(reviews));
   return "detail";
 }
 @ExceptionHandler(OutOfStockException.class)
 public ModelAndView handleException(OutOfStockException exception, Locale locale) {
   Product outOfStockProduct = productService.findProductByProductCode(exception.getProductCode());
   ModelAndView mav = new ModelAndView("/detail");
   mav.addObject("hasErrorMessage", Boolean.TRUE);
   mav.addObject(
       "errorMessage",
       messageSource.getMessage(
           exception.getMessageCode().getCode(),
           new String[] {outOfStockProduct.getProductName()},
           locale));
   mav.addObject(outOfStockProduct);
   return mav;
 }