I\'m using Spring 3.2.0. According to this answer, I have the same method in my annotated controller which implements the HandlerExceptionResolver
interface suc
You can config the CommonsMultipartResolver's resolveLazily property to true like this:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="resolveLazily" value="true"/>
</bean>
From the answer posted by Dirk Lachowski, I have excluded some of the pages which are used for multipart-upload from HiddenHttpMethodFilter.
HiddenHttpMethodFilter was originally given a URL pattern like /*
. Therefore, it was tedious to move these pages in a separate directory/folder and specify a different URL patter like /xxx/*
. To avoid this, I have inherited OncePerRequestFilter in my own class and excluded these pages used for multipart-upload that worked as expected showing a user-friendly error message on the current page.
package filter;
import java.io.IOException;
import java.util.Locale;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
public final class HiddenHttpMethodFilter extends OncePerRequestFilter {
/**
* Default method parameter: <code>_method</code>
*/
public static final String DEFAULT_METHOD_PARAM = "_method";
private String methodParam = DEFAULT_METHOD_PARAM;
/**
* Set the parameter name to look for HTTP methods.
*
* @see #DEFAULT_METHOD_PARAM
*/
public void setMethodParam(String methodParam) {
Assert.hasText(methodParam, "'methodParam' must not be empty");
this.methodParam = methodParam;
}
private boolean excludePages(String page) {
//Specifically, in my case, this many pages so far have been excluded from processing avoiding the MaxUploadSizeExceededException in this filter. One could use a RegExp or something else as per requirements.
if (page.equalsIgnoreCase("Category.htm") || page.equalsIgnoreCase("SubCategory.htm") || page.equalsIgnoreCase("ProductImage.htm") || page.equalsIgnoreCase("Banner.htm") || page.equalsIgnoreCase("Brand.htm")) {
return false;
}
return true;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String servletPath = request.getServletPath();
if (excludePages(servletPath.substring(servletPath.lastIndexOf("/") + 1, servletPath.length()))) {
String paramValue = request.getParameter(this.methodParam);
//The MaxUploadSizeExceededException was being thrown at the preceding line.
if ("POST".equals(request.getMethod()) && StringUtils.hasLength(paramValue)) {
String method = paramValue.toUpperCase(Locale.ENGLISH);
HttpServletRequest wrapper = new filter.HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
filterChain.doFilter(wrapper, response);
} else {
filterChain.doFilter(request, response);
}
} else {
filterChain.doFilter(request, response);
}
}
/**
* Simple {@link HttpServletRequest} wrapper that returns the supplied
* method for {@link HttpServletRequest#getMethod()}.
*/
private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
private final String method;
public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
super(request);
this.method = method;
}
@Override
public String getMethod() {
return this.method;
}
}
}
And in my web.xml
file, this filter - filter.HiddenHttpMethodFilter
was specified instead of org.springframework.web.filter.HiddenHttpMethodFilter as follows.
<filter>
<filter-name>multipartFilter</filter-name>
<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>multipartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>httpMethodFilter</filter-name>
<filter-class>filter.HiddenHttpMethodFilter</filter-class>
<!--<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> This was removed replacing with the preceding one-->
</filter>
<filter-mapping>
<filter-name>httpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I'm still hoping that there should/could be a fair way to handle the exception in question along with org.springframework.web.filter.HiddenHttpMethodFilter
According to your posted stacktrace the MaxUploadSizeExceeded
exception is thrown before the request has reached the dispatcher servlet. Therefore your exceptionhandler isn't called because at the point the exception is thrown the target controller has yet to be determined.
If you look at the stacktrace you can see that the exception is thrown in the HiddenHttpMethodFilter
that gets all parameters of your multipart-request - and also your "to big" upload-data parameter.
Is the HiddenHttpMethodFilter
needed for your controller handling the multipart-upload? If not, exclude this filter from your upload-handling controllers.
In your ControllerAdvice which is handling the Exception you can have code like this.It worked for me.This is in spring 4.0+
@ExceptionHandler(Exception.class)
public @ResponseBody BaseResponse onException(Exception e, HttpServletResponse response) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
BaseResponse resp = new BaseResponse();
if(e instanceof MaxUploadSizeExceededException){
resp.setCode(FileUploadFailed.SIZE_EXCEED);
resp.setMessage("Maximum upload size exceeded");
}
return resp;
}
Is there anyway to get the @RequestParam arguments defined in the controller method in the ExceptionHandler that manages the MaxUploadSizeExceededException? Seems to be being thrown before getting to the Controller method.
My solution :First define bean for class that implements HandlerExceptionResolver .
<bean id="classForBeanException" class="XXXX.path.To.classForBeanException" />