Download or redirect with error message to another controller action in Spring web MVC
What you need is the RedirectAttributes
a specialization of the Model
which controllers can use to select attributes for a redirect scenario.
So for a working example see below code:
@ResponseBody
@RequestMapping(value = "/download/{fileaddress}", method = RequestMethod.GET)
public Object download(@PathVariable(value = "fileaddress") String fileaddress, RedirectAttributes redirectAttrs) throws Exception {
if(StringUtils.hasText(fileaddress)){
try{
// Get the remove file based on the fileaddress
RemoteFile remotefile = new RemoteFile(fileaddress);
// Set the input stream
InputStream inputstream = remotefile.getInputStream();
// asume that it was a PDF file
HttpHeaders responseHeaders = new HttpHeaders();
InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
responseHeaders.setContentLength(contentLengthOfStream);
responseHeaders.setContentType(MediaType.valueOf("application/pdf"));
return new ResponseEntity<InputStreamResource> (inputStreamResource,
responseHeaders,
HttpStatus.OK);
} catch (MyExceptionA | MyExceptionB | MyExceptionC | MyExceptionD ex) {
redirectAttrs.addFlashAttribute("error", ex.getMessage());
}
} else {
redirectAttrs.addFlashAttribute("error", "File name is required");
}
return "redirect:/addresses";
}
Update: I've thought the question is about situations where RedirectAttributes
are not available because otherwise, the solution is pretty obvious (use RedirectAttributes
).
Orignal answer:
I'm using the following code to bind messages to the flash map in situations where Spring doesn't support RedirectAttributes
(e.g. in ExceptionHandler
methods):
public static Feedback getInstance(HttpServletRequest request, HttpServletResponse response) throws IllegalArgumentException {
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
Object o = flashMap.get(KEY);
if (o != null) {
if (o instanceof Feedback) {
return Feedback.class.cast(o);
} else {
throw new IllegalArgumentException(...);
}
} else {
FeedbackContainer feedbackContainer = new FeedbackContainer();
flashMap.put(KEY, feedbackContainer);
FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request);
flashMapManager.saveOutputFlashMap(flashMap, request, response);
return feedbackContainer;
}
where Feedback
/ FeedbackContainer
is a container for messages which is then accessed in JPSs via JSON serialization. In your case you may use a mere String with key "error" and access it directly in the JSP:
void storeErrorMsg(HttpServletRequest request, HttpServletResponse response, String message) {
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
flashMap.put("error", message);
FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request);
flashMapManager.saveOutputFlashMap(flashMap, request, response);
}
The main reason for using my own message container is the possibility to have multiple messages with different levels and additional getInstance
methods for RedirectAttributes
, Model
or ModelMap
, so I don't have to care about duplicate feedback bindings and/or the different binding code.