I am getting a Request method 'PUT' not supported
error on hitting a PUT method on a restful API to upload a file.
Following is the information uploaded to this ticket.
- Client Log
- RestController
- Spring Boot App Config
- Tomcat log
- POM.xml
1. Client Log
$ curl -X PUT -T "/cygdrive/c/a/documents/test.pptx" http://localhost:8080/piranha-storage-service/buckets/gnaval.bucket1/test.pptx
<html><head><title>Apache Tomcat/7.0.52 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 405 - Request method 'PUT' not supported</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>Request method 'PUT' not supported</u></p><p><b>description</b> <u>The specified HTTP method is not allowed for the requested resource.</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/7.0.52</h3></body></html>
2. RestController
package com.acme.piranha.api.impl;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.acme.piranha.api.PiranhaStorageService;
import com.acme.piranha.dto.TransferStream;
import com.acme.piranha.exception.PiranhaDataAccessException;
import com.acme.piranha.s3.svc.S3;
@RestController
@RequestMapping(value = "/piranha-storage-service")
public class PiranhaStorageServiceRESTImpl implements PiranhaStorageService {
@Autowired
S3 s3;
@RequestMapping(value = "/buckets/{bucketName}/{objectName:.+}", method = RequestMethod.PUT, headers="{Accept=*/*, content-type=multipart/form-data}")
public @ResponseBody
String upload(@PathVariable final String bucketName,
@PathVariable final String objectName,
@RequestParam("file") MultipartFile file) {
LOG.info("Reached upload. uploading object.");
try {
File uploadedFile = new File(file.getOriginalFilename());
try {
byte[] bytes = file.getBytes();
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(uploadedFile));
stream.write(bytes);
stream.close();
} catch (IOException e) {
throw new RuntimeException("Failed to upload file!", e);
}
final FileInputStream fileUpload = new FileInputStream(uploadedFile);
final String objectTag = s3.upload(bucketName, objectName, fileUpload);
LOG.info("Successfully uploaded object to S3, assigned object tag="
+ objectTag);
return objectTag;
} catch (final IOException ioe) {
LOG.error("Failed upload operation, returning empty string");
// in case of exception flow return a empty stream.
return "";
} catch (final PiranhaDataAccessException pdae) {
LOG.error("Failed upload operation, returning empty string");
// in case of exception flow return a empty stream.
return "";
}
}
}
3. Spring Boot App Config
package com.acme.piranha.config;
import javax.servlet.MultipartConfigElement;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.embedded.MultiPartConfigFactory;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
@Configuration
@EnableAutoConfiguration
@ComponentScan("com.acme.piranha")
public class PiranhaStorageServiceApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(
final SpringApplicationBuilder application) {
return application.sources(PiranhaStorageServiceApplication.class);
}
public static void main(final String[] args) throws Exception {
SpringApplication.run(PiranhaStorageServiceApplication.class, args);
}
@Bean
public MultipartConfigElement multipartConfigElement() {
MultiPartConfigFactory factory = new MultiPartConfigFactory();
factory.setMaxFileSize("2MB");
factory.setMaxRequestSize("2MB");
return factory.createMultipartConfig();
}
@Bean
public MultipartResolver multipartResolver() {
return new CommonsMultipartResolver();
}
}
4. Tomcat log
2014-04-03 12:44:37.159 INFO 5592 --- [lication.main()] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080/http
2014-04-03 12:44:37.168 INFO 5592 --- [lication.main()] c.p.p.c.PiranhaStorageServiceApplication : Started PiranhaStorageServiceApplication in 5.423 seconds (JVM running for 11.60
8)
2014-04-03 12:44:51.995 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing servlet 'dispatcherServlet'
2014-04-03 12:44:51.997 INFO 5592 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2014-04-03 12:44:51.998 INFO 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2014-04-03 12:44:51.999 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Using MultipartResolver [org.springframework.web.multipart.support.StandardServl
etMultipartResolver@1c15b988]
2014-04-03 12:44:52.007 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Unable to locate LocaleResolver with name 'localeResolver': using default [org.s
pringframework.web.servlet.i18n.AcceptHeaderLocaleResolver@30ab6fdf]
2014-04-03 12:44:52.014 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Unable to locate ThemeResolver with name 'themeResolver': using default [org.spr
ingframework.web.servlet.theme.FixedThemeResolver@3696a572]
2014-04-03 12:44:52.025 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Unable to locate RequestToViewNameTranslator with name 'viewNameTranslator': usi
ng default [org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@57dc2acc]
2014-04-03 12:44:52.032 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Unable to locate FlashMapManager with name 'flashMapManager': using default [org
.springframework.web.servlet.support.SessionFlashMapManager@5e2cc0ac]
2014-04-03 12:44:52.033 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Published WebApplicationContext of servlet 'dispatcherServlet' as ServletContext
attribute with name [org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcherServlet]
2014-04-03 12:44:52.033 INFO 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 34 ms
2014-04-03 12:44:52.037 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Servlet 'dispatcherServlet' configured successfully
2014-04-03 12:44:52.060 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing PUT request for [/pir
anha-storage-service/buckets/gnaval.bucket1/PivotalInstall.pptx]
2014-04-03 12:44:52.065 DEBUG 5592 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /piranha-storage-service/buckets/gnaval.bucke
t1/PivotalInstall.pptx
2014-04-03 12:44:52.073 DEBUG 5592 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Did not find handler method for [/piranha-storage-service/buckets/gnaval.bucket1
/PivotalInstall.pptx]
2014-04-03 12:44:52.075 DEBUG 5592 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Matching patterns for request [/piranha-storage-service/buckets/gnaval.bucket1/P
ivotalInstall.pptx] are [/**]
2014-04-03 12:44:52.076 DEBUG 5592 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : URI Template variables for request [/piranha-storage-service/buckets/gnaval.buck
et1/test.pptx] are {}
2014-04-03 12:44:52.080 DEBUG 5592 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapping [/piranha-storage-service/buckets/gnaval.bucket1/test.pptx] to
HandlerExecutionChain with handler [org.springframework.web.servlet.resource.ResourceHttpRequestHandler@19db7f7e] and 1 interceptor
2014-04-03 12:44:52.083 DEBUG 5592 --- [nio-8080-exec-1] .w.s.m.a.ResponseStatusExceptionResolver : Resolving exception from handler [org.springframework.web.servlet.resource.Resou
rceHttpRequestHandler@19db7f7e]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'PUT' not supported
2014-04-03 12:44:52.086 DEBUG 5592 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolving exception from handler [org.springframework.web.servlet.resource.Resou
rceHttpRequestHandler@19db7f7e]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'PUT' not supported
2014-04-03 12:44:52.089 WARN 5592 --- [nio-8080-exec-1] o.s.web.servlet.PageNotFound : Request method 'PUT' not supported
2014-04-03 12:44:52.096 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': a
ssuming HandlerAdapter completed request handling
2014-04-03 12:44:52.098 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Successfully completed request
5. pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.0.0.RELEASE</version>
</parent><dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>core</artifactId>
<version>0.9.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-service-connector</artifactId>
<version>0.9.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>cloudfoundry-connector</artifactId>
<version>0.9.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.0.002</version>
</dependency>
</dependencies>
</project>
Chek you request mapping
if you declare request mapping in class level
@RequestMapping("/api/users")
then if you declare mapping in method level@RequestMapping("/api/users/{id}")
this error could occur.correct
incorrect , might cause PUT not supported error
This error happened with me too, I just restarted the server and the error disappeared, the RequestMapping that you've put match the request.
To enable the PUT verb you have to add an interceptor that allows that method in the response header.
Something like that:
I don't know how to add an interceptor using spring boot though, and I would be intersted in knowing it :)
For adding Interceptor what you should do is implementing
WebMvcConfigurer
and overriding addInterceptors method.Simply put: your
@RequestMapping
doesn't match the request. The regex probably needs some work.