Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failure to resolve @RequestMapping method arguments in Servlet 2.5 environments [SPR-14358] #18930

Closed
spring-projects-issues opened this issue Jun 13, 2016 · 2 comments
Assignees
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

@spring-projects-issues spring-projects-issues commented Jun 13, 2016

Dmitri Gabbasov opened SPR-14358 and commented

Given the following bean configuration:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/mvc   http://www.springframework.org/schema/mvc/spring-mvc.xsd">
  <context:component-scan base-package="test" />
  <mvc:annotation-driven/>
</beans>

and the following controller:

package test;
// ...
@Controller
public class TestController {
  @RequestMapping("/home")
  @ResponseBody
  public String home(@RequestParam String param) {
    return param;
}

and using them in a Servlet 2.5 environment (e.g. Tomcat 6) will result in the following exception when a request is made to /home:

org.springframework.web.multipart.MultipartException: Current request is not a multipart request
        at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:188)
        at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:104)
        at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
        at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        ...

This only occurs when Spring chooses to use the RequestMappingHandlerAdapter (as opposed to the deprecated AnnotationMethodHandlerAdapter).

The root cause of this seems to be in the (somewhat recent) MultipartResolutionDelegate class. Its servletPartClass field remains null in pre Servlet 3.0 environments, and some equality checks yield false positives due to that. For instance:

private static boolean isPartCollection(MethodParameter methodParam) {
	return (servletPartClass == getCollectionParameterType(methodParam));
}
private static Class<?> getCollectionParameterType(MethodParameter methodParam) {
	Class<?> paramType = methodParam.getNestedParameterType();
	if (Collection.class == paramType || List.class.isAssignableFrom(paramType)){
		Class<?> valueType = GenericCollectionTypeResolver.getCollectionParameterType(methodParam);
		if (valueType != null) {
			return valueType;
		}
	}
	return null;
}

getCollectionParameterType returns null for non-collection parameters, which makes isPartCollection return true. The isPartArray method is plagued by the same issue (and maybe other places are too).


Affects: 4.3 GA

Issue Links:

  • #19030 MultipartResolutionDelegate in Servlet 2.5 environments not working correctly

Referenced from: commits dcb2c73

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 14, 2016

Juergen Hoeller commented

Good catch! Fixed for 4.3.1 now.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 20, 2016

Francisco Lozano commented

Was about to report it, we were just hit by this. In our case, isPartCollection is the one hurting, glad it's already reported and fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants