Idea: I have a Spring web MVC action that should accomplish one or both of these taks:
Problem: Spring is unable to download a file and redirect in case of a problem - somehow flash attributes don't work because the get lost in the redirect:
@ResponseBody
@RequestMapping(value = "/download/{fileaddress}", method = RequestMethod.GET)
public void download(HttpServletRequest request, HttpServletResponse response, @PathVariable(value = "fileaddress") String fileaddress) throws Exception
{
if(fileaddress != null && fileaddress.length() > 0)
{
try
{
// Get the remove file based on the fileaddress
RemoteFile remotefile = new RemoteFile(fileaddress);
// Set the input stream
InputStream inputstream = remotefile.getInputStream();
// Write the input stream to the output stream or throw an exception
Utils.writeTo(inputstream, response.getOutputStream());
}
catch(MyExceptionA)
{
// TODO: Define error message a and pass it to /addresses
// PROBLEM: Flash attributes that contain all critical error information don't work
response.sendRedirect(request.getContextPath() + "/addresses");
}
catch(MyExceptionB)
{
// TODO: Add another error message and redirect
response.sendRedirect(request.getContextPath() + "/addresses");
}
catch(MyExceptionC)
{
// TODO: Add another error message and redirect
response.sendRedirect(request.getContextPath() + "/addresses");
}
catch(MyExceptionN)
{
// TODO: Add another error message and redirect
response.sendRedirect(request.getContextPath() + "/addresses");
}
}
else
{
// TODO: Add error message
response.sendRedirect(request.getContextPath() + "/addresses");
}
}
JSP page of /addresses:
<%@ page pageEncoding="UTF-8" %>
<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %>
<%@ taglib prefix="core" uri="http://java.sun.com/jsp/jstl/core" %>
<tags:index>
<jsp:attribute name="content">
<core:if test="${not empty error}">
<div class="alert alert-danger">
<p>${error}</p>
</div>
</core:if>
<p>Page under construction!</p>
</jsp:attribute>
</tags:index>
Question: How I am able to display the error message (Simple string for example) in the /addresses site? Working with different URL parameter (error=errora, error=errorb ...) is a huge pain, if there are multiple error types and passing the error message as GET parameter looks unprofessional and is the root of encoding problems.
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";
}