How to deal with error "Request method 'GET' not supported" - spring

I would like to implement deletion of a entity from a list view. And I faced this problem. Can you explain me, what is the problem and how can I ovrcome it?
The controller method:
#RequestMapping(value = "/deleteComment/{commentId}", method = RequestMethod.POST)
public String deleteComment(#PathVariable int commentId, BindingResult result, Model model){
{
Comment deletedComment = commentService.findCommentByID(commentId);
if (deletedComment != null) {
commentService.deleteComment(deletedComment);
}
return "refresh:";
}
Do I need to specify 'Get' method, if I'm dealing with list-view (and I see the whole list). If I need, what code should I place there. I have no any ideas...

The problem is in button type attribute.
If You have HTML button type="submit" then Your service can be only RequestMethod.GET. When You change to RequestMethod.POST then You have "Request method 'GET' not supported".
SOLUTION: Change attribute in button tag to type="button".

By specifying method = RequestMethod.POST you are essentially saying that the deleteComment method should be called only for POST and for a path /deleteComment/{commentId}. If you want it to accept requests for GET also, you can just remove the method or accept GET also this way:
#RequestMapping(value = "/deleteComment/{commentId}", method = {RequestMethod.POST, RequestMethod.GET})
You may also want to explicitly specify the name of the variable to bind to the commentId path variable this way:
public String deleteComment(#PathVariable("commentId") int commentId, BindingResult result, Model model){

Related

FlashAttributes not in model after redirect

I have this controller method:
#GetMapping("/notations")
public String listAll(Model model) {
Iterable<PriceNotation> allItems = loadAllNotations();
model.addAttribute("notations", allItems);
return "supply/notations";
}
Then I have this method which redirects to the one above:
#GetMapping(value = "/notations/delete")
public String delete(#RequestParam(name="id", required=true) Long id, RedirectAttributes redirectAttributes)
{
try {
notationRepository.deleteById(id);
} catch (RuntimeException e) {
redirectAttributes.addFlashAttribute("message", "delete failed");
}
return "redirect:/notations";
}
When I put a breakpoint in the first method after a redirect, the model is empty. Although the documentation says:
After the redirect, flash attributes are automatically added to the
model of the controller that serves the target URL.
Also in my html page I have this header which should display the message:
<h2 th:text="${message}"></h2>
Also this header is empty. What am I missing?
PS, I know this question has been asked before but there was no accepted answer and none of the suggestions worked for me.
they are not added to model as they are passed as query parameters like example.com?message=abc.
So you can either:
access them in controller with #RequestParam and then add to your model
OR access them in thymeleaf with ${#param.message[0]}
in summary you should treat redirectAttributes as reqular query parameters in receiving controller (listAll).

views in thymeleaf spring boot templates sub folder

I am using thymeleaf in spring boot, and have several views. I don't want to keep all the views in the same folder which is src/main/resources/templates by default.
Is it possible to move some of the view in src/main/resources/templates/folder1, and I will pass "folder1/viewname" to access that page?
When I tried http://localhost:8080/folder1/layout1 it didn't found my html in src/main/resources/templates/folder1/, but when I move the html in templates main folder src/main/resources/templates/, http://localhost:8080/layout1 worked fine.
My controller class looks like:
#RequestMapping(value = "{pagename}", method = RequestMethod.GET)
public String mf42_layout1(#PathVariable String pagename) {
return pagename;
}
So, I thought if I pass layout1, it will look int the templates, and if I say "a/layout1", it will look in /layout folder
Thanks,
Manish
Basically, your request mapping and the name of your view are decoupled, you just need to pay attention to the syntax.
For instance, with
#RequestMapping(value = "/foobar", method = RequestMethod.GET)
public String mf42_layout1() {
return "layout1";
}
a request to http://localhost:8080/foobar will render the template located in src/main/resources/templates/layout1.html.
It also works if you put your templates on a subfolder, as long as you provide the correct path to the view:
#RequestMapping(value = "/foobar", method = RequestMethod.GET)
public String mf42_layout1() {
return "a/layout1";
}
A request to http://localhost:8080/foobar will render the template located in src/main/resources/templates/a/layout1.html.
You can also parameterized the url endpoint with #PathVariable:
#RequestMapping(value = "/foobar/{layout}", method = RequestMethod.GET)
public String mf42_layout1(#PathVariable(value = "layout") String layout) { // I prefer binding to the variable name explicitely
return "a/" + layout;
}
Now a request to http://localhost:8080/foobar/layout1 will render the template in src/main/resources/templates/a/layout1.html and a request to http://localhost:8080/foobar/layout2 will render what's in src/main/resources/templates/a/layout2.html
But beware the forward slash acts as a separator in URLs, so with your controller:
#RequestMapping(value = "{pagename}", method = RequestMethod.GET)
public String mf42_layout1(#PathVariable String pagename) {
return pagename;
}
My guess is when you hit http://localhost:8080/a/layout1 pagename receives "a" and "layout1" is not caught. So the controller probably tries to render the contents of src/main/resources/templates/a.html
The Spring MVC reference extensively describes how to map requests, you should read it carefully.
I faced similar template not found issue when running the application in a Linux server. I was using the path as "return "/a/layout1". This worked fine in a local windows PC, but I had to remove the starting "/" to make it work in a Linux box(i.e. "return "a/layout1").

Why I can't redirect from a Spring MVC controller method to another controller method?

I am pretty new in Spring MVC and I have some problem trying to redirect to a controller method after that another controller method terminate its execution.
So I have the following situation. Into a controller class I have this method that correctly handle POST request toward the validaProgetti resource:
#RequestMapping(value = "validaProgetti", method=RequestMethod.POST)
public #ResponseBody String validaProgetti(#RequestBody List<Integer> checkedRowList) {
System.out.println("ID progetti da aggiornare: " + checkedRowList);
List<Twp1007Progetto> progettiDaValidare = new ArrayList<Twp1007Progetto>();
for (int i=0; i<checkedRowList.size(); i++) {
System.out.println("ID PROGETTO: " + checkedRowList.get(i));
progettiDaValidare.add(progettoService.getProgetto(checkedRowList.get(i)));
}
progettoService.validaProgetti(progettiDaValidare);
return "redirect:ricercaValidazione";
}
So this method is correctly mapped and when the validaProgetti resource is called it is executed.
At the end of this method I don't return a view name that render a JSP page but I have to redirect to another method (that do something and render a JSP page). So, instead to return a view name, I redirect toward another resource:
return "redirect:ricercaValidazione";
Then in the same controller class I have declared this method that handle request toward this ricercaValidazione resource:
#RequestMapping(value = "ricercaValidazione", method=RequestMethod.POST)
public String ricercaValidazione(#ModelAttribute ConsultazioneFilter consultazioneFilter, Model model, HttpServletRequest request) {
RicercaConsultazioneViewObject filtro = null;
try {
filtro = new ObjectMapper().readValue(request.getParameter("filtro"), RicercaConsultazioneViewObject.class);
filtro.setSelStatoProgetto(3); // Progetti da validare
} catch (IOException e) {
logger.error(e);
}
consultazioneFilter = new ConsultazioneFilter(filtro);
model.addAttribute("consultazioneFilter", consultazioneFilter);
model.addAttribute("listaProgetti", new ListViewObject<Twp1007Progetto>(progettoService.getListaProgettiConsultazione(consultazioneFilter)) );
return "validazione/tabellaRisultati";
}
The problem is that it can't work and after the redirection can't enter into the ricercaValidazione() method.
I think that maybe the problem is that this ricercaValidazione() method handle POST request toward the ricercaValidazione resource and the return "redirect:ricercaValidazione"; maybe generate a GET request.
But I am not sure about it.
Why? What am I missing? How can I solve this issue?
Tnx
the redirect and fordward prefix are for resolving views; you are tring to redirect from one controller to another one. This can be done but redirect works in the following way
A response is sent to the browser with the redirect http status code and and url
The browser loads via GET the request URL
Your Spring controller (and the corresponding ammping method) is invocated if it matches the annotation params
From what you write I'm not sure this is what you really want; as you already noted there is a mismatch between HTTP methods (GET vs POST).
Your second method ricercaValidazione expects a filtro param in order to filter some data, but in the validaProgetti there is nothing similar, so it seems that the two controllers are not directly chainable. If what you want is to display a page after validaProgetti that shows a form and the the user can submit it you must add a method annotated with a method GET and url ricercaValidazione; the new method must return the view containing the form; which points via POST to url of validaProgetti. In this way you can redirect from ricercaValidazione to validaProgetti
Give mapping name of your controller with redirect like
redirect:/controll-mapping_name/ricercaValidazione
have a look on this question
Unable to redirect from one controller to another controller-Spring MVC

How to get and post parameter from url

I got a page link like www.example.com/resetPassword?pass=33 and I can get this value from controller method with using #RequestParam method.
Problem is I also need this parameter(pass) value when I post this page(form).When I post below form url changes to www.example.com/resetPassword but I want also paramter as www.example.com/resetPassword?pass=33.Is there an easy way to achieve this?
Here is my form;
<form:form action="resetPassword.htm" role="form" method="POST">
....
</form:form>
My controller method;
#RequestMapping(value = "/resetPassword.htm*", method = {RequestMethod.GET, RequestMethod.POST})
public ModelAndView resetPassword(HttpServletRequest request, HttpServletResponse response, #RequestParam("pass") String pass){
if(request.getMethod().equals("GET")){
//
}
else if(request.getMethod().equals("POST")){
//
}
}
This is in general a bad idea. You are breaking restful convention.
The different request types normally have different behaviour, don;t try and combine them.

How are these params used in #RequestMapping

I have inherited code which I am trying to figure out.
I have a Controller class for registering a user with the following method
#RequestMapping(method = POST, params = {USERNAME_PARAM, "!" + EMAIL_PARAM})
public ModelAndView usernameRegister(#Valid RegisterWithUsernameParameter usernameParameter, ModelMap model)
Where USERNAME_PARAM = "username" and EMAIL_PARAM = "email". I also have this method:
#RequestMapping(method = POST, params = {EMAIL_PARAM, "!" + USERNAME_PARAM})
public ModelAndView emailRegister(#Valid AuthenticateWithEmailParameter emailParameter, ModelMap model)
My question is, what is the purpose of the "params = " ? I have removed and tested and I can't see any difference, it still works. Also what does "!" mean in this context?
Thanks!
params = {} attribute specifies additional conditions under which a particular method will be called.
usernameRegister() method will only be called if USERNAME_PARAM is present and EMAIL_PARAM is NOT present in the request.
emailRegister() method will only be called if EMAIL_PARAM is present and USERNAME_PARAM is NOT present in the request.
Some useful links:
Javadoc for params, Example using params attribute
Using 'params' we can narrow the request. And '!' negate the expression. So first method (userNameRegister) is looking for reuqets with USERNAME_PARAM but not EMAIL_PARAM whereas second one (emailRegister) is lookign for EMAIL_PARAM but not an USERNAME_PARAM

Resources