sparks
sparks

Reputation: 764

POJO JAXB annotation not converting to XML

I have a simple POJO "Greeting" that is annotated with JAXB, and am trying to return the XML from a Java Restful service. However, whenever I am trying to hit the webpage the POJO isn't being successfully converted to XML. I am getting Http 406 with the error in my logs:

o.s.w.s.m.a.AnnotationMethodHandlerExceptionResolver - Resolving exception from handler [GreetingController@20b722]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation

I can return a simple String just fine, but when I try and return my POJO it errors out.

I am using a Spring-MVC structure.

Greeting.java:

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

@XmlRootElement
public class Greeting {


    private String id;
    private String content;

    public Greeting() {

    }

    public void setId(String id) {
        this.id = id;
    }

    @XmlElement
    public String getId() {
        return id;
    }

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

    @XmlElement
    public String getContent() {
        return content;
    }
}

controller:

@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();


    //Returns correct string
    @RequestMapping(method = RequestMethod.GET, value="/goodbye", headers="Accept=application/xml")
    public @ResponseBody String letsReturnAString() {
        log.info("Entered letsReturnAString()");

        return "Curses, Foiled Again!";
    }

    //Returns Http 406
    @RequestMapping(method = RequestMethod.GET, headers="Accept=application/xml")
    public @ResponseBody Greeting greeting() {
        log.info("Entered greeting()");

        Greeting g = new Greeting();
        g.setId(rand.nextInt(99999999) +"");
        g.setContent(String.format(template, "NAME"));

        return g;
    }
}

Context.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.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.1.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

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

    <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>

    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="mediaTypes">
      <map>
          <entry key="html" value="text/html"></entry>
          <entry key="json" value="application/json"></entry>
          <entry key="xml"  value="application/xml"></entry>
      </map>
    </property>
    <property name="viewResolvers">
        <list>
          <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
            <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
            <property name="prefix" value="/WEB-INF/jsp/"></property>
            <property name="suffix" value=".jsp"></property>
          </bean>
        </list>
    </property>
</bean>

</beans>

Full Error logs related to hitting the page:

DEBUG o.s.security.web.FilterChainProxy - /greeting at position 1 of 12 in additional filter chain; firing Filter: 'ChannelProcessingFilter'
DEBUG o.s.s.web.util.AntPathRequestMatcher - Request '/greeting' matched by universal pattern '/**'
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: 'SecurityContextPersistenceFilter'
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: 'LogoutFilter'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 4 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 5 of 12 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 6 of 12 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
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: 'SessionManagementFilter'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
DEBUG o.s.security.web.FilterChainProxy - /greeting at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
DEBUG o.s.s.web.util.AntPathRequestMatcher - Checking match of request : '/greeting'; against '/welcome*'
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@84fdbc, returned: 0
DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.AuthenticatedVoter@12e5c94, 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' processing GET request for [/SpringMVC/greeting]
DEBUG o.s.w.s.m.a.DefaultAnnotationHandlerMapping - Mapping [/greeting] to HandlerExecutionChain with handler [com.package.controller.GreetingController@20b722] and 1 interceptor
DEBUG o.s.web.servlet.DispatcherServlet - Last-Modified value for [/SpringMVC/greeting] is: -1
DEBUG o.s.w.b.a.s.HandlerMethodInvoker - Invoking request handler method: public com.package.form.Greeting com.package.controller.GreetingController.greeting()
INFO  c.s.controller.GreetingController - Entered greeting()
DEBUG o.s.w.s.m.a.AnnotationMethodHandlerExceptionResolver - Resolving exception from handler [com.package.controller.GreetingController@20b722]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver - Resolving exception from handler [com.package.controller.GreetingController@20b722]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolving exception from handler [com.package.controller.GreetingController@20b722]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext is empty or 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

Upvotes: 1

Views: 1764

Answers (2)

sparks
sparks

Reputation: 764

I found my problem. I was using <mvc:annotation-driven/> HOWEVER, the schema I was using for mvc wasn't right.

xmlns:mvc="http://www.springframework.org/schema/tx"

Is NOT the correct schema. Once I changed it to the proper one, everything worked fine. Proper schema:

xmlns:mvc="http://www.springframework.org/schema/mvc"

Upvotes: 1

bdoughan
bdoughan

Reputation: 149017

Not sure if this is your issue but since you are annotating the fields (instance variables) and not the properties (get or set method) you need to annotate your class with @XmlAccessorType(XmlAccessType.FIELD). If you don't JAXB will throw a "duplicate property" exception which could manifest itself as the problem you are seeing.

Upvotes: 0

Related Questions