hide1998
@hide1998

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

SpringBootで予約キャンセルの機能を実装での画面遷移がうまくいかない。

解決したいこと

SpringBootでキャンセルの機能を実装させたい。

発生している問題・エラー

No static resource reservations/restaurant/2/reservations/cancel.と出ておりコントローラーがみつからない。

該当するソースコード

package com.example.portfolio.controller;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.web.PageableDefault;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.example.portfolio.entity.Reservation;
import com.example.portfolio.entity.Restaurant;
import com.example.portfolio.entity.User;
import com.example.portfolio.form.ReservationInputForm;
import com.example.portfolio.form.ReservationRegisterForm;
import com.example.portfolio.repository.ReservationRepository;
import com.example.portfolio.repository.RestaurantRepository;
import com.example.portfolio.security.UserDetailsImpl;
import com.example.portfolio.service.ReservationService;
import com.example.portfolio.service.SendMailService;

@Controller
public class ReservationController {
	private final ReservationRepository reservationRepository;
	private final RestaurantRepository restaurantRepository;
	private final ReservationService reservationService;
	private final SendMailService sendMailService;
	
	public ReservationController(ReservationRepository reservationRepository, 
			RestaurantRepository restaurantRepository, 
			ReservationService reservationService,
			SendMailService sendMailService){
		this.reservationRepository = reservationRepository;
		this.restaurantRepository = restaurantRepository;
		this.reservationService = reservationService;
		this.sendMailService = sendMailService;
	}
<省略>

    @PostMapping("/restaurant/{id}/reservations/cancel")
	public String cancel(@PathVariable(name = "id") Integer id, RedirectAttributes redirectAttributes) {
		Reservation reservation = reservationRepository.getReferenceById(id);
		
		reservationRepository.delete(reservation);
		sendMailService.sendMailReservationCancel(reservation);
		
		redirectAttributes.addFlashAttribute("successMessage", "予約をキャンセルしました。");
		
		return "redirect:/reservations";
		
	}

}
 
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
	<head>
		<div th:replace="~{fragment :: meta}"></div>
		
		<div th:replace="~{fragment :: styles}"></div>
		
		<title>予約一覧</title>
	</head>
	<body>
		<div class="nagoyameshi-wrapper">
			<div th:replace="~{fragment :: header}"></div>
			<main>
				<div class="container nagoyameshi-container pb-5">
					<div class="row justify-content-center">
						<div class="col-xxl-9 col-xl-10 col-lg-11">
							<nav class="my-3" style="--bs-breadcrumb-divider: '>';" aria-label="breadcrumb">
								<ol class="breadcrumb">
									<li class="breadcrumb-item"><a th:href="@{/}">トップページ</a></li>
									<li class="breadcrumb-item active" aria-current="page">予約一覧</li>
								</ol>
							</nav>
							
							<h2 class="mb-3 text-center">予約一覧</h2>
							
							<div th:if="${successMessage}" class="alert alert-info">
								<span th:text="${successMessage}"></span>
							</div>
							
							<div th:if="${param.reserved}" class="alert alert-info">
								予約が完了しました。
							</div>
							
							<table class="table">
								<thead>
									<tr>
										<th scope="col">店舗名</th>
										<th scope="col">日時</th>
										<th scope="col">人数</th>
									</tr>
								</thead>
								<tbody>
									<tr th:each="reservation : ${reservationPage}">
										<td><a th:href="@{/restaurant/__${reservation.getRestaurant().getId()}__}" th:text="${reservation.getRestaurant().getName()}"></a></td>
										<td th:text="${reservation.getVisitingTime()}"></td>
										<td th:text="${reservation.getNumberOfPeople()}"></td>
										<td><a href="#" class="nagoyameshi-link-danger" data-bs-toggle="modal" th:data-bs-target="${'#deleteReservationModal' + reservation.getId()}">キャンセル</a></td>
										
										<div class="modal fade" th:id="${'deleteReservationModal' + reservation.getId()}" tabindex="-1" th:aria-labelledby="${'deleteRestaurantModalLabel' + reservation.getId()}">
											<div class="modal-dialog">
												<div class="modal-content">
													<div class="modal-header">
														<h5 class="modal-title" th:id="${'deleteReservationModal' + reservation.getId()}" th:text="${reservation.getRestaurant().getName() + 'の予約をキャンセルしますか?'}"></h5>
														<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="閉じる"></button>
													</div>
													<div class="modal-footer">
														<form method="post"th:action="@{/reservations/restaurant/__${reservation.getId()}__/reservations/cancel}">
															<button type="submit" class="btn nagoyameshi-btn-danger text-white shadow-sm">キャンセル</button>
														</form>
													</div>
												</div>
											</div>
										</div>
									</tr>
								</tbody>
							</table>
							
							<div th:if="${reservationPage.getTotalPages() >1}" class="d-flex justify-content-center">
								<nav aria-label="予約一覧ページ">
									<ul class="pagination">
										<li class="page-item">
											<span th:if="${reservationPage.isFirst()}" class="page-link disabled">前</span>
											<a th:unless="${reservationPage.isFirst()}" th:href="@{reservations(page = ${reservationPage.getNumber() - 1})}" class="page-link nagoyameshi-page-link">前</a>
										</li>
										<li th:each="i : ${#numbers.sequence(0, reservationPage.getTotalPages() - 1)}" class="page-item">
											<span th:if="${i == reservationPage.getNumber()}" class="page-link active nagoyameshi-active" th:text="${i + 1}"></span>
											<a th:unless="${i == reservationPage.getNumber()}" th:href="@{/reservations(page = ${i})}" class="page-link nagoyameshi-page-link" th:text="${i + 1}"></a>
										</li>
										<li class="page-item">
											<span th:if="${reservationPage.isLast()}" class="page-link disabled">次</span>
											<a th:unless="${reservationPage.isLast()}" th:href="@{/reservations(page = ${reservationPage.getNumber() + 1})}" class="page-link nagoyameshi-page-link">次</a>
										</li>
									</ul>
								</nav>
							</div>   
						</div>
					</div>
				</div>
			</main>
			<div th:replace="~{fragment :: footer}"></div>
		</div>
		<div th:replace="~{fragment :: scripts}"></div>
	</body>
</html>

自分で試したこと

ここに問題・エラーに対して試したことを記載してください。
似たコードを探してみた。

0

1Answer

No static resource reservations/restaurant/2/reservations/cancel.
和訳すると、「静的リソースが見つからない」です。つまり、HTML(Thymeleaf)ファイルがないということです。

@PostMappingと、th:actionのパスが一致していないのが原因だと思われます。

@{/reservations/restaurant/__${reservation.getId()}__/reservations/cancel} /restaurant/ {id} /reservations/cancel
0Like

Your answer might help someone💌