Thymeleaf provide null in controller - spring

I want to deliver the entire object from html to the controller
Controller:
#RequestMapping(method = RequestMethod.GET)
public String get(){
Info info = new Info();
info.setTitle("Hello");
model.addAttribute("infos", Collections.singleton(info));
return "info-page";
}
#RequestMapping(method = RequestMethod.POST, value = "show-all")
public String showAllInfoObject(#ModelAttribute("info") Info info){
// info has null values!
}
HTML
<li th:each="info : ${infos}">
<span th:text="${info.title}">webTitle</span>.
<form th:action="#{'/show-all}" method="post">
<input type="hidden" name="result" th:field="*{info}" />
<input type="submit" value="show detalis" />
</form>
</li>
However, the controller gets an empty object.
Interestingly, when I provide only String "title", it gets the correct result in the controller.
How to deliver correctly the whole object from HTML?

The problem is that th:field replaces the attributes value, id, and name in the input tag.
I would rewrite the HTML code as something like this:
<ul>
<li th:each="info : ${infos}">
<span th:text="${info.title}"></span>
<form th:action="#{/show-all}" method="post" >
<input type="hidden" th:value="${info.title}" name="title" id="title" />
<input type="submit" value="show detalis" />
</form>
</li>
</ul>
So, setting the input name and id with "title", the controller will make the bind as expected.
The controller code remains the same but I will leave here the test that I did.
#RequestMapping(method = RequestMethod.GET)
public String get(Model model){
Info info = new Info();
info.setTitle("Hello");
Info info2 = new Info();
info2.setTitle("Hello2");
model.addAttribute("infos", Arrays.asList(info, info2));
return "info-page";
}
#RequestMapping(method = RequestMethod.POST, value = "show-all")
public String showAllInfoObject(#ModelAttribute("info") Info info){
// info has values!
return "info-page";
}
Hope it helps you.

Related

how to resolve Request method 'GET' not supported

I am getting below warning as
WARN [org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver] (default task-1) Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported]
I have already set the method as POST but still I'm getting the above error. I'm getting this warning message for my delete controller all other CRUD operations are working fine, except delete.
Please find below code
Controller mapped deleteproducts :
#RequestMapping(value="/deleteproducts", method= RequestMethod.POST)
public String deleteProduct(#PathVariable("productId")int productId) {
IProductsDAO ip = new ProductsDAOImpl();
boolean b = ip.deleteProduct(productId);
if(b)
return "success";
else
return "deleteproducts";
here's my jsp view:
<body>
<form id="update product form" action="${pageContext.request.contextPath}/deleteproducts" method="post" role="form" style="display: none;">
<div class="form-group row">
<label for="product Id" class="col-sm-2 col-form-label">Id</label>
<div class="col-sm-10">
<input type="text" name="productId" class="form-control" id="productid" placeholder="Enter the product Id you want to delete">
</div>
</div>
</form>
</body>
DAOimplementation for delete Method call:
public boolean deleteProduct(int productId)
{
boolean b = true;
try
{
sess.beginTransaction();
Products p = (Products)sess.load(Products.class, new Integer(productId));
sess.delete(p);
sess.getTransaction().commit();
}catch(Exception ex)
{
sess.getTransaction().rollback();
b = false;
}
return b;
}
can some one now tell me what changes should I make in my code to fix this ?
Thank you!
edit 1:
#DeleteMapping(value="/deleteproducts/{productId}")
public String deleteProduct(#PathVariable("productId")int productId) {
IProductsDAO ip = new ProductsDAOImpl();
boolean b = ip.deleteProduct(productId);
if(b)
return "success";
else
return "deleteproducts";
}
still getting a warning as:
WARN [org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver] (default task-1) Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported]
I don't understand #RequestMapping(value="/deleteproducts", method= RequestMethod.POST)
what do you mean by this? You are making a RequestMapping want to delete a record and method is POST?
I would suggest please follow the standard way of development. If you want to delete DeleteMapping, for POST use PostMapping and to retrieve some information you can use GetMapping.
Ideally, it should be
#DeleteMapping("/deleteproducts/{id}")
public void deleteStudent(#PathVariable long id) {
deleteproductsRepository.deleteById(id); or some CRUD logic to delete
}
You can refer to this link for better understanding REST
AS i think request form going to GET Method you can try javascript to submit form with function call.
Please find below code :
<form id="update product form" action="${pageContext.request.contextPath}/deleteproducts" method="POST">
<div class="form-group row">
<label for="product Id" class="col-sm-2 col-form-label">Id</label>
<div class="col-sm-10">
<input type="text" name="productId" class="form-control" id="productid" placeholder="Enter the product Id you want to delete">
</div>
<div class="col-sm-10">
<input type="button" value="submit" onclick="javascript:formSubmit()" name="submit" ></a>
</div>
</div>
</form>
<script>
function formSubmit() {
if(!isEmpty(document.from.productId.value)){ //even you can validate values in productId
document.form.method='POST';
document.form.action='/deleteproducts';
document.form.submit();
}
)
<script>
After writing the below code
#DeleteMapping(value="/deleteproducts/{productId}")
public String deleteProduct(#PathVariable("productId")int productId) {
IProductsDAO ip = new ProductsDAOImpl();
boolean b = ip.deleteProduct(productId);
if(b)
return "success";
else
return "deleteproducts";
}
After this instead of running on a normal browser, try running it on a REST API. I tried it on POSTMAN API and I don't get the error. Look at the below image

Spring Boot ModelAndView - cannot update value to Model

I am trying to create a form with 3 fields within the class LoginForm: usuario, senha, msgLogin.
I receive the fields usuário and senha from the input boxes and then I try to redirect to the same page with the same fields plus the field MsgLogin. But I've not been able to update the msgLogin field and I don't understand why.
These are the code:
HTML:
<form id="frmLogin" class="form col-md-12" action="#" th:action="#{/login}" th:object="${loginForm}" method="post">
<div class="form-group">
<label for="usuario" class="col-md-1">Usuário: </label>
<input type="text" id="usuario" placeholder="Email" th:field="*{usuario}"/>
</div>
<div class="form-group">
<label for="senha" class="col-md-1">Senha: </label>
<input type="password" id="senha" placeholder="senha" th:field="*{senha}"/>
</div>
<div class="row">
<button id="entrar">Entrar</button>
</div>
<div class="row">
<div id="msgLogin"></div>
<p th:text="${loginForm.msgLogin}" />
</div>
</form>
The Controller:
#RequestMapping("/")
public String init(#ModelAttribute LoginForm loginForm) {
Logger.getAnonymousLogger().info("Tela Inicial.");
return "home";
}
#PostMapping("/login")
public ModelAndView entrar(LoginForm loginForm) throws IOException {
Logger.getAnonymousLogger().info("Entrando no Internet Banking.");
service.login(usuario, senha);
ModelMap model = new ModelMap();
loginForm.setMsgLogin("I want to update that value!");
model.addAttribute("loginForm", loginForm);
return new ModelAndView("redirect:/", model);
}
Class using Lombok:
#Getter
#Setter
public class LoginForm {
private String usuario;
private String senha;
private String msgLogin;
}
A redirect send a 302 HTTP status back to the browser to resubmit using a new url, so it resubmits the same two fields to the new url. There's no expectation of payload data in the 302 response.
In your Controller, change the last line in your entrar method to: return new ModelAndView("/login", model);

how to pass checkbox value from jsp to java class

I have in my jsp page some checkbox and I want to pass in my spring controller the checked ones.
insertTaskInformation.jsp
<body>
<div align="center">
<strong> <strong>Title:</strong>${task.title} <form:form
action="addSymbol" method="post" name="catch">
<c:forEach var="symbol" items="${symbols}">
<input type="checkbox" name="id" value="${symbol.type} }">${symbol.type}<BR>
</c:forEach>
<input type="submit" value="Submit">
</form:form>
</strong>
</div>
</body>
taksController.java
#RequestMapping(value="/addSymbol", method = RequestMethod.POST)
public String addSymbol() {
return "administration/taskRecap";
}
You can use spspring:form library and you add in your controller something like this :
#PostMapping("/greeting")
public String greetingSubmit(#ModelAttribute Greeting greeting) {
return "result";
}
And In your first controller, you add an attribute to the model with model.addAttribute(new greeting() ) so the full code will be
#RequestMapping(value="/addSymbol", method = RequestMethod.POST)
public String addSymbol(Model model) {
model.addAttribute(new greeting() )
return "administration/taskRecap";
}
For more information check here

Spring MVC validation errors are not displayed in Freemarker template

I'm trying to display validation errors in a 'user registration' page built with freemarker template if a controller returns binding errors.
My controller's code is as follows:
#Controller
#RequestMapping("/")
public class UserController {
#Autowired
private UserService userService;
#Autowired
private SecurityService securityService;
#Autowired
private UserValidator userValidator;
#RequestMapping(value = "/registration", method = RequestMethod.GET)
public String registration(Model model) {
model.addAttribute("userForm", new User());
return "registration";
}
#RequestMapping(value = "/registration", method = RequestMethod.POST)
public String registration(#ModelAttribute("useraccount") User userForm, BindingResult bindingResult, Model model) {
userValidator.validate(userForm, bindingResult);
if (bindingResult.hasErrors()) {
return "registration";
}
userService.save(userForm);
securityService.autologin(userForm.getUsername(), userForm.getPasswordConfirm());
return "redirect:/explore";
}
while this is the registration.ftl freemarker template I am trying to build :
<div>
<fieldset>
<h1>Create your Account</h1>
<form id="regForm" class="idealform" action="registration" method="post" name='useraccount'>
Username: <input type="text" name="username" /> <errors path="username" cssClass="error"/><br/>
Password: <input type="text" name="password" /><errors path="password" cssClass="error"/><br/>
<label class="main-label" style="width: 91px;"> </label>
<input type="submit" value="submit">
</form>
</fieldset>
I tried also the solution recommended here:
Displaying Spring MVC validation errors in Freemarker templates
and the registration.ftl becomes:
<#assign form=JspTaglibs["http://www.springframework.org/tags/form"] />
<#macro formErrors>
<#assign formErrors><#form.errors path="*" /></#assign>
<#if formErrors?has_content>
<div id="errors">
<#spring.message "admin.error.globalMessage" />
</div>
</#if>
</#macro>
<div>
<fieldset>
<h1>Create your Account</h1>
<#form.form id="regForm" class="idealform" action="registration" method="post" name='useraccount'>
Username: <input type="text" name="username" path="username" /> <br/>
Password: <input type="text" name="password" path="password" /><br/>
<#formErrors />
<label class="main-label" style="width: 91px;"> </label>
<input type="submit" value="submit">
</#form.form>
</fieldset>
</div>
but still the validation messages are not displayed.
Could you share your thoughts with me on this issue?
Thank you very much.
I rewrote your controller code to something like this:
#Controller
#RequestMapping("/")
public class UserController {
#Autowired
private UserService userService;
#Autowired
private SecurityService securityService;
#Autowired
private UserValidator userValidator;
#RequestMapping(value = "/registration", method = RequestMethod.GET)
public String registration(#ModelAttribute(name = "userForm") User user) {
return "registration";
}
#RequestMapping(value = "/registration", method = RequestMethod.POST)
public String registration(#ModelAttribute(name = "userForm") User user, BindingResult result) {
userValidator.validate(user, result);
if (result.hasErrors()) {
return "registration";
}
userService.save(user);
securityService.autologin(user.getUsername(), user.getPasswordConfirm());
return "redirect:/explore";
}
}
1) There is no need to use model.addAttribute("modelName", model) if you use a constructor without arguments, instead you can use a #ModelAttribute annotation specifying the name attribute (by default the name goes from the class name). You only have to be sure that this model is in a consistent state. Also you need to pass the name exactly the same as you use in your view (freemarker template).
Now "registration.ftl"
...
<#import "/spring.ftl" as spring/>
...
<fieldset>
<h1>Create your Account</h1>
<form id="regForm" class="idealform" action="<#spring.url '/registration'/>" method="post">
<#spring.bind 'userForm.username'/>
Username: <input type="text" name="${spring.status.expression}" value="${spring.status.value?html}"/>
<#list spring.status.errorMessages as error>
<span class="error">${error}</span>
<br>
</#list>
<#spring.bind 'userForm.password'/>
Password: <input type="password" name="${spring.status.expression}" value="${spring.status.value?html}"/>
<#list spring.status.errorMessages as error>
<span class="error">${error}</span>
<br>
</#list>
<label class="main-label" style="width: 91px;"> </label>
<input type="submit" value="submit">
</form>
</fieldset>
...
1)You need <#import "/spring.ftl" as spring/> in order to add spring's user-defined directives that are pretty useful.
2)Use <#spring.bind 'userForm.username'> directive to bind following input to your model. Here "userForm" is your model and "username" is a field that you want to bind. This directive also declares new variable "spring.status" that contains an "expression" variable - for a path, a "value" - to populate the form in case it's returned with errors, and "errorMessages" from BindingResult.
3)If you use a message source to support different languages you should change <span class="error">${error}</span> to something like <#spring.message '${error}'/> otherwise you'll get just message codes.
Hope it helps.

Passing parameters from JSP to controller - Spring MVC

I have a little problem when I want to pass parameter to my controller.
I have one method in controller:
#RequestMapping("/redirect")
public String print(String type, HttpServletRequest servletRequest)
{
String path = "redirect:" + servletRequest.getParameter("type");
return path;
}
And I have some buttons in my jsp file:
<form method="post" action="/WWP/redirect">
<button onclick=" <input type="text" name="type" value="/developer"/>">Developer</button>
<button onclick=<input type="text" name="type" value="/graphic"/>>Graphic</button>
<button onclick=" <input type="text" name="type" value="/cleaner"/>">Cleaner</button>
</form>
In this way I have 3 buttons and when for example I press Developer button variable "type" is "/developer" and I'm sending it to controller. But now my buttons look like this:
http://imageshack.us/photo/my-images/854/buttonspx.png/
It works correct, but I can't get rid this HTML tag and it's really nervous. How to do this? Or how send value to controller in different way. Thanks in advance.
Instead of normal buttons you can have submit buttons and handle them in controller as below
<input type="submit" value="Developer" name="developer"></input>
<input type="submit" value="Graphic" name="graphic"></input>
<input type="submit" value="Cleaner" name="cleaner"></input>
And you can have different methods in the controller class for each of the buttons clicked using the params attribute like this
#RequestMapping(value = "/redirect", method = {RequestMethod.POST}, params = "developer")
public ModelAndView developerMethod(){
}
#RequestMapping(value = "/redirect", method = {RequestMethod.POST}, params = "graphic")
public ModelAndView graphicMethod(){
}
#RequestMapping(value = "/redirect", method = {RequestMethod.POST}, params = "cleaner")
public ModelAndView cleanerMethod(){
}

Resources