HTTP redirect: 301 (permanent) vs. 302 (temporary) in Spring - spring

I want to make a 301 redirect in Spring, So here the piece of code I use
#RequestMapping(value = { "/devices" } , method = RequestMethod.GET)
private String initGetForm(#ModelAttribute("searchForm") final SearchForm searchForm,
BindingResult result,
HttpServletRequest request,
HttpServletResponse response,
Model model, Locale locale) throws Exception {
String newUrl = "/devices/en";
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
response.setHeader("Location", newUrl);
response.setHeader("Connection", "close");
return "redirect:" + newUrl;
}
But checking the IE Developer Tools I got this Status 302 Moved Temporarily !

Spring is resetting your response headers when it handles the redirection since you are returning a logical view name with a special redirect prefix.If you want to manually set the headers handle the response yourself without using Spring view resolution. Change your code as follows
#RequestMapping(value = { "/devices" } , method = RequestMethod.GET)
private void initGetForm(#ModelAttribute("searchForm") final SearchForm searchForm,
BindingResult result,
HttpServletRequest request,
HttpServletResponse response,
Model model, Locale locale) throws Exception {
String newUrl = request.getContextPath() + "/devices/en";
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
response.setHeader("Location", newUrl);
response.setHeader("Connection", "close");
}

You can use RedirectView with TEMPORARY_REDIRECT status.
#RequestMapping(value = { "/devices" } , method = RequestMethod.GET)
private ModelAndView initGetForm(#ModelAttribute("searchForm") final SearchForm searchForm,
BindingResult result,
HttpServletRequest request,
HttpServletResponse response,
Model model, Locale locale) throws Exception {
....
RedirectView redirectView = new RedirectView(url);
redirectView.setStatusCode(HttpStatus.TEMPORARY_REDIRECT);
return new ModelAndView(redirectView);
}

Related

Spring ModelAndView Attribute is null

I have one simple controller and one interceptor.
Within interceptor in postHandle-method I am checking user.
Problem: My user-model is sometimes null, between controller-handles.
postHandle invoked by home-handle==> User-Model is not null
postHandle invoked by check_user-handle ==> User-model is null
postHandle invoked by redirectToErrorPage-handle ==> User-model is
not null anymore and contains everything, what i've expected by
check_user-PostHandle Invocation.
Here is my controller
#Controller
#SessionAttributes("user")
public class HomeController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView home(Model model, HttpServletRequest request, HttpSession session) {
User user = new User();
return new ModelAndView("login", "user", user);
////now User-Model was saved in the session
}
//now i'am redirectring user in the "check_user"-handle
#RequestMapping(value = "/check_user", method = RequestMethod.POST)
public ModelAndView checkUser(#Valid #ModelAttribute("user") User user, BindingResult bindingResult, Model model,
HttpServletRequest request, RedirectAttributes redirectAttr) {
RedirectView redirectView = null;
ModelAndView mav=null;
try {
if(!bindingResult.hasErrors()){
redirectView = new RedirectView("home");
redirectView.setStatusCode(HttpStatus.FOUND);
redirectAttr.addFlashAttribute("httpStatus", HttpStatus.FOUND);
mav = new ModelAndView(redirectView);
return mav; //at next i entry post-handle from interceptor,
//which says to me, that user-model is null.
}
}
//My interceptor redirects me to this handle.
//After this handle within interceptor method "postHandle", i see, that
//user-object exists
#RequestMapping(value = "/error", method = RequestMethod.GET)
public String redirectToErrorPage(HttpServletRequest request){
return "error";
}
}
And my Interceptor:
public class UserInterceptor extends HandlerInterceptorAdapter {
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
User user = (User) modelAndView.getModel().get("user");
if(user == null || !user.isAdmin()){
response.sendRedirect(request.getContextPath()+"/failed");
}
}
}
While I retrive, which keys my model has, when postHandle was invoked by "check_user", I have only one key "totalTime". Whats going on with my model?
Try modifying your postHandle() as below:
...
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
User user = (User) request.getSession().getAttribute("user");
...

Request method 'GET' not supported

Trying to redirect from controller method to another controller, facing below error
org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported
I have submitForm method in controller 1, once i call submit method it should call controller 2
Controller 1
#RequestMapping(method = RequestMethod.POST)
public ModelAndView submitForm(#ModelAttribute("loginForm") Login login, BindingResult errors, SessionStatus status, HttpServletRequest request, HttpServletResponse response) throws IOException {
return new ModelAndView("path2.sp");
}
Controller 2
#Controller
#RequestMapping("path2.sp")
public class DestinationController {
System.out.println("");
}
This is not the way to do redirection.
First, fix your #RequestMapping in Controller 2, like this:
#Controller
#RequestMapping("/path2")
public class DestinationController {
System.out.println("");
}
Now, in controller 1 just do this:
#RequestMapping(method = RequestMethod.POST)
public String submitForm(#ModelAttribute("loginForm") Login login, BindingResult errors, SessionStatus status, HttpServletRequest request, HttpServletResponse response) throws IOException {
return "redirect:/path2";
}

How do I extract client data from the httpheaders?

I have a login post request.
#RequestMapping(value = EWPRestContants.DO_LOGIN, method = RequestMethod.POST, consumes=MediaType.APPLICATION_XML_VALUE,produces=MediaType.TEXT_PLAIN_VALUE)
public ResponseEntity<String> doLogin(#RequestBody Loginrequest logReq,#RequestHeader HttpHeaders headers, HttpServletRequest request, HttpServletResponse httpResponse) throws Exception {
//........
}
I want to extract data from the header. Is there an API to do so?
Suppose my header contains customer msIsdn number and name. How do I fetch those details. getFirst() is used to get the user-agent details or the start line only.
This is the answer.
String id= headers.getFirst("ID");
like
#RequestHeader(value="User-Agent", defaultValue="foo") String userAgent
#RequestMapping(value = EWPRestContants.DO_LOGIN, method = RequestMethod.POST, consumes=MediaType.APPLICATION_XML_VALUE,produces=MediaType.TEXT_PLAIN_VALUE)
public ResponseEntity<String> doLogin(#RequestBody Loginrequest logReq,#RequestHeader(value="User-Agent", defaultValue="foo") String userAgent,#RequestHeader(value="Accept-Language") String acceptLanguage, HttpServletRequest request, HttpServletResponse httpResponse) throws Exception {
//........
}
or from
#RequestMapping(value = EWPRestContants.DO_LOGIN, method = RequestMethod.POST, consumes=MediaType.APPLICATION_XML_VALUE,produces=MediaType.TEXT_PLAIN_VALUE)
public ResponseEntity<String> doLogin(#RequestBody Loginrequest logReq,#RequestHeader HttpHeaders headers, HttpServletRequest request, HttpServletResponse httpResponse) throws Exception {
String userAgent = headers.getFirst(HttpHeaders.USER_AGENT);
}

Converting a responseEntity to httpServletResponse with spring

My controller method looks like this :
public void doLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
and I want to do this
ResponseEntity<String> responseEntity = restTemplate.postForEntity(testPrefix + "/login", map, String.class);
response = responseEntity;
or similar, basically make a restcall and return the HttpReponseEntity as the response n its enitirety
From updated comments I assume that you are wanting to return the result of the restTemplate.postForEntity() call from your Controller.
As shown by the Spring MVC documentation, ResponseEntity is a valid return type from a Controller method. So you can simply return the result of your restTemplate.postForEntity() call from the doLogin() method. As an example:
#Controller
public class MyController
{
#AutoWired
private RestTemplate restTemplate;
#RequestMapping("/yourPath")
public ResponseEntity<String> doLogin(HttpServletRequest request) throws IOException
{
return restTemplate.postForEntity(testPrefix + "/login", map, String.class);
}
}
Spring MVC will take care of marshalling the ResponseEntity into the HTML response using a HTTPMessageConverter.

Bad design letting controller return an Object?

Hi is this bad design? I would like return Profile if everything goes according to plan. If not I would like to return my custom error message.
Is this ok?
#RequestMapping(value = "/{userId}", method = RequestMethod.PUT)
public #ResponseBody
Object saveUser(#PathVariable Long userId, ModelMap data, #Valid Profile profile, BindingResult bindingResult, HttpServletResponse response) {
if (bindingResult.hasErrors()) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return ValidationUtil.createValidationErrors(bindingResult);
}
profileService.save(profile);
return profile;
}
You should use #ExceptionHandler (Exception.class) and #ResponseStatus Annotation
Example
#ExceptionHandler (Exception.class)
#RequestMapping(value = "/{userId}", method = RequestMethod.PUT)
public #ResponseBody
Profile saveUser(#PathVariable Long userId, ModelMap data, #Valid Profile profile, BindingResult bindingResult, HttpServletResponse response) {
if (bindingResult.hasErrors()) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
throw new Exception("message");
if(ValidationUtil.createValidationErrors(bindingResult)) {
throw new Exception("message");
}
}
profileService.save(profile);
return profile;
}
For more details refer
http://jnb.ociweb.com/jnb/jnbNov2010.html
http://www.stormpath.com/blog/spring-mvc-rest-exception-handling-best-practices-part-1
http://blog.cuttleworks.com/2011/12/spring-restful-controllers-and-error-handling/
If you need access to the profile object, I'd suggest you add it to the session or the request context. Then you can return a string from your saveUser method (or a ModelAndView object, if you prefer), and still have the object available to later requests.

Resources