Vad1mo
Vad1mo

Reputation: 5543

Spring Boot MultipartResolver is missing on PUT method

I am creating a REST Service with Spring and get an Exception telling me the following.

Expected MultipartHttpServletRequest: is a MultipartResolver configured?

When I change method=RequestMethod.PUT to method=RequestMethod.POST it is working.

Why do I get this exception on PUT but not on POST?

@Configuration
@ComponentScan("io.myservice")
@EnableAutoConfiguration
@EnableCaching
@EnableAsync(mode = ASPECTJ)
public class Application implements AsyncConfigurer {

static org.slf4j.Logger LOG = LoggerFactory.getLogger(Application.class);

public static final String MAX_FILE_SIZE = "2MB";
public static final String MAX_REQUEST_SIZE = "2MB";
public static final String FILE_SIZE_THRESHOLD = "2MB";

@Value("${app.dir.incoming}")
public String createdDir;

@Bean
public LocalValidatorFactoryBean localValidatorFactoryBean() {
    return new LocalValidatorFactoryBean();
}

@Bean
MultipartConfigElement multipartConfigElement() {
    String absTempPath = new File(createdDir).getAbsolutePath();
    MultipartConfigFactory  factory = new MultipartConfigFactory();
    factory.setMaxFileSize(MAX_FILE_SIZE);
    factory.setMaxRequestSize(MAX_REQUEST_SIZE);
    factory.setFileSizeThreshold(FILE_SIZE_THRESHOLD);
    factory.setLocation(absTempPath);
    return factory.createMultipartConfig();
}

@Bean
public StandardServletMultipartResolver multipartResolver() {
    return new StandardServletMultipartResolver();
}

@Override
@Bean
public ThreadPoolTaskExecutor getAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(2);
    executor.setMaxPoolSize(2);
    executor.setQueueCapacity(5);
    executor.initialize();
    return executor;
}

@Bean
public SimpleCacheManager cacheManager(){
    SimpleCacheManager cacheManager = new SimpleCacheManager();
    List<Cache> caches = new ArrayList<Cache>();
    caches.add(cacheBean());
    cacheManager.setCaches(caches );
    return cacheManager;
}

@Bean
public Cache cacheBean(){
    Cache  cache = new ConcurrentMapCache("default");
    return cache;
}

public static void main(String[] args) throws IOException {
    SysOutOverSLF4J.sendSystemOutAndErrToSLF4J();
    run(Application.class, args);
}
}


@RequestMapping(value="/converter", method=RequestMethod.PUT)
@ResponseBody
public String convert(MultipartFile file) {
    LOG.info("received new file to convert")
}


Caused by: java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?
at org.springframework.util.Assert.notNull(Assert.java:112)
at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.resolveName(RequestParamMethodArgumentResolver.java:171)
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:89)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:79)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:157)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:124)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
... 37 common frames omitted

Upvotes: 8

Views: 7508

Answers (4)

Luc De pauw
Luc De pauw

Reputation: 431

You can use and setup org.springframework.web.multipart.commons.CommonsMultipartResolver to support POST and PUT methods. Example:

@Configuration
public class MultipartConfig {
    
    @Bean
    public CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        multipartResolver.setSupportedMethods("POST","PUT");
        return multipartResolver;
    }
}

Upvotes: 1

Vad1mo
Vad1mo

Reputation: 5543

What finally worked for me with PUT was using an InputStream instead of MultipartFile

    @RequestMapping(value="/converter", method=RequestMethod.PUT)
    @ResponseBody
    public String convert(InputStream file) 

This way I was able to use file body and multipart body to upload the file content.

Upvotes: 0

Ritesh Singh
Ritesh Singh

Reputation: 15

MultipartResolver does not have support for PUT method.Because PUT method does not suitable for form submit with multiple arguments.

Rather I have tried with PostMapping for same update method.As Multipart does not support for Put method.

Upvotes: 1

M. Deinum
M. Deinum

Reputation: 124898

The multipart support as used by Spring doesn't support other request method then POST. For the StandardServletMultipartResolver this is hardcoded in that class.

For the CommonsMultipartResolver it is hardcoded in the ServletFileUpload utility class from the Apache Commons Fileupload project.

Tthe Form-based File Upload in HTML (RFC1867) isn't really explicit about this but the only mention of a used HTTP method is POST.

In short, at the moment only POST is supported by the frameworks you might be able to work around it by reimplemening some classes but if it works (especially with the default Servlet 3.0 file upload support) might depend on your container.

Upvotes: 14

Related Questions