Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot 405 POST method not supported?

How could POST method not support by Spring Boot MVC ?! I am trying to implement a simple post method that accepts a list of entities : here is my code

@RestController(value="/backoffice/tags")
public class TagsController {

    @RequestMapping(value = "/add", method = RequestMethod.POST)
        public void add(@RequestBody List<Tag> keywords) {
            tagsService.add(keywords);
        }
}

Hitting this URL like this:

http://localhost:8090/backoffice/tags/add

Request Body:

[{"tagName":"qweqwe"},{"tagName":"zxczxczx"}]

I receive:

{
    "timestamp": 1441800482010,
    "status": 405,
    "error": "Method Not Allowed",
    "exception": "org.springframework.web.HttpRequestMethodNotSupportedException",
    "message": "Request method 'POST' not supported",
    "path": "/backoffice/tags/add"
} 

EDIT:

Debugging Spring Web Request Handler

     public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.checkRequest(request); 

 protected final void checkRequest(HttpServletRequest request) throws ServletException {
        String method = request.getMethod();
        if(this.supportedMethods != null && !this.supportedMethods.contains(method)) {
            throw new HttpRequestMethodNotSupportedException(method, StringUtils.toStringArray(this.supportedMethods));
        } else if(this.requireSession && request.getSession(false) == null) {
            throw new HttpSessionRequiredException("Pre-existing session required but none found");
        }
    }

The only two methods in supportedMethods are {GET,HEAD}

like image 267
Adelin Avatar asked Sep 09 '15 12:09

Adelin


2 Answers

You have an error in RestController annotation definition. According to the docs it is:

public @interface RestController {

/** * The value may indicate a suggestion for a logical component name, * to be turned into a Spring bean in case of an autodetected component. * @return the suggested component name, if any * @since 4.0.1 */ String value() default "";

}

Which means the value you have entered ("/backoffice/tags") is NAME of the controller not the path under which it is available.

Add @RequestMapping("/backoffice/tags") on the controller's class and remove value from the @RestController annotation.

EDIT: Fully working example as per comment that it does not work - try to use this code please - and run locally from IDE.

build.gradle

buildscript {
    ext {
        springBootVersion = '1.2.5.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 
        classpath("io.spring.gradle:dependency-management-plugin:0.5.2.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot' 
apply plugin: 'io.spring.dependency-management' 

jar {
    baseName = 'demo'
    version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenCentral()
}


dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    testCompile("org.springframework.boot:spring-boot-starter-test") 
}


eclipse {
    classpath {
         containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
         containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
    }
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.3'
}

Tag.java

package demo;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class Tag {

    private final String tagName;

    @JsonCreator
    public Tag(@JsonProperty("tagName") String tagName) {
        this.tagName = tagName;
    }

    public String getTagName() {
        return tagName;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Tag{");
        sb.append("tagName='").append(tagName).append('\'');
        sb.append('}');
        return sb.toString();
    }
}

SampleController.java

package demo;

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/backoffice/tags")
public class SampleController {

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public void add(@RequestBody List<Tag> tags) {
        System.out.println(tags);
    }
}

DemoApplication.java

package demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
like image 107
Rafal G. Avatar answered Oct 20 '22 17:10

Rafal G.


Actually When method name is available but method type is different than required type so this exception will throw 405.

like image 41
Vipul Kacha Avatar answered Oct 20 '22 16:10

Vipul Kacha