Spring XML 406 error

痞子三分冷 提交于 2020-01-02 05:29:10

问题


I am trying to make a RESTful service using Java, using several tutorials and many, MANY StackOverflow entries. Unfortunately I don't seem to be able to get my code to work, I am persistantly getting Http 406 when I try and hit the endpoint. Any help is appreciated.

GreetingController.java:

import java.util.Random;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.ResponseBody;

@Controller
@RequestMapping("/greeting")
public class GreetingController {

    protected final Logger log = LoggerFactory.getLogger(GreetingController.class);

    private static final String template = "Hello, %s!";
    private static Random rand = new Random();

    @RequestMapping(method = RequestMethod.GET, headers="Accept=*/*")//, value="/{name}")
    @ResponseBody
    public Greeting greeting() {
        log.debug("Entered greeting()");
        return new Greeting(rand.nextInt(99999999),
                            String.format(template, "Stephen"));
    }

    @RequestMapping(method = RequestMethod.GET, value="/{name}")
    @ResponseBody
    public Greeting greetingName(@PathVariable String name) {
        log.debug("Entered greetingName()");
        return new Greeting(rand.nextInt(99999999),
                            String.format(template, name));
    }
}

Greeting.java:

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="greeting")
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
public class Greeting {

    private Integer id;
    private String content;

    public Greeting() {

    }

    public Greeting(Integer id, String content) {
        this.id = id;
        this.content = content;
    }

    @XmlElement
    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    @XmlElement
    public void setContent(String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }
}

x-servlet.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:oxm="http://www.springframework.org/schema/oxm"
    xmlns:mvc="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <context:component-scan base-package="com.package.name" />

    <mvc:annotation-driven/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix">
            <value>/WEB-INF/pages/</value>
      </property>
      <property name="suffix">
            <value>.jsp</value>
      </property>
    </bean>

</beans>

Http headers (via firebug):

Response Headers
Content-Language    en
Content-Length  1067
Content-Type    text/html;charset=utf-8
Date    Tue, 18 Feb 2014 20:24:13 GMT
Server  Apache-Coyote/1.1

Request Headers
Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language en-US,en;q=0.5
Connection  keep-alive
Cookie  JSESSIONID=9064B3E9F1C3259B73C65B022C8BDC75
Host    localhost:8080
User-Agent  Mozilla/5.0 (Windows NT 6.0; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0

log when starting up tomcat and hitting the different pages on said server:

DEBUG o.s.security.web.FilterChainProxy - Converted URL to lowercase, from: '/greeting'; to: '/greeting'
DEBUG o.s.security.web.FilterChainProxy - Candidate is: '/greeting'; pattern is /**; matched=true
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 1 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.access.channel.ChannelProcessingFilter@9a6bbb'
DEBUG o.s.s.w.a.i.DefaultFilterInvocationSecurityMetadataSource - Converted URL to lowercase, from: '/greeting'; to: '/greeting'
DEBUG o.s.s.w.a.i.DefaultFilterInvocationSecurityMetadataSource - Candidate is: '/greeting'; pattern is /**; matched=true
DEBUG o.s.s.w.a.c.ChannelProcessingFilter - Request: FilterInvocation: URL: /greeting; ConfigAttributes: [ANY_CHANNEL]
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 2 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.context.SecurityContextPersistenceFilter@16fcc4'
DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No HttpSession currently exists
DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created.
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 3 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.logout.LogoutFilter@1db52c8'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 4 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@17d6c1'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 5 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@1144823'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 6 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.www.BasicAuthenticationFilter@8c02cc'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 7 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.savedrequest.RequestCacheAwareFilter@bbd1b'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 8 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@ac576f'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 9 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.AnonymousAuthenticationFilter@15daa9e'
DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 10 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.session.SessionManagementFilter@6c9f0f'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 11 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.access.ExceptionTranslationFilter@13ec758'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 12 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.access.intercept.FilterSecurityInterceptor@917cb0'
DEBUG o.s.s.w.a.i.DefaultFilterInvocationSecurityMetadataSource - Converted URL to lowercase, from: '/greeting'; to: '/greeting'
DEBUG o.s.s.w.a.i.DefaultFilterInvocationSecurityMetadataSource - Candidate is: '/greeting'; pattern is /welcome*; matched=false
DEBUG o.s.s.w.a.i.DefaultFilterInvocationSecurityMetadataSource - Candidate is: '/greeting'; pattern is /**; matched=true
DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /greeting; Attributes: [IS_AUTHENTICATED_ANONYMOUSLY]
DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.RoleVoter@1913751, returned: 0
DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.AuthenticatedVoter@c6b80e, returned: 1
DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful
DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object
DEBUG o.s.security.web.FilterChainProxy - /greeting reached end of additional filter chain; proceeding with original chain
DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'spring-tutorial' determining Last-Modified value for [/SpringMVC/greeting]
DEBUG o.s.w.s.m.a.DefaultAnnotationHandlerMapping - Mapping [/greeting] to handler 'com.example.controller.GreetingController@1eb1db2'
DEBUG o.s.web.servlet.DispatcherServlet - Last-Modified value for [/SpringMVC/greeting] is: -1
DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'spring-tutorial' processing GET request for [/SpringMVC/greeting]
DEBUG o.s.w.b.a.s.HandlerMethodInvoker - Invoking request handler method: public com.example.form.Greeting com.example.controller.GreetingController.greeting()
INFO  c.s.controller.GreetingController - Entered greeting()
DEBUG o.s.w.s.m.a.AnnotationMethodHandlerExceptionResolver - Resolving exception from handler [com.example.controller.GreetingController@1eb1db2]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver - Resolving exception from handler [com.example.controller.GreetingController@1eb1db2]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolving exception from handler [com.example.controller.GreetingController@1eb1db2]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext contents are anonymous - context will not be stored in HttpSession. 
DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'spring-tutorial': assuming HandlerAdapter completed request handling
DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request
DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed

回答1:


I just came across this when trying to troubleshoot the same issue. After looking at pfac's answer, I discovered I could solve my issue simply by adding the jackson-dataformat-xml library to my project.

If using maven:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.3.2</version>
</dependency>



回答2:


Just spent some hours chasing this, so I'm leaving here what worked for me (I'm using Spring 4.0.6) and what I believe will work for you (Spring 3.0.x).

Spring 4.0.x

Since MappingJackson2HttpMessageConverter picks up the Jackson data binding library automatically and enables controller methods annotated with @ResponseBody to automatically return JSON, one usually assumes that such a tool also exists for XML, but this is not the case.

In order to enable XML I had to manually create a RequestMappingHandlerAdapter with two message converters, a MarshallingHttpMessageConverter followed by a MappingJackson2HttpMessageConverter.

This also allows to use any of the marshallers provided by Spring, just by setting it as a property of MarshallingHttpMessageConverter.

Resulting spring-servlet.xml:

<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- ... -->

    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
                    <property name="marshaller">
                        <bean class="org.springframework.oxm.xstream.XStreamMarshaller"></bean>
                    </property>
                </bean>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
            </list>
        </property>
    </bean>

    <!-- ... -->

</beans>

Spring 3.0.x

NOTE: I'm assuming this version from the schema locations in your x-servlet.xml.

According to http://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc and http://spring.io/blog/2013/06/03/content-negotiation-using-views/, there are two ways to achieve what you want in Spring 3. The first one is using a ContentNegotiationManager, which is only available since versions 3.2.x and therefore is unavailable for your version. The second one is using a ContentNegotiatingViewResolver, which delegates the resolution of the views to other resolvers based on the content type requested (whether this is defined by the Accept header, by extension, or by default is configurable).

Basically you need to configure a ContentNegotiatingViewResolver with two resolvers, one for XML and another for your JSP views.

spring-servlet.xml:

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="viewResolvers">
        <list>
            <bean class="org.springframework.web.servlet.view.XmlViewResolver">
                <property name="location" value="spreadsheet-views.xml"/>
            </bean>

            <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="WEB-INF/views"/>
                <property name="suffix" value=".jsp"/>
            </bean>
        </list>
    </property>
</bean>

You can add a view resolver for JSON for example, but you will have to implement it since Spring does not provide one. The second blog post shows how to implement a simple one.




回答3:


406 means the request content is considered Not Acceptable by the server. Try to remove the Accept header or adding headers="Accept=*/*" to the @RequestMapping annotations.




回答4:


I was struggling with a similar problem. It appeared that for some reason my web app was not providing xml data type by default, even despite I was setting "produces=application/xml" parameter in annotations.

I only solved it by adding extra bean configuration for my applicationContext.xml:

<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
   <property name="defaultContentType" value="application/xml" />
</bean>
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />

or via Java Config class:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.defaultContentType(MediaType.APPLICATION_XML);
    }
}


来源:https://stackoverflow.com/questions/21865179/spring-xml-406-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!