Spring MVC Param Error - How to send date request to jsp - spring

I am using Spring MVC 3.4.0. When i tried CRUD example I get this error in my browser console;
HTTP Status 400 - The request sent by the client was syntactically
incorrect.
My codes:
EditBlog.jsp;
<%#taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%# page contentType="text/html; charset=UTF-8" language="java"%>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%# taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles"%>
<form action="/testhibernate/edit/${blogID}/" method="POST" name="BLOG">
<h3>TITLE</h3>
<input name="TITLE" type="text" value="${blogList.title}" size="30"/>
<h3>CREATE_DATE</h3>
<input name="CREATE_DATE" type="date" value="${blogList.createDate}" size="30"/>
<h3>TEXT_CONTENT</h3>
<input name="TEXT_CONTENT" type="text" value="${blogList.textContent}" size="30"/>
<br>
<input name="action" type="submit" value="Edit" size="30"/>
</form>
editController ;
package com.basari.testhibernate;
import java.util.Date;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.basari.blog.Blog;
import com.basari.blog.User_Blog_App;
#Controller
public class editController {
#Autowired
private User_Blog_App deneme1;
#RequestMapping(value = "/edit/{blogID}", method = RequestMethod.GET)
public ModelAndView findBlog(#PathVariable Integer blogID)
{
ModelAndView mav = new ModelAndView("editBlog");
Blog blog= deneme1.findBlog(blogID);
mav.addObject("blogList", blog);
return mav;
}
#RequestMapping(value = "/edit/{blogID}/", method = RequestMethod.POST)
public ModelAndView editBlog(#PathVariable Integer blogID
, #RequestParam( value = "TITLE", required=false) String title
, #RequestParam( value = "TEXT_CONTENT", required=false) String content
, #RequestParam( value = "CREATE_DATE", required=false) Date date
) {
Blog blog= deneme1.findBlog(blogID);
blog.setTitle( title );
blog.setTextContent( title );
blog.setCreateDate(date);
this.deneme1.editBlog( blog );
ContactController.logger.debug( "contactPost action called ");
try{
}finally{
}
ModelAndView mav = new ModelAndView("editBlog");
mav.addObject("blogList", blog);
return mav;
}
}
edit Function ;
public void editBlog(Blog blog){
Session session =sessionFactory.openSession();
Transaction tx= null;
try{
tx= session.beginTransaction();
session.update(blog);
tx.commit();
}
catch(HibernateException e){
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally{
session.close();
}
}
And there is no error in my JAVA console. What is wrong?

Try this It will work for you
In your controller
#InitBinder
protected void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat,false));
}

The error is almost certainly that Spring cannot convert the date you enter in this <input> field
<input name="CREATE_DATE" type="date" value="${blogList.createDate}" size="30"/>
into an argument to pass to
#RequestParam( value = "CREATE_DATE", required=false) Date date
As a result, the request is a Bad Request and Spring returns you a 400 status code.
Add a #DateTimeFormat annotation to your request parameter. For example,
#RequestParam( value = "CREATE_DATE", required=false) #DateTimeFormat("dd-MM-yyyy") Date date
And then make sure your client sends the appropriate format of date. For example
14-01-2014

Related

Showing input parameter on same page in Thymeleaf

I am trying to show the results on the same page as the form in Thymleaf and Spring and this is what I have tried till now:
Controller:
#Controller
public class ThymeleafController {
#GetMapping("/hello")
public String getHello() {
return "hello";
}
#PostMapping("/test")
public String test(#RequestParam("text1")String str, Model model) {
model.addAttribute("sample", str);
return "test";
}
}
test.html page:
<!DOCTYPE html>
<html xmlns:th ="http://www.thymeleaf.org" >
<head>
<meta charset ="UTF-8" ></meta>
<title> Hello World</title>
</head>
<body>
<h1> Hello World</h1>
<form method ="post" action ="/test" >
Enter: <input type ="text" name ="text1" />
<input type ="submit" value ="click" />
</form>
<span th:text ="${sample == null} ? 'null' : ${sample}" ></span>
</body>
</html>
When i go on test page i see this error:
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'GET' not supported
org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported
Can someone give me an ideea or an example how I could display a value on the same page as the form / input ? Thanks
Ref : https://hellokoding.com/handling-form-submission-example-with-java-spring-boot-and-freemarker/
Add for get , so this issue will get solved.
#Controller
public class ThymeleafController {
#GetMapping("/hello")
public String getHello() {
return "hello";
}
#GetMapping("/test")
public String testfrm() {
return "test";
}
#PostMapping("/test")
public String test(#RequestParam("text1")String str, Model model) {
return "test";
}
}

Spring mvc form submission bindingresult throws error

So my bindingresult throws an error but I'm not able to see it for some reason and I'm not able to figure out what the problem is. I'm guessing the problem lies with the variable targetDate where there is a problem the type. I've pasted my controller and JSP code below. Any help is appreciated!
#Controller
public class ToDoController {
#Autowired
private ToDoService service;
// All date parameters displayed as mm/DD/yyyy
#InitBinder
protected void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("mm/DD/yyyy");
binder.registerCustomEditor(Date.class, new CustomDateEditor(
dateFormat, false));
}
#RequestMapping(value = "/list-todo", method= RequestMethod.GET)
// HttpSession allows access to the session
public String showToDo(ModelMap model, HttpSession httpSession) {
String user = (String) httpSession.getAttribute("name");
model.addAttribute("todos", service.retrieveTodos(user));
return "list-todos";
}
// redirect to update form
#RequestMapping(value = "/update-todo", method= RequestMethod.GET)
public String getUpdateForm(ModelMap model, #RequestParam int id) {
System.out.println("ID " + id);
// To work with command bean
model.addAttribute("id", id);
model.addAttribute("todo", service.retrieveTodo(id-1));
return "updateToDo";
}
// What does Valid do?
#RequestMapping(value = "/update-todo", method= RequestMethod.POST)
public String submitUpdate(ModelMap model, #Valid ToDo todo, BindingResult result) {
if (result.hasErrors()) {
System.out.println("ERROR" + result.getAllErrors());
// Redirect and pass on the id value
return "redirect:/update-todo?id=" + todo.getId();
}
System.out.println("Update todo" + todo);
service.updateToDo(todo);
model.clear();
return "redirect:/list-todo";
}
// Will be executed first
#RequestMapping(value = "/add-todo", method= RequestMethod.GET)
public String showAddForm(ModelMap model) {
model.addAttribute("todo", new ToDo());
return "addToDo";
}
/*
* Will be executed after form is submitted
* #Valid ToDo - command bean from addToDo.jsp.
* #Valid to validate the information
* #BindingResult showcases the result of the validation
*/
#RequestMapping(value = "/add-todo", method= RequestMethod.POST)
public String submitAddForm(ModelMap model , #Valid ToDo todo, HttpSession httpSession, BindingResult result) {
System.out.println("running" + result);
// If there is validation error , return to addToDos page for user to fix the error
if (result.hasErrors()) {
return "redirect:/showAddForm?id=?" + todo.getId();
}
String user = (String) httpSession.getAttribute("name");
service.addTodo(user, todo.getDescription(), todo.getTargetDate(), false);
// Clears the url e.g. name?=jyj123
model.clear();
// return to the url which executes the showToDO
return "redirect:/list-todo";
}
// delete to do entry
#RequestMapping(value = "/delete-todo", method= RequestMethod.GET)
public String deleteToDo(ModelMap model, #RequestParam int id) {
service.deleteTodo(id);
model.clear();
return "redirect:/list-todo"; }
}
My JSP
<%# taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%# include file = "common/header.jspf" %>
<%# include file = "common/nav.jspf" %>
<div class="container">
<H1>Update your task!</H1>
<form:form method="POST" commandName="todo">
<!-- Carry on the id value -->
<form:hidden path = "id"/>
<form:hidden path = "user"/>
<fieldset class="form-group">
<form:label path="description">Description:</form:label>
<form:input path="description" type="text" class="form-control"
required="required" />
<form:errors path="description" cssClass="text-warning" />
</fieldset>
<fieldset class="form-group">
<form:label path="targetDate">Target Date</form:label>
<form:input path="targetDate" type="text" class="form-control"
required="required" />
<form:errors path="targetDate" cssClass="text-warning" />
</fieldset>
<fieldset class="form-group">
<form:radiobutton path="completion" value="true" />
<form:radiobutton path="completion" value="false" />
</fieldset>
<button type="submit" class="btn btn-success" >Submit Update</button>
</form:form>
<spring:hasBindErrors htmlEscape="true" name="todo">
<c:if test="${errors.errorCount gt 0}">
<h4>The error list :</h4>
<font color="red">
<c:forEach items="${errors.allErrors}" var="error">
<spring:message code="${error.code}"
arguments="${error.arguments}"
text="${error.defaultMessage}"/><br/>
</c:forEach>
</font>
</c:if>
</spring:hasBindErrors>
</div>
<%# include file = "common/footer.jspf" %>
EDIT: bindingresult throws this
ERROR[Field error in object 'todo' on field 'targetDate': rejected value [Tue Jan 05 00:00:00 SGT 2021]; codes [typeMismatch.todo.targetDate,typeMismatch.targetDate,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [todo.targetDate,targetDate]; arguments []; default message [targetDate]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'targetDate'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.util.Date] for value 'Tue Jan 05 00:00:00 SGT 2021'; nested exception is java.lang.IllegalArgumentException]]
In your jsp you submit the form to "todo", not "update-todo". It would be nice to see your ToDo bean. Also: result.getAllErrors().

Why the value in model.put is appended in URL

I am building a Spring MVC Web App. In one Controller, I used model.put method to pass some information to a jsp file.
The following is the snippet of controller
#RequestMapping(value = "/login" , method= RequestMethod.POST)
public String loginPost(HttpSession session,ModelMap model, #RequestParam(value = "username") String username, #RequestParam(value = "password") String password) throws Exception {
User user = getUser(username, password);
if(user !=null){
session.setAttribute("username",username);
model.put("message","login successful ");
return "redirect:/index";
}else{
model.put("message","login failed");
return "redirect:/login";
}
}
The index.jsp and login.jsp:
<%# page contentType="text/html; charset=UTF-8" %>
<html>
<body>
Click to upload page
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: cbl
Date: 2016/1/6
Time: 15:34
To change this template use File | Settings | File Templates.
--%>
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Login</title>
</head>
<body>
<h1>${message}</h1>
<form method = "POST" action = "/login">
<label for="username">Username</label>
<input id="username" type="text" name = "username">
<label for="password">Password</label>
<input id="password"type="password" name="password">
<input type="submit" value="login">
</form>
</body>
</html>
The ${message} is extected to be display within body, however, it is appended after URl:http://localhost:8000/login?message=login+failed and http://localhost:8000/index?message=login+successful++
Any response is appreciated
Since you are returning a redirect, a new GET request is created under the covers, that is why is getting attached to the url.
If you want to keep the data in the model only, you can use the flash scope with RedirectAttributes
#RequestMapping(value = "/login" , method= RequestMethod.POST)
public String loginPost(HttpSession session,
RedirectAttributes ra,
#RequestParam(value = "username") String username,
#RequestParam(value = "password") String password) throws Exception {
User user = getUser(username, password);
if(user !=null){
session.setAttribute("username",username);
ra.addFlashAttribute("message","login successful ");
return "redirect:/index";
}else{
ra.addFlashAttribute("message","login failed");
return "redirect:/login";
}
}

How to get QR code from id?

In my controller I have the following method:
import net.glxn.qrgen.QRCode;
import org.marcio.demospringboot.dao.FormationRepository;
import org.marcio.demospringboot.model.Formation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import java.io.ByteArrayOutputStream;
import java.util.Map;
#Controller
public class FormationController {
#Autowired
private FormationRepository formationRepository;
#RequestMapping (value="formation/qr/{id}", method = RequestMethod.GET)
public ResponseEntity<byte[]> qr(#PathVariable final Long id) {
ByteArrayOutputStream stream = QRCode.from(formationRepository.findOne(id).toString()).stream();
byte[] bytes = stream.toByteArray();
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
return new ResponseEntity<byte[]> (bytes, headers, HttpStatus.CREATED);
}
}
In my html page:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>QR Code</title>
</head>
<body>
<img th:src="#{/formation/qr/${id}}" />
</body>
</html>
This is the generated image:
I want to get user data from your "id". I am using a simple repository Spring formationRepository and the library net.glxn.qrgen.QRCode.The application works, but not generate the QR code with the user data regarding the "id". Thanks.
Forgot '/' #RequestMapping (value="/formation/qr/{id}", method = RequestMethod.GET) before formation
EDIT:
ByteArrayOutputStream stream = QRCode.from(formationRepository.findOne(id).toString()).stream();
byte[] data = stream.toByteArray();;
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_JPEG);
headers.setContentLength(data.length);
return new HttpEntity<byte[]>(data, headers);
This should work in order so the browser will understand it is an image and will show it
Thank you for your help and comments. They were all very helpful. I could solve the problem by upgrading to:
#RequestMapping (value="/formation/qr/{id}", method = RequestMethod.GET)
public HttpEntity<byte[]> qr(#PathVariable Long id) {
byte[] bytes = QRCode.from(formationRepository.findOne(id).getTheme()
.toString()).withSize(120, 120).stream().toByteArray();
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
headers.setContentLength(bytes.length);
return new ResponseEntity<byte[]> (bytes, headers, HttpStatus.CREATED);
}
The solution was byte []bytes = QRCode.from(formation Repository.findOne (id).getTheme(). So I got the registration content (getTheme) and presents it in QR code.

Getting error when submitting form using SpringMVC and REST

Created an online form in JSP using SpringMVC tag libraries. The controller for my form is a RESTful web service.
The RESTful web service has two calls:
(1) http://localhost:8080/myapp/applications/new
This brings up the online form in the browser (this works).
(2) http://localhost:8080/myapp/applications/create
This saves the form data to a database (handles submit). This is where it breaks.
Followed the conventions from the sample demo petclinic app which comes with the Spring Framework.
Online form:
<%# page contentType="text/html;charset=UTF-8" language="java"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<body>
<form:form modelAttribute="application" method="POST" action="create">
<table>
<tr>
<td>Name:</td>
<td><form:input path="name" size="30" maxlength="80"/></td>
</tr>
<tr>
<td>Description:</td>
<td><form:input path="description" size="30" maxlength="80"/></td>
</tr>
<tr>
<td>Image URL:</td>
<td><form:input path="imgUrl" size="30" maxlength="80"/></td>
</tr>
</table>
<input type="submit" value="Save" />
</form:form>
</body>
</html>
The RESTful web service which serves as form controller:
#Controller
#Path(ApplicationsResource.APPLICATION_URL)
public class ApplicationsResource
{
private final Logger log =
LoggerFactory.getLogger(ApplicationsResource.class);
public static final String APPLICATION_URL = "/applications";
#Autowired
private ApplicationManager applicationManager;
#Autowired
private ProfileManager profileManager;
#POST
#Path("create")
#Produces(MediaType.TEXT_HTML)
public Model getNewApplication(#Context HttpServletRequest request,
#RequestAttribute Model model)
{
Application app = new Application();
model.addAttribute("application", app);
try
{
if ("POST".equalsIgnoreCase(request.getMethod()))
{
if (app != null)
{
applicationManager.save(app);
log.info("Added application: " + app.getName());
}
else
{
log.info("Application not added");
}
}
}
catch (Exception e)
{
log.info("Exception: ", e);
throw new
WebApplicationException(Response.status(
RestError.SERVER_ERROR_HTTP_RESP).
type("application/json;charset=utf-8").
entity(new ErrorOutput(RestError.SERVER_ERROR_CODE, RestError.SERVER_ERROR_MSG, e.toString())).build());
}
return model;
}
#InitBinder
public void setAllowedFields(WebDataBinder dataBinder)
{
dataBinder.setDisallowedFields(new String[] {"id"});
}
#GET
#Path("new")
#Produces( { MediaType.TEXT_HTML })
public ModelAndView getNewApplicationForm()
{
log.info("ApplicationsResource - Inside getNewApplicationForm");
ModelAndView mv = new ModelAndView("/applications/applications_new");
mv.addObject("application", new Application());
return mv;
}
}
Exception thrown when I click on submit:
Failed executing POST /applications/create
org.jboss.resteasy.spi.BadRequestException:
Could not find message body reader for type:
interface org.springframework.ui.Model of content type:
application/x-www-form-urlencoded at
org.jboss.resteasy.core.MessageBodyParameterInjector$1
createReaderNotFound(MessageBodyParameterInjector.java:73)
Does anyone know why I am getting this exception?
Would really appreciate it if someone could help me with this issue...
Happy programming and thank you for taking the time to read this.
It was a RESTEasy problem... The fix was putting the #Form Application App inside the parameter list and prepending the domain model object's setters with #FormParam("name").
See: Integrating RESTEasy with SpringMVC
You haven't told your controller what mime types it accepts and how to map them, it needs a Reader associated with that mime type to map it and send it into your method.

Resources