Thymeleaf does not see reference from Controller - java

I'm trying to show all Customers from my local database(PostgreSQL) on the html page using Thymeleaf. My project is using Spring Boot.
Connection and getting data from database is not the point of this question(or is it?). The point is that thymeleaf does not see model that i passed through controller.
homePage.html
!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Opera</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'Opera home page'" />
<ul th:each="customer : ${customers}">
<li>
<span th:text="${customers.getFirstName}">Name</span>
<span th:text="${customers.getLastName}">Surname</span>
<span th:text="${customers.getPhone}">Phone</span>
<span th:text="${customers.getEmail}">e-mail</span>
</li>
</ul>
</body>
</html>
HomePageController.java
#Controller
#RequestMapping("/")
public class HomePageController {
private CustomerRepository customerRepository;
#Autowired
public HomePageController(CustomerRepository customerRepository){
this.customerRepository = customerRepository;
}
#RequestMapping(method = RequestMethod.GET)
public String homePage(Model model) {
List<Customer> customers = Lists.newArrayList(customerRepository.findAll());
model.addAttribute("customers", customers);
return "homePage";
}
}
CustomerRepository.java
#Repository
public interface CustomerRepository extends CrudRepository<Customer, Long> {
}
Customer.java
#Entity
#Getter #Setter
public class Customer {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
#NotNull private String firstName;
#NotNull private String lastName;
#NotNull private String phoneNumber;
#NotNull private String email;
protected Customer(){}
public Customer(Long id, String firstName, String lastName, String phoneNumber, String email){
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.phoneNumber = phoneNumber;
this.email = email;
}
#Override
public String toString(){
return String.format(
"Customer[id=%d, firstName='%s', lastName='%s', phoneNumber='%s', emailr='%s']",this.getId(),
firstName, lastName, phoneNumber, email);
}
}
Screenshot from html file showing problem:
screen
Edit: some english corrections :(

Dont use getter in the template. Do like this:
<span th:text="${customer.firstName}">Name</span>
Sorry you also have to remove the s

Related

How can I use two seperate Forms using spring and thymeleaf?

I am trying to pass in every form different objects and to different entities.
It is actually works, I can see the new added values(rows) in my database, but still I keep getting the same Exception by submitting both forms separately.
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'post' available as request attribute
and
rg.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "/addPost" - line 11, col 24)
my Controller
import com.example.blog.domain.Category;
import com.example.blog.domain.Post;
import com.example.blog.service.CategoryService;
import com.example.blog.service.PostService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
#Controller
#RequestMapping("edit")
public class EditController {
private final PostService postService;
private final CategoryService categoryService;
// At the same time, I can use #Autowired
public EditController(PostService postService , CategoryService categoryService) {
this.categoryService = categoryService;
this.postService = postService;
}
//(1)
#GetMapping("/addPost")
public String showAddPost(Model model) {
model.addAttribute("post", new Post());
model.addAttribute("category" , new Category());
return "/addPost";
}
//Mapping is coming from the view page(addPost.html).
//The name of the action must be equal
#PostMapping(value = "/upload")
public String dataPost(#ModelAttribute Post post, #RequestParam(value = "action", required = true) String action){
if (action.equals("AddPost")){
postService.addPost(post);
}
return "/addPost";
}
//default : show all posts
//and shows all categories
#GetMapping
public String showAllPosts(Model model){
model.addAttribute("posts",postService.getAllPosts());
model.addAttribute("categories" , categoryService.getAllCategories());
return "index";
}
#GetMapping("/deletePost/{id}")
public String deletePostById(#PathVariable("id") Long id){
postService.deletePost(id);
return "redirect:/edit";
}
#GetMapping("/editPost/{id}")
public String editPost(#PathVariable("id") Long id,Model model){
Post post = postService.findOnePost(id);
model.addAttribute("post", post);
return "updatePost";
}
#PostMapping("/updatePostAction/{id}")
public String updateEditedPost(#ModelAttribute Post post, #PathVariable Long id){
post.setId(id);
if (post.getId() == null){
throw new NullPointerException("what the hell: " + post.getId());
}
postService.EditPost(post);
return "redirect:/edit";
}
#PostMapping(value = "/addCategory" )
public String addCategory(#ModelAttribute Category category, #RequestParam(value = "action",required = true) String action) {
if (action.equals("AddCategory")) {
categoryService.addCategory(category);
}
return "/addPost";
}
and my html file:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form th:action="#{/edit/upload}" th:object="${post}" method="post" >
Name:<br>
<input type="text" th:field="*{author}">
<br>
Title:<br>
<input type="text" th:field="*{title}">
<br>
Post:<br>
<textarea name="post" id="" cols="30" rows="10" th:field="*{text}"></textarea>
<br><br>
<input type="submit" name="action" value="AddPost">
</form>
<br>
<form th:action="#{/edit/addCategory}" th:object="${category}" method="post" >
New Category: <br>
<input type="text" th:field="*{name}">
<input type="submit" name="action" value="AddCategory" >
</form>
<p th:text="${post.author}"></p>
<p th:text="${post.text}"></p>
</body>
</html>
How can I solve this Exception?
EDIT:
Post class.
#Entity
#Table(name = "posts")
public class Post {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Date date;
private String author;
private String title;
private String text;
public Post(String author, String title, String text) {
this.author = author;
this.title = title;
this.text = text;
}
public Post(){
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}

Hibernate, MySQL, Spring MVC,Freemarker :java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax [duplicate]

This question already has answers here:
How to map an entity field whose name is a reserved word in JPA
(8 answers)
Closed 4 years ago.
I'm making simple Spring MVC library app, using Freemarker, MySQL and Hibernate,
i created form for adding new book to the library, it's code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Create new user</title>
</head>
<body>
<form name="booker" action="/newBook" method="post" >
<p>Name</p>
<input title="Name" type="text" name="name">
<p>Desc</p>
<input title="Email" type="text" name="desc">
<p>Author</p>
<input title="Age" type="text" name="aut">
<p>Year</p>
<input title="Age" type="text" name="year">
<input type="submit" value="OK">
</form>
</body>
</html>
Also i have Controller, BookDAO, BookService and Book entity
Controller:
#Controller
#RequestMapping("/")
public class BookController {
#Autowired
private BookService service;
#GetMapping("/books")
public String viewAll(Model model){
model.addAttribute("books",service.findAll());
return "books";
}
#GetMapping("/addBook")
public String addBook(){
return "createBook";
}
#PostMapping("/newBook")
public String newBooks(#ModelAttribute("booker") Book book){
service.add(book);
return "redirect:/books";
}
}
Entity:
#Table(name = "booker")
#Entity
public class Book {
private int id;
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
#Column(name = "idbooker")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
private String name;
private String desc;
private String aut;
private int year;
#Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Column(name="desc")
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
#Column(name = "aut")
public String getAut() {
return aut;
}
public void setAut(String author) {
this.aut = author;
}
#Column(name = "year")
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
}
When i try to post new book, i get this exception, database columns' names are same can somebody tell how to fix it, ty.
Could be you have some issue with desc (reserved word) try using backtics
#Column(name="`desc`")

How to display #Lob image from mysql database using spring mvc and jsp

There is link to github: https://github.com/Lukszn/ProjectProfile I'm using Spring 4.3.7.RELEASE, MySQL Connector Java: 5.1.39 and hibrnate: 5.2.9. Finaly
There i have User and his Account model. In account i have #Lob accPicture and some Strings(+ get/set). I'm trying a lot of answers from stackoverflow and documentation to show Account image, but without success. Last think what I do : created own ImageController. I successfully stored image in database but when I'm trying to display it in my jsp, it is showing "HTTP Status 400 -
The request sent by the client was syntactically incorrect."
Firstly I show you my User model:
#Entity
#Table(name = "users")
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(unique = true)
#NotBlank
#Size(min=4,max=20)
private String login;
#NotBlank
private String password;
#Column(unique = true)
#Email
#NotBlank
private String email;
private String permission;
#OneToMany()
private List<Account> accounts;
public User(final String login, final String password, final String email) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(login));
Preconditions.checkArgument(!Strings.isNullOrEmpty(password));
Preconditions.checkArgument(!Strings.isNullOrEmpty(email));
this.login = login;
this.password = password;
this.email = email;
}
public User() {
}
}
+ get/set
Account model:
#Entity
#Table(name = "accounts")
public class Account {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private boolean ifBasicAccount;
private String accTitle;
private String accFirstName;
private String accLastName;
private String accBirthdate;
private String accPhoneNumber;
private String accEducation;
private String accExperience;
private String accAbilities;
private String accInterests;
private String accProjects;
private String accDescription;
#Lob
private byte[] accPicture;
#ManyToOne
private User user;
public Account() {
}
+ get/set
next Account Controller:
#Controller
public class AccountController {
#Autowired
AccountRepository accountRepository;
#Autowired
UserRepository userRepository;
#RequestMapping(method = RequestMethod.GET, value ="addAccount")
public String addAccount(Model model) {
Account account = new Account();
model.addAttribute("account", account);
return "addAccount";
}
#RequestMapping(method = RequestMethod.POST, value ="addAccount")
public String addAccount(#ModelAttribute Account account, HttpSession session) {
User user = userRepository.findOne((Long) session.getAttribute("user_id"));
account.setIfBasicAccount(false);
account.setUser(user);
accountRepository.save(account);
return "redirect:/accounts";
}
#RequestMapping("/accounts")
public String accountList(Model model, HttpSession ses) {
long userId = (Long) ses.getAttribute("user_id");
List<Account> accounts = accountRepository.findUserAccounts(userId);
model.addAttribute("accounts", accounts);
return "accounts";
}
#RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
public String editAccountForm(Model model, #PathVariable long id) {
Account account = accountRepository.findOne(id);
model.addAttribute("account",account);
return "editAccountForm";
}
#RequestMapping(value = "/edit/{id}", method = RequestMethod.POST)
public String editAccount(#ModelAttribute Account account, #PathVariable long id) {
Account accountToUpdate = accountRepository.findOne(id);
accountToUpdate.setAccTitle(account.getAccTitle());
accountToUpdate.setAccFirstName(account.getAccFirstName());
accountToUpdate.setAccLastName(account.getAccLastName());
accountToUpdate.setAccBirthdate(account.getAccBirthdate());
accountToUpdate.setAccPhoneNumber(account.getAccPhoneNumber());
accountToUpdate.setAccEducation(account.getAccEducation());
accountToUpdate.setAccExperience(account.getAccExperience());
accountToUpdate.setAccAbilities(account.getAccAbilities());
accountToUpdate.setAccInterests(account.getAccInterests());
accountToUpdate.setAccProjects(account.getAccProjects());
accountToUpdate.setAccDescription(account.getAccDescription());
accountRepository.save(accountToUpdate);
return "redirect:/accounts";
}
#RequestMapping("/delete")
public String deleteAccount(Model model) {
return "deleteAccount";
}
#RequestMapping("/read/{id}")
public String read(#PathVariable long id) {
return accountRepository.findOne(id).toString();
}
#RequestMapping("/delete/{id}")
public String delete(#PathVariable long id) {
Account account = accountRepository.findOne(id);
accountRepository.delete(account);
return "redirect:/accounts";
}
}
and last one ImageController:
#Controller
#RequestMapping("/user")
public class ImageController {
private AccountRepository accountRepository;
#RequestMapping(value = "/accounts", method = RequestMethod.GET)
public void showImage(#RequestParam("id") Long id, HttpServletResponse response, HttpServletRequest request)
throws ServletException, IOException {
Account account = accountRepository.getOne(id);
response.setContentType("image/jpeg, image/jpg, image/png, image/gif");
response.getOutputStream().write(account.getAccPicture());
response.getOutputStream().close();
}
}
my .jsp to show account:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix = "fmt" uri = "http://java.sun.com/jsp/jstl/fmt" %>
<%# page isELIgnored="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%# include file="/WEB-INF/parts/header.jsp" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<div align="center">
<table class="table table-striped">
<h1>Accounts:</h1>
<c:forEach items="${accounts}" var="account" begin="0" varStatus="theCount">
<tr>
<td>${theCount.index+1}</td>
<td><b>Nazwa: </b>${account.accTitle}</td>
<td><b>Opis: </b>${account.accDescription}</td>
<td><img src="/ProjectProfile/user/accounts?id=${account.id}"/></td>
<td><a style="width: 180px;height: 20px;" href="./edit/${account.id}" class="badge badge-primary">Show/Edit</a></td>
<td><a style="width: 180px;height: 20px;" href="./delete/${account.id}" class="badge badge-danger">Delete</a></td>
</tr>
</c:forEach>
</table>
Add Account
</body>
</html>
Maybe I need use Base64Encoder, but i don't know how? .... I use pom.xml and AppConfig for configuration. Please, check out this project, maybe somebody can help?
<img id="photo" src="data:image/png;base64,${PHOTOYOUNEED}" />
In the controller responsible for the image sending to the html:
(...)
String photoencodeBase64 = modelX.getStringPhoto();
modelAndView.addObject("PHOTOYOUNEED", photoencodeBase64 );
and I also use this method in the model to convert byte[] to string in base64:
public static String convertBinImageToString(byte[] binImage) {
if(binImage!=null && binImage.length>0) {
return Base64.getEncoder().encodeToString(binImage);
}
else
return "";
}
and I call it in the getStringPhoto() getter inside the model.
Ok Eunito, let's see... Changed Account.java(model):
#Entity
#Table(name = "accounts")
public class Account {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private boolean ifBasicAccount;
private String accTitle;
private String accFirstName;
private String accLastName;
private String accBirthdate;
private String accPhoneNumber;
private String accEducation;
private String accExperience;
private String accAbilities;
private String accInterests;
private String accProjects;
private String accDescription;
#Lob
private byte[] accPicture;
private String stringPhoto;
#ManyToOne
private User user;
public Account() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAccTitle() {
return accTitle;
}
public void setAccTitle(String accTitle) {
this.accTitle = accTitle;
}
public String getAccFirstName() {
return accFirstName;
}
public void setAccFirstName(String accFirstName) {
this.accFirstName = accFirstName;
}
public String getAccLastName() {
return accLastName;
}
public void setAccLastName(String accLastName) {
this.accLastName = accLastName;
}
public String getAccBirthdate() {
return accBirthdate;
}
public void setAccBirthdate(String accBirthdate) {
this.accBirthdate = accBirthdate;
}
public String getAccPhoneNumber() {
return accPhoneNumber;
}
public void setAccPhoneNumber(String accPhoneNumber) {
this.accPhoneNumber = accPhoneNumber;
}
public String getAccEducation() {
return accEducation;
}
public void setAccEducation(String accEducation) {
this.accEducation = accEducation;
}
public String getAccExperience() {
return accExperience;
}
public void setAccExperience(String accExperience) {
this.accExperience = accExperience;
}
public String getAccAbilities() {
return accAbilities;
}
public void setAccAbilities(String accAbilities) {
this.accAbilities = accAbilities;
}
public String getAccInterests() {
return accInterests;
}
public void setAccInterests(String accInterests) {
this.accInterests = accInterests;
}
public String getAccProjects() {
return accProjects;
}
public void setAccProjects(String accProjects) {
this.accProjects = accProjects;
}
public String getAccDescription() {
return accDescription;
}
public void setAccDescription(String accDescription) {
this.accDescription = accDescription;
}
public byte[] getAccPicture() {
return accPicture;
}
public void setAccPicture(byte[] accPicture) {
this.accPicture = accPicture;
}
public String getStringPhoto() {
return convertBinImageToString(accPicture);
}
public void setStringPhoto(String stringPhoto) {
this.stringPhoto = stringPhoto;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public boolean isIfBasicAccount() {
return ifBasicAccount;
}
public void setIfBasicAccount(boolean ifBasicAccount) {
this.ifBasicAccount = ifBasicAccount;
}
public static String convertBinImageToString(byte[] accPicture) {
if(accPicture!=null && accPicture.length>0) {
return Base64.getEncoder().encodeToString(accPicture);
}
else
return "";
}
}
I have two controllers for Account(one is only for showing image-I'm not so sure that's a good thing, because i have two the same RequestMappings). So see changed ImageController:
#Controller
#RequestMapping("/admin/user")
public class ImageController {
#Autowired
AccountRepository accountRepository;
#RequestMapping(value = "/accounts", method = RequestMethod.GET)
public void showImage(#RequestParam("id") long id, Model model) {
Account account = accountRepository.findById(id);
String photoencodeBase64 = account.getStringPhoto();
model.addAttribute("accPicture", photoencodeBase64);
}
}
And .jsp to show image:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix = "fmt" uri = "http://java.sun.com/jsp/jstl/fmt" %>
<%# page isELIgnored="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%# include file="/WEB-INF/parts/header.jsp" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<div align="center">
<table class="table table-striped">
<h1>Accounts:</h1>
<c:forEach items="${accounts}" var="account" begin="0" varStatus="theCount">
<tr>
<td>${theCount.index+1}</td>
<td><b>Title: </b>${account.accTitle}</td>
<td><b>Description: </b>${account.accDescription}</td>
<td><b>Image: </b><img id="photo" src="data:image/png;base64,${account.accPicture}" /></td>
<td><a style="width: 180px;height: 20px;" href="./edit/${account.id}" class="badge badge-primary">Show/Edit</a></td>
<td><a style="width: 180px;height: 20px;" href="./delete/${account.id}" class="badge badge-danger">Delete</a></td>
</tr>
</c:forEach>
</table>
Add Account
</body>
</html>
so what is happen- when i add new account -> write Title, Name etc. and add image from file my browser show me HTTP Status 400 - The request sent by the client was syntactically incorrect. - > there i need see all user accounts.
In STS console nothing happend. In MySQL too.
Why not use Spring Content JPA? This can provide a storage service and rest endpoints for managing content associated with jpa entities.
pom.xml
<!-- Java API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-jpa</artifactId>
<version>0.1.0</version>
</dependency>
<!-- REST API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-rest</artifactId>
<version>0.1.0</version>
</dependency>
Configuration
#Configuration
#EnableJpaStores
#Import("org.springframework.content.rest.config.RestConfiguration.class")
public class MysqlConfig {
// schema management
//
#Value("/org/springframework/content/jpa/schema-drop-mysql.sql")
private Resource dropRepositoryTables;
#Value("/org/springframework/content/jpa/schema-mysql.sql")
private Resource dataRepositorySchema;
#Bean
DataSourceInitializer datasourceInitializer() {
ResourceDatabasePopulator databasePopulator =
new ResourceDatabasePopulator();
databasePopulator.addScript(dropReopsitoryTables);
databasePopulator.addScript(dataReopsitorySchema);
databasePopulator.setIgnoreFailedDrops(true);
DataSourceInitializer initializer = new DataSourceInitializer();
initializer.setDataSource(dataSource());
initializer.setDatabasePopulator(databasePopulator);
return initializer;
}
}
To associate content, add Spring Content annotations to your account entity.
Account.java
#Entity
public class Account {
// replace #Lob field with
#ContentId
private String contentId;
#ContentLength
private long contentLength = 0L;
// if you have rest endpoints
#MimeType
private String mimeType = "text/plain";
Create a "store":
AccountImagesStore.java
#StoreRestResource(path="accountImages)
public interface AccountImagesStore extends ContentStore<Account, String> {
}
This is all you need to create REST endpoints # /accountImages. When your application starts, Spring Content will look at your dependencies (seeing Spring Content JPA/REST), look at your AccountImagesStore interface and inject an implementation of that interface for JPA. It will also inject a #Controller that forwards http requests to that implementation. This saves you having to implement any of this yourself whch I think is what you are after.
So...
curl -X POST /accountImages/{account-id}
with a multipart/form-data request will store the image in the database and associate it with the account entity whose id is account-id.
curl /accountImages/{account-id}
will fetch it again and so on...supports full CRUD.
So all you should need to display this in your JSP is an image tag:
There are a couple of getting started guides here. The reference guide is here. And there is a tutorial video here. The coding bit starts about 1/2 way through.
HTH

Spring MVC :how a form transfer an object to Controller?? Always 400 error

When i try to access http://localhost:8080/XX/articles/addArticle
and submit the form, there is always a "400 BAD REQUEST" error.
i've tried to look up for the reason, all i got is that object transfered from the form is not as same type as my model(, which is an Article object? here). However, i don't think i really get it..
All codes are here, the config is all good.
Here are 2 models:
Article.java
#Entity
#Table(name="article_inf")
public class Article {
private int articleId;
private String title;
private User author;
private String content;
public Article() {
}
public Article(String title, User author, String content) {
this.title = title;
this.author = author;
this.content = content;
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public int getArticleId() {
return articleId;
}
public void setArticleId(int articleId) {
this.articleId = articleId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#ManyToOne(targetEntity=User.class)
#JoinColumn(name="author", referencedColumnName="userId", nullable=false)
public User getAuthor() {
return author;
}
public void setAuthor(User author) {
this.author = author;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
User.java
#Entity
#Table(name="agri_user_inf")
public class User {
private int userId;
private String userName;
private String password;
private String cellPhone;
private List<Article> articles;
public User() {
articles = new ArrayList<>();
}
public User(String userName, String password, String cellPhone) {
this.userName = userName;
this.password = password;
this.cellPhone = cellPhone;
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCellPhone() {
return cellPhone;
}
public void setCellPhone(String cellPhone) {
this.cellPhone = cellPhone;
}
#OneToMany(targetEntity=Article.class, mappedBy="author")
public List<Article> getArticles() {
return articles;
}
public void setArticles(List<Article> articles) {
this.articles = articles;
}
controller
ArticleController.java
#Controller
#RequestMapping("articles")
public class ArticleController {
private ArticleDao articleDao;
#Autowired
public ArticleController(ArticleDao articleDao) {
this.articleDao = articleDao;
}
#RequestMapping(value="addArticle", method=GET)
public String addArticle(ModelMap modelMap) {
List<User> authors = userDao.getAllUsers();
// add all authors
modelMap.addAttribute("authors", authors);
return "articles/addArticleForm";
}
#RequestMapping(value="addArticle", method=POST)
public String addArticle(Article article) {
articleDao.addArticle(article);
return "redirect:/articles";
}
// other code
my form addArticleForm.jsp
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form method="post">
title: <input type="text" name="title"/><br/>
author: <select name="author">
<c:forEach items="${authors}" var="author">
<option value="${author}">${author.userName}</option>
</c:forEach>
</select>
<br/>
content: <input type="text" name="content"/><br/>
<input type="submit" value="add"/>
</form>
</body>
</html>
You are violating REST principles. Always use version in your endpoint and resource name after that. Example - /api/v1/articles. After that with help of HttpMethods access your resources. Example - If you want to
1.1 add new Article , use POST request to /api/v1/articles
1.2 delete existing Article, use DELETE request to /api/v1/articles/{articleId}
1.3 get one Article, use GET request to /api/v1/articles/{articleId}
1.4 get all Articles, use GET request to /api/v1/articles
1.5 update existing Article, use PUT request to /api/v1/articles/{articleId}
Never use your Entity which is going to be persisted in DB for all layers. It`s bad practice to connect Entity with your view, instead you can use DTO.
Use #ModelAttribute annotation in your controller layer with same name as in view to handle incoming Article object. Example
public String addArticle(#ModelAttribute("article") Article article )
To add new Article first you need to create endpoint which is returning empty Article object inside of ModelMap. Then you must handle this in your front end(JSP) and for submitting this form follow step 3.
Hope this will help.
I got solution :
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form method="post">
title: <input type="text" name="title"/><br/>
author: <select name="author.userId">
<c:forEach items="${authors}" var="author">
<option value="${author.userId}">${author.userName}</option>
</c:forEach>
</select>
<br/>
content: <input type="text" name="content"/><br/>
<input type="submit" value="add"/>
</form>
</body>
</html>
change name of <select> tag from "author" to "author.userId" . That works.

Why the errors.hasErrors() always return false in Spring 4 annotated form validation?

I tried to implement the annotated form input validation in Spring 4.
The following tutorials just don't work.
http://www.javacodegeeks.com/2013/04/spring-mvc-form-validation-with-annotations-2.html
http://codetutr.com/2013/05/28/spring-mvc-form-validation/
The symptoms are the same: the errors.hasErrors() always return false.
And some reader of the above tutorial 2 reported the identical issue, too.
This is the model object Spitter :
public class Spitter {
private Long id;
#NotNull
#Size(min = 5, max = 16)
private String username="default name";
#NotNull
#Size(min = 5, max = 25)
private String password;
#NotNull
#Size(min = 2, max = 30)
private String firstName;
#NotNull
#Size(min = 2, max = 30)
private String lastName;
#NotNull
#Email
private String email;
public Spitter() {
}
public Spitter(String username, String password, String firstName,
String lastName, String email) {
this(null, username, password, firstName, lastName, email);
}
public Spitter(Long id, String username, String password, String firstName,
String lastName, String email) {
this.id = id;
this.username = username;
this.password = password;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(#Size(min = 5, max = 16) String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Override
public boolean equals(Object that) {
return EqualsBuilder.reflectionEquals(this, that, "firstName",
"lastName", "username", "password", "email");
}
#Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this, "firstName",
"lastName", "username", "password", "email");
}
}
This the form JSP:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# taglib uri="http://www.springframework.org/tags/form" prefix="f" %>
<%# page session="false" %>
<html>
<head>
<title>Spitter</title>
<link rel="stylesheet" type="text/css"
href="<c:url value="/resources/style.css" />" >
</head>
<body>
<h1>Register</h1>
<f:form method="POST" commandName="spitter" modelattribute="spitter">
f-First Name: <f:input path="firstName" /><br/>
f-Last Name: <f:input path="lastName" /><br/>
f-Email: <f:input path="email" /><br/>
f-User Name: <f:input path="username" /><br/>
f-Password: <f:input path="password" /><br/>
<input type="submit" value="Register" />
</f:form>
</body>
</html>
I am using:
validation-api-1.1.0.Final.jar
hibernate-validator-5.0.1.Final.jar
This question is solved at here!
How to turn on annotation driven validation in Spring 4?
You also need to tell Spring to enable JSR-303 validation. If you are using an xml way, try registering
<mvc:annotation-driven/> in your context xml
or if you are using java style:
#EnableWebMvc atop your context loading class
Hope this solves

Categories