Spring MVC - #RequestMapping GET and POST #RequestMethod - spring

I understand this question has been asked previously, I am learning Spring following along Spring Petclinic Sample project. There is no problem with processCreationForm, when a redirect is done to showOwner using GET it works as expected, but when I experiment it by using POST it throws HTTP Status 405 - Request method 'GET' not supported. Is it because processCreationForm is doing a redirect to showOwner I am unable to grab it as POST request?
#RequestMapping(value = "/owners/new", method = RequestMethod.POST)
public String processCreationForm(#Valid Owner owner,
BindingResult result) {
if(result.hasErrors()) {
return "owners/ownerForm";
} else {
this.clinicService.saveOwner(owner);
return "redirect:/owners/" + owner.getId();
}
}
#RequestMapping(value = "/owners/{ownerId}", method = RequestMethod.POST)
public ModelAndView showOwner(#PathVariable("ownerId") int ownerId) {
ModelAndView mav = new ModelAndView("owners/ownerDetails");
mav.addObject(this.clinicService.findOwnerById(ownerId));
return mav;
}
Any helpful comments are appreciated.

You're redirecting to /owners/{ownerId} url, but you didn't define a GET handler for that endpoint, hence Spring MVC complains with:
HTTP Status 405 - Request method 'GET' not supported.
Using RequestMethod.GET will solve your problem:
#RequestMapping(value = "/owners/{ownerId}", method = RequestMethod.GET)
public ModelAndView showOwner(#PathVariable("ownerId") int ownerId) { ... }
Is it because processCreationForm is doing a redirect to showOwner I
am unable to grab it as POST request?
Since your POST handler on /owners/new is redirecting to /owners/{ownerId}, does not mean that redirection will be a POST request. Redirections are always GET requests.

Related

Spring MVC - Stop redirect in Controller function

I have a Spring MVC Controller and a PUT mapping that consumes JSON. I receive the JSON and everything just fine, the problem is whenever I fire off the JSON the mapper wants to redirect to the URL, giving me error 500 because the server can't find any template for the URL. How can I stop Spring MVC from trying to redirect to the URL and just receive the JSON?
My relevant Controller code :
#RequestMapping(value = "admin/users/VMs", method = RequestMethod.PUT, consumes = "application/json")
public void removeVM(#RequestBody ManageVMRequest packet, Authentication authentication) {
System.out.println(packet.getVm());
System.out.println(packet.getUser_id());
}
You can try to return ResponseEntity<Void>
#RequestMapping(value = "admin/users/VMs", method = RequestMethod.PUT, consumes = "application/json")
public #ResponseBody ResponseEntity<Void> removeVM(#RequestBody ManageVMRequest packet, Authentication authentication) {
System.out.println(packet.getVm());
System.out.println(packet.getUser_id());
return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
}

Spring WebFlux + thymeleaf: Post request redirect Get page returns the 303 see other status

I just used SpringBoot + WebFlux + thymeleaf to write the controller.
#RequestMapping(value = "/create", method = RequestMethod.GET)
public String createCityForm(Model model) {
model.addAttribute("city", new City());
model.addAttribute("action", "create");
return CITY_FORM_PATH_NAME;
}
#RequestMapping(value = "/create", method = RequestMethod.POST)
public String postCity(#ModelAttribute City city) {
cityService.saveCity(city);
return REDIRECT_TO_CITY_URL;
}
I witre thymeleaf page to receive the form, and redirect/return the get method page, But the browser give the 303 see other status.
Also, the delete resources also doesn't work.
The SEE_OTHER status is actually the default status of the RedirectView when invoked without explicitly specifying the HTTP code (like the ThymeleafReactiveViewResolver does).
If you want to override this status, return the RedirectView directly instead of letting Thymeleaf do it when it matches the redirect: pattern in the view name:
#RequestMapping(value = "/create", method = RequestMethod.GET)
public RedirectView createCityForm(Model model) {
model.addAttribute("city", new City());
model.addAttribute("action", "create");
return new RedirectView("/target_url", HttpStatus.MOVED_PERMANENTLY);
}

"org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported" Request method 'POST' not supported

I am using angular JS and Spring MVC+Spring Security in my application. When using $http like below:
$http.post('/abc/xyz/'+catalogId);
it is giving below error:
org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported
WARNING: Request method 'POST' not supported.
Moreover I've put POST in my controller as well:
#RequestMapping(value = "/xyz/{catalogId}", method = RequestMethod.POST)
public #ResponseBody List<Category> getCategorybyCatalogId(#PathVariable(value = "catalogId") long catalogId, ModelMap modelMap,
HttpSession session) throws IOException {
if (catalogId != 0) {
return menuService.getCategorybyCatalogId(catalogId);
} else {
return null;
}
}
this problem started coming when I added spring security config class.
Please help!!

Adding #ModelAttribute results in 400 (Bad Request) in Delete Request

I can submit a delete request fine with the following:
#RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public ResponseEntity<Result> deleteTest(#PathVariable String id) {
return new ResponseEntity<>(Result.Success("Hi " + id + "!!!", null), HttpStatus.OK);
}
However, when I add an #ModelAttribute variable, I get 400 (Bad Request) as the http response code:
#RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public ResponseEntity<Result> deleteTest(#PathVariable String id, #ModelAttribute("authUser") User authUser) {
return new ResponseEntity<>(Result.Success("Hi " + id + "!!!", null), HttpStatus.OK);
}
This #ModelAttribute is working fine with a put request handler I have in my #RestController but not in this delete request.
Here's the #ModelAttribute code:
#ModelAttribute("authUser")
public User authUser(#AuthenticationPrincipal SpringAuthUser springAuthUser) throws Exception {
User user = ConstantsHome.userprofileMgr.getUserByUserId(springAuthUser.getUsername(), true, true);
user.updateRights(null);
request.getSession().setAttribute(ConstantsHome.USEROBJECT_KEY, user);
return user;
}
Why would adding #ModelAttribute cause a delete request to return a 400 (Bad Request) http response?
I'm using spring-web-4.1.4 & spring-security-4.0.3
I digged a little and found that specifying a #PathVariable of "id" somehow attaches it to the #ModelAttribute variable (as a Long(!) instead of a String as I specified). I then came across this post that lead me to different ways to resolve the issue :
Values of #PathVariable and #ModelAttribute overlapping.
Ended up with this as a method declaration (replaced "id" with "userId"):
#RequestMapping(value = "/{userId}", method = RequestMethod.DELETE)
public ResponseEntity<Result> deleteUser(#PathVariable String userId,
#ModelAttribute("authUser") User authUser) {
...
}
Hopefully this will help someone else quickly that might run into this issue instead of spending a day trying to figure it out...

get error HTTP Status 405 for rest web service POST method

I load at browser as
localhost:8080/picking/addPick get error HTTP Status 405 - Request method 'GET' not supported.
What wrong?Hope advice thanks
#Controller
#RequestMapping("/picking")
public class PickerController {
#RequestMapping(method = RequestMethod.GET)
public #ResponseBody ArrayList getAllPickingItems()throws SQLException, ClassNotFoundException{
//....
}
#RequestMapping(value="/addPick",method=RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public Boolean add(#RequestBody PickingInfo pickingInfo,HttpServletResponse response){
try{
Boolean success = pickerMethod.addPickingInfo(pickingInfo);
response.setHeader("addPickingInfo", success+"");
return true;
}catch(Exception ex){
System.out.println(ex.getMessage());
}
return false;
}
}
You limited URI/picking/addPick to POST requests :
#RequestMapping(value="/addPick",method=RequestMethod.POST)
When you try to open that URI from your browser you're sending a GET request, not a POST. If you want to be able to access /picking/addPick from your browser you must either :
remove the restriction method=RequestMethod.POST
allow explicitely GET requests : method = { RequestMethod.POST, RequestMethod.GET }
If you just want to test a POST method, use SoapUI. Simply create a "New REST Project", paste your service URI, and send any type of HTTP Request you want.
You have mapped /addPick to the add method only for POST requests. Therefor GET is not mapped to anything (and in this case there is no point in mapping get to the method since you are also using #RequestBody)

Resources