Sending object from thymeleaf template to Rest Controller returns "Unsupported Media Type" - spring

I'm trying to POST some object fields to a RestController using thymeleaf.
But the result of the post returns what looks like a parsing error :
There was an unexpected error (type=Unsupported Media Type, status=415). Content type
'application/x-www-form-urlencoded;charset=UTF-8' not supported
The index page sends two attributes to the controller which then calls the business service that builds the new object.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Simple Sidebar - Start Bootstrap Template</title>
<!-- Bootstrap core CSS -->
<link th:href="#{/index/vendor/bootstrap/css/bootstrap.min.css}"
rel="stylesheet">
<!-- Custom styles for this template -->
<link th:href="#{/index/css/simple-sidebar.css}" rel="stylesheet">
</head>
<body>
<!-- Page Content -->
<div id="page-content-wrapper">
<div class="container-fluid">
<form action="#" th:action="#{/accounts}" th:object="${account}" method="post" enctype="application/json">
<div class="form-row">
<div class="form-group col-md-4 ">
<label for="inputState">Departement</label>
<input type="text" th:field="*{owner}" class="form-control" placeholder="Type in the department ..." />
</div>
</div>
<div class="form-row">
<div class="form-group col-md-4 ">
<label for="inputState">Budget</label>
<input type="number" step="0.01" th:field="*{budget}" class="form-control" placeholder="Type in Budget ..." />
</div>
</div>
<button class="btn btn-primary" type="submit">Enregistrer</button>
</form>
</div>
</div>
<!-- /#page-content-wrapper -->
</body>
</html>
This is the Rest Controller :
#RestController
public class AccountController {
#Autowired
private AccountService accountService;
#RequestMapping(value="/accounts", method=RequestMethod.POST)
public void addAccount(#RequestBody Account account ) {
accountService.addAccount(account);
}
}
Account is a simple POJO :
public class Account {
private String id;
private String owner;
private double budget;
private double budgetInvest;
private double budgetFonction;
public Account() {
}
public Account(String id,String owner, double budget, double budgetInvest, double budgetFonction
) {
super();
this.id = id;
this.owner=owner;
this.budget = budget;
this.budgetInvest = budgetInvest;
this.budgetFonction = budgetFonction;
}
public Account (String owner, double budget) {
this.owner = owner;
this.budget=budget;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public double getBudget() {
return budget;
}
public void setBudget(double budget) {
this.budget = budget;
}
public double getBudgetInvest() {
return budgetInvest;
}
public void setBudgetInvest(double budgetInvest) {
this.budgetInvest = budgetInvest;
}
public double getBudgetFonction() {
return budgetFonction;
}
public void setBudgetFonction(double budgetFonction) {
this.budgetFonction = budgetFonction;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
}
And the add method simply adds the object to a list of objects.
What am i doing wrong here ?

I think problem in you controller. First it won't be #RestController. It will be #Controller. Second it won't be #RequestBody. It will be #ModelAttribute.So write your controller like
#Controller
public class AccountController {
#Autowired
private AccountService accountService;
#RequestMapping(value="/accounts", method=RequestMethod.POST)
public void addAccount(#ModelAttribute("account") Account account ) {
System.out.ptintln("Checking");
accountService.addAccount(account);
}
The most relevant to the discussion of REST, the #RestController annota- tion tells Spring that all handler methods in the controller should have their return value written directly to the body of the response, rather than being carried in the model to a view for rendering. This line from book spring in action. So here you should use #Controller annotation.

You can use restcontroller but u must using ajax post for run "/account"
Cmiiw

Related

How to pass individual variables to view in thymeleaf?

Hi I'm building a skeleton of a car renting webapp and I'm trying to create a view that shows some details like location name, car name etc.
View code- car-list.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Vehicle List</title>
<h2 th:text="${location1}">Locations</h2>
<table class="table table-stripped">
<thead>
<td th:text="${vehicle1Name}">Vehicle Name</td>
</tr>
</thead>
<td th:text="${vehicle2Name}">Vehicle Name</td>
</tr>
</table>
</head>
<body>
</body>
</html>
And heres my controller
package com.project.CS4125.controller;
import com.project.CS4125.model.*;
import com.project.CS4125.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.ArrayList;
import java.util.List;
#Controller
#RequestMapping("/car-list")
public class VehicleController {
#GetMapping("/car-list")
public String carList(Model model){
Vehicle VWGolf = new BasicCar();
Vehicle Duster = new SUVDecorator(new BasicCar());
Location limerick= new Location("Limerick");
model.addAttribute("location1", limerick.getLocationName());
model.addAttribute("vehicle1Name", "Volkswagen Golf");
model.addAttribute("vehicle2Name", "Dacia Duster");
return "index";
}
}
My problem is the view comes up completely empty, any help appreciated.
EDIT
Before this page I have a register and login page
index.html (register page
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Register</title>
</head>
<body>
<form action="#" th:action="#{/register}" th:object="${user}"
method="post">
<p>User Name <input type="text" name="name"></p>
<p>Password <input type="password" name="password"></p>
<button type="submit">Register</button>
</form>
<button>Login Here</button>
</body>
</html>
login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<form action="#" th:action="#{/login}" th:object="${user}"
method="post">
<p>User Name <input type="text" name="name"></p>
<p>Password <input type="password" name="password"></p>
<button type="submit">Login</button>
</form>
<button>Register Here</button>
</body>
</html>
And heres the controller for these
#Controller
#RequestMapping("/")
public class IndexController {
#Autowired
private UserService userService;
#Autowired
private CustomerFactory userFactory;
#PostMapping("/register")
public String registerUser(#ModelAttribute User user){
User u = userFactory.createUser(user.getName(), user.getPassword());
userService.saveUser(u);
return "login";
}
#GetMapping("/login")
public String login(){
return "login";
}
#PostMapping("/login")
public String loginUser(#ModelAttribute User user){
User authenticatedUser = userService.authenticate(user.getName(), user.getPassword());
System.out.println(authenticatedUser.toString());
return "car-list";
}
}
Even after adding the code from the answer below I'm still getting an empty page, after submitting the login form moving to the car list page its still empty.
I also noticed in the answer the URL is http://localhost:8080/car-list but when I try it its http://localhost:8080/login
I've just tested your code and you have two problems.
The first one is at your:
#Controller
#RequestMapping("/car-list")
public class VehicleController {
#GetMapping("/car-list")
In this GetMapping you're saying that you want to access your template at /car-list/car-list.
The seccond one is with your template name. You're returning "index" when you should return "car-list", at this you're returning the template name.
So, editting your code like this:
#Controller
#RequestMapping("/car-list")
public class VehicleController {
#GetMapping
public String carList(Model model){
model.addAttribute("location1", "Answer");
model.addAttribute("vehicle1Name", "Volkswagen Golf");
model.addAttribute("vehicle2Name", "Dacia Duster");
return "car-list";
}
}
I got:
Template working and returning

use Thymleaf and spring met org.springframework.web.method.annotation.MethodArgumentTypeMismatchException

I am running a springboot demo,integrated with Thymleaf.But it keep throwing the following exeption:
WARN 25302 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved
[org.springframework.web.method.annotation.MethodArgumentTypeMismatchException:
Failed to convert value of type 'java.lang.String' to required type
'java.lang.Long'; nested exception is java.lang.NumberFormatException:
For input string: "form.html"]**
controller:
#RestController
#RequestMapping("/users")
public class UserController {
#Autowired
private UserRepository userRepository;
private List<User> getUserlist() {
return userRepository.listUser();
}
#GetMapping
public ModelAndView list(Model model) {
model.addAttribute("userList", getUserlist());
model.addAttribute("title", "user management");
return new ModelAndView("users/list", "userModel", model);
}
#GetMapping("/form")
public ModelAndView createForm(Model model) {
User user=new User();
user=userRepository.saveOrUpateUser(user);
model.addAttribute("user", user);
model.addAttribute("title", "create user");
return new ModelAndView("users/form", "userModel", model);
}
list.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title th:text="${userModel.title}">welcome</title>
</head>
<body>
<div th:replace="~{fragments/header :: header}">...</div>
<h3 th:text="${userModel.title}">Welcome to baidu.com</h3>
<div>
create user
</div>
<table border="1">
<thead>
<tr>
<td>ID</td>
<td>Age</td>
<td>Name</td>
</tr>
</thead>
<tbody>
<tr th:if="${userModel.userList.size()} eq 0">
<td colspan="3">no user info!!</td>
</tr>
<tr th:each="user : ${userModel.userList}">
<td th:text="${user.id}">1</td>
<td th:text="${user.age}">11</td>
<td><a href="view.html" th:href="#{'/users/' + ${user.id}}"
th:text="${user.name}">waylau</a></td>
</tr>
</tbody>
</table>
<div th:replace="~{fragments/footer :: footer}">...</div>
</body>
</html>
form.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title th:text="${userModel.title}">users : View</title>
</head>s
<body>
<div th:replace="~{fragments/header :: header}">...</div>
<h3 th:text="${userModel.title}">Welcome to baidu.com</h3>
<div>
back to home
</div>
<form action="/users" method="POST" th:object="${userModel.user}">
<input type="hidden" name="id" th:value="*{id}">
名称:<br>
<input type="text" name="name" th:value="*{name}">
<br>
年龄:<br>
<input type="text" name="age" th:value="*{age}">
<input type="submit" value="提交">
</form>
<div th:replace="~{fragments/footer :: footer}">...</div>
</body>
</html>
User.java
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement // mediatype 转为xml
public class User {
private long id; // 用户的唯一标识
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
....getter and setter
}
on the home page,everything goes fine,except the create user anchor which should return a form to fill.
any idea?

Spring and Hibernate Form Validation Error not show

This is my customer.java class using for as bean
package com.zeeshan.form;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class Customer {
private String firstName;
#NotNull(message="is required")
#Size(min=1)
private String lastName;
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;
}
}
CustomerController.java
package com.zeeshan.form;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping("/customer")
public class CustomerController {
#RequestMapping("/showForm")
public String showFormModel(Model theModel) {
theModel.addAttribute("customer", new Customer());
return "customer-form";
}
#RequestMapping("/processForm")
public String processForm(#ModelAttribute("customer") #Valid Customer theCustomer, BindingResult theBindingresult) {
if(theBindingresult.hasErrors()) {
return "customer-form";
}
else {
return "customer-confirmation";
}
}
}
customer-form.jsp
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
<style>
.error{
color: red;
}
</style>
</head>
<body>
<h2>Customer Registeration Form</h2>
<form:form action="processForm" modelAttribute="customer">
First Name : <form:input path="firstName"/>
<br><br>
Last Name (*) : <form:input path="lastName"/>
<form:errors path="lastName" cssClass="error" />
<br><br>
<input type="submit" value="Submit" />
</form:form>
</body>
</html>
Hibernate validator doesn't work.
my code run properly but doesn't show any error
I am attaching file structure
following libraries are being used
hibernate version 6.0.2
spring version 5.0.6
The code looks fine. Reading your question, it seems that you might be a little confused between these two:
Hibernate ORM: Implementation of JPA
Hibernate Validator: Implementation of Bean Validation
So, for Bean Validation to work, you need to add Hibernate Validator in classpath. Means simply add it in dependencies of your build.gradle/pom.xml i.e. the build script of your build tool.

HTTP Status 400 - Bad Request issue

I create simple Spring app.I have two views(forma,confirmation),model(User) and Spring Bean-Controller(Main_Controller).When I'm on the adress http://localhost:8080/Path/forma.htm and fill all forma fields and submit forma glassfish say HTTP Status 400 - Bad Request.Why?To work well should I see a confirmation page with client entry.
Main_Controller
package kontroleri;
#RequestMapping(value = "/forma",method = RequestMethod.GET)
public String pozivanjeForme(Model model)
{
model.addAttribute("user",new User());
return "forma";
}
#RequestMapping(value="/forma",method= RequestMethod.POST)
public String confirm(#ModelAttribute("user")User user,ModelMap model)
{
model.addAttribute("first_name",user.getFirst_name());
model.addAttribute("last_name",user.getLast_name());
model.addAttribute("date_of_birth",user.getDate_of_birth());
model.addAttribute("pid",user.getPid());
model.addAttribute("email",user.getEmail());
model.addAttribute("country",user.getCountry());
model.addAttribute("city",user.getCity());
model.addAttribute("postal",user.getPostal());
return "confirmation";
}
}
User
package model;
private String first_name;
private String last_name;
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private LocalDate date_of_birth;
private String pid;
private String email;
private String country;
private String city;
private String postal;
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
public void setPid(String pid) {
this.pid = pid;
}
public String getCity() {
return city;
}
public String getCountry() {
return country;
}
public LocalDate getDate_of_birth() {
return date_of_birth;
}
public String getEmail() {
return email;
}
public String getFirst_name() {
return first_name;
}
public String getLast_name() {
return last_name;
}
public String getPid() {
return pid;
}
public String getPostal() {
return postal;
}
public void setCountry(String country) {
this.country = country;
}
public void setCity(String city) {
this.city = city;
}
public void setDate_of_birth(LocalDate date_of_birth) {
this.date_of_birth = date_of_birth;
}
public void setEmail(String email) {
this.email = email;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public void setPostal(String postal) {
this.postal = postal;
}
}
forma.jsp
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<%#taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Forma page</title>
<style>
.field{
clear:both;
padding: 5px;
}
.field label{
text-align: left;
width: 100px;
float: left;
}
.error{
color: red;
}
</style>
</head>
<body>
<form:form action="forma.htm" method="post" commandName="user">
<div class="field">
<form:label path="first_name">First name</form:label>
<form:input path="first_name"/>
</div>
<div class="field">
<form:label path="last_name">Last name</form:label>
<form:input path="last_name"/>
</div>
<div class="field">
<form:label path="date_of_birth">Date of birth</form:label>
<form:input path="date_of_birth" type="date"/>
</div>
<div class="field">
<form:label path="pid">Personal ID</form:label>
<form:input path="pid"/>
</div>
<div class="field">
<form:label path="email">Email</form:label>
<form:input path="email"></form:input>
</div>
<div class="field">
<form:label path="country">Country</form:label>
<form:input path="country"></form:input>
</div>
<div class="field">
<form:label path="city">City</form:label>
<form:input path="city"/>
</div>
<div class="field">
<form:label path="postal">Postal code</form:label>
<form:input path="postal"></form:input>
</div>
<input type="submit" value="Submit">
</form:form>
</body>
</html>
confirmation.jsp
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Confirmation Page</title>
</head>
<body>
<h1>You entered following data:</h1>
<p>First name:${first_name}</p>
<p>Last name:${last_name}</p>
<p>Date of birth:${date_of_birth}</p>
<p>Personal ID:${pid}</p>
<p>Email:${email}</p>
<p>Country:${country}</p>
<p>City:${city}</p>
<p>Postal code: ${postal}</p>
</body>
</html>
dispatcher-servlet.xml
<?xml version='1.0' encoding='UTF-8' ?>
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="index.htm">indexController</prop>
<prop key="forma.htm">Kontroler</prop>
</props>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
<bean name="indexController"
class="org.springframework.web.servlet.mvc.ParameterizableViewController"
p:viewName="index" />
<bean class="kontroleri.Main_Controller" id="Kontroler"/>
Please, define extra namespace in dispatcher-servlet.xml
<beans
...
xmlns:mvc="http://www.springframework.org/schema/mvc"
...
xsi:schemaLocation="
...
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
Add <mvc:annotation-driven/> to enable annotation-driven and support for formatting Date etc. fields.

Error message not showing in view page in JSR303, using Bootstrap in jsp

I am adding server side validation in my project. and somehow the error message from controller is not reaching view page.
I am using :
spring
jpa,
JSR303 for validation, and
bootstrap
Below is code for add.jsp
<!DOCTYPE html>
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet"
href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script
src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<style>
.error {
color: #ff0000;
}
.errorblock {
color: #000;
background-color: #ffEEEE;
border: 3px solid #ff0000;
padding: 8px;
margin: 16px;
}
</style>
<title>Add User</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="col-md-4">
<h2>Add User</h2>
<form:form action="user" method="post" role="form"
commandName="user">
<form:errors path="*" cssClass="errorblock" />
<div class="form-group ">
<label for="user">User Name:</label>
<form:input type="text" class="form-control" path="name"
id="name" placeholder="Enter User Name" required="requried"/>
</div>
<div class="form-group">
<label for="email">Email Address:</label>
<form:input type="email" path="emailAddress" class="form-control"
id="email" placeholder="Enter Email Address" required="requried"/>
</div>
<div class="form-group">
<label for="role">Role:</label>
<form:select path="role" class="form-control" id="role" required="requried">
<option disabled selected></option>
<c:forEach var="role" items="${roles}">
<option value="${role.value}">${role.name}</option>
</c:forEach>
</form:select>
</div>
<button type="submit" value="Submit" name="add"
class="btn btn-info active">Submit</button>
Back
</form:form>
</div>
<div class="col-md-4">
<div class="col-md-4"></div>
</div>
</div>
</div>
</div>
</body>
</html>
Below is code for Controller.java
#RequestMapping(value = "/user", params = "add", method = RequestMethod.GET)
public String getAddUser(Model model) {
ArrayList<Role> roles = new ArrayList<Role>();
// From user Add only admin and head of department can be added
roles.add(Role.ADMIN);
roles.add(Role.HEAD_OF_DEPARTMENT);
model.addAttribute("roles", roles);
model.addAttribute("user", new User());
return "user/add";
}
#RequestMapping(value = "/user", params = "add", method = RequestMethod.POST)
public String postAddUser(#ModelAttribute #Valid User user,
BindingResult result) {
if (result.hasErrors()) {
return "redirect:user?add";
} else {
System.out.println("Inside postAddUser");
user = userRepository.save(user);
return "redirect:user?id=" + user.getId();
}
}
Below is code for User.java
package in.ac.jmi.entities;
import in.ac.jmi.constants.Role;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.NotEmpty;
#Entity
#Table(name="USER")
public class User extends UrlEntity{
#Column(name="NAME", nullable = false)
#NotEmpty(message="Name can not be empty")
private String name;
#Column(name="ROLE", nullable = false)
#NotNull(message="Role can not be left blank")
private Role role;
#Column(name = "EMAIL_ADDRESS", nullable = false)
#NotEmpty(message="email address can not be empty")
private String emailAddress;
public User(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
#Override
public String toString() {
return "\nUser [name=" + name + ", role=" + role + ", emailAddress="
+ emailAddress + "]";
}
}
The reason is you are using return "redirect:user?add";, which cleared the error messages in model, try change it to return "user?add";

Resources