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.