'Method contains does not work in <form:option>
I have a project that represents Library. On edit page of book, I want that co-authors will be selected, if this book has these authors. For example, like in the screenshots: booklistpage, editbookpage
I used this code to do that
<tr>
<td>Co-authors</td>
<td>
<form:select class="form-select" path="authorsSet" multiple="true">
<c:forEach items="${authors}" var="author">
<c:set var="authorName" value="${author.name} ${author.surname}"/>
<form:option value="${author.authorId}" label="${authorName}" selected="${book.authorSet.contains(author)? 'selected' : '' }"/>
</c:forEach>
</form:select></td>
</tr>
But it doesn't work. I overrode method .equals(), because I thought that problem may happen there. It also didn't help. There is my model and controller classes
BookController.class
package com.library.controller;
import com.library.AuthorEditor;
import com.library.model.Author;
import com.library.model.Book;
import com.library.service.AuthorService;
import com.library.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Set;
@Controller
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService;
@Autowired
private AuthorService authorService;
@Autowired
private AuthorEditor authorEditor;
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Author.class, this.authorEditor);
}
@GetMapping
public String allBooks(Model model) {
model.addAttribute("books", bookService.findAll());
return "book_list";
}
@GetMapping("/add")
public String showForm(Model model) {
Book book = new Book();
model.addAttribute("book", book);
model.addAttribute("authors", authorService.findAll());
return "book_add";
}
@PostMapping("/add")
public String addBook(@Valid @ModelAttribute Book book) {
bookService.addBook(book);
return "redirect:/books";
}
@GetMapping("/{id}")
public String getBook(Model model, @PathVariable Long id) {
Book book = bookService.findBookById(id);
model.addAttribute("book", book);
model.addAttribute("authors", book.getAuthorSet());
return "book_details";
}
@GetMapping("delete/{id}")
public String deleteBook(@PathVariable Long id) {
Book book = bookService.findBookById(id);
bookService.deleteBook(book);
return "redirect:/books";
}
@RequestMapping("/edit/{id}")
public String editBook(@PathVariable("id") long id, Model model){
model.addAttribute("book", this.bookService.findBookById(id));
model.addAttribute("title", this.bookService.findBookById(id).getTitle());
model.addAttribute("mainAuthor", this.bookService.findBookById(id).getMainAuthor());
//all authors
model.addAttribute("authors", authorService.findAll());
//all authors of book
model.addAttribute("authorsSet", bookService.findBookById(id).getAuthorSet());
model.addAttribute("amountOfCopies", bookService.findBookById(id).getAmountOfCopies());
return "book_edit";
}
@PostMapping("/edit/{id}")
public String editBook(@PathVariable("id") long id, @RequestParam String title, @RequestParam Integer amountOfCopies, @RequestParam Author mainAuthor, @RequestParam(required = false)Set<Author> authorsSet) {
Book book = this.bookService.findBookById(id);
book.setTitle(title);
book.setAmountOfCopies(amountOfCopies);
book.setMainAuthor(mainAuthor);
book.setAuthorSet(authorsSet);
this.bookService.updateBook(book);
return "redirect:/books";
}
}
Book.class
package com.library.model;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotEmpty;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "books")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "book_id")
private Long bookId;
@Column(name = "title", nullable = false)
@NotEmpty(message = "Please, enter tittle of the book")
private String title;
@Column(name = "amount_of_copies", nullable = false)
private Integer amountOfCopies;
@ManyToOne
@JoinColumn(name = "main_author")
private Author mainAuthor;
@ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST}, fetch = FetchType.EAGER)
@OnDelete(action = OnDeleteAction.NO_ACTION)
@JoinTable(
name = "books_authors",
joinColumns = {@JoinColumn(name = "book_id")},
inverseJoinColumns = {@JoinColumn(name = "author_id")}
)
Set<Author> authorSet = new HashSet<>();
public Set<Author> getAuthorsSet() {
return authorSet;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return Objects.equals(bookId, book.bookId);
}
}
Author.class
package com.library.model;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import java.util.HashSet;
import java.util.Set;
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "authors")
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "author_id")
private long authorId;
@Column(name = "first_name", nullable = false)
String name;
@Column(name = "last_name", nullable = false)
String surname;
@ManyToMany(mappedBy = "authorSet", cascade = CascadeType.PERSIST)
private Set<Book> bookSet = new HashSet<>();
}
book_edit.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<title>Book</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
</head>
<body>
<div class="container">
<h1>Edit book information</h1>
<table class="table table-borderless">
<form:form method="post" modelAttribute="book">
<tr>
<td>Title</td>
<td><form:input path="title" value="${book.title}" class="form-control"/></td>
</tr>
<tr>
<td>Main author</td>
<td>
<form:select class="form-select" path="mainAuthor">
<c:forEach items="${authors}" var="author">
<c:set var="authorName" value="${author.name} ${author.surname}"/>
<form:option value="${author.authorId}" label="${authorName}" selected="${author.authorId == book.mainAuthor.authorId? 'selected' : '' }"/>
</c:forEach>
</form:select></td>
</tr>
<tr>
<td>Co-authors</td>
<td>
<%--FIXME selected authors is necessary--%>
<form:select class="form-select" path="authorsSet" multiple="true">
<c:forEach items="${authors}" var="author">
<c:set var="authorName" value="${author.name} ${author.surname}"/>
<form:option value="${author.authorId}" label="${authorName}" selected="${book.authorSet.contains(author)? 'selected' : '' }"/>
</c:forEach>
</form:select></td>
</tr>
<tr>
<td>Amount of copies</td>
<td><form:input path="amountOfCopies" class="form-control" value="${book.amountOfCopies}"/>
</td>
</tr>
<tr>
<td>
<button class="btn btn-outline-dark" type="submit">Update</button>
</td>
</tr>
</form:form>
</table>
<a href="/library/books">Back to List</a><br>
<a href="/library">Home</a>
</div>
</body>
</html>
Could you, please, help me to find the problem.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
