开发者

how to marshal object and return as a view (and not as JSP page) in spring + xstream

I'm trying to follow this tutorial and build a RESTful service that can un/marshal an object to/from XML. http://www.stupidjavatricks.com/?p=54

The marshaller of choice in the article is xStream (I found it to be very easy to use and configure).

The point is, using STS -- Spring's own flavor of Eclipse bundled with tcServer -- I built a project based on the STS template of MVC. This is a legacy project started from Spring version 2.4, and I migrated it to version 3.0. So, the template created all the necessary XML markup, and I added my configuration to point the view to the correct object conversion (to the xstream marshaler).

Here is part of my bean that sends the object to a new view (copied out from the link):

<bean id="bookXmlView" class="org.springframework.web.servlet.view.xml.MarshallingView">  
     <constructor-arg>  
         <bean class="org.springframework.oxm.xstream.XStreamMarshaller">  
             <property name="autodetectAnnotations" value="true"/>  
         </bean>  
     </constructor-arg>  
</bean>

It all worked nicely until I installed the latest STS version 2.5.2.RELEASE and created a new MVC project from a template. (The new template does not use urlrewrite.xml anymore, among some other changes).

I set the correct configuration 1 by 1 as the tutorial suggests, but now no matter what, the view is always directed to a JSP, so if my controller looks like this:

@RequestMapping(value = "/authors/{authorId}")  
public ModelAndView getAuthorById(@PathVariable String authorId) {  
    Author author = bookService.getAuthorById(authorId);  
    ModelAndView mav =new ModelAndView("bookXmlView", BindingResult.MODEL_KEY_PREFIX+"author", author);  
    return mav;  
}

It would always try to return to a author.jsp view and not the object as XML. I tried many things with no 开发者_如何学JAVAsuccess. Any ideas why this happens and how to fix it?


UPDATE ------------------- As noted I added logs:

I set it as DEBUG level and discovered something:

DEBUG: org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - Rejected bean name 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor': no URL paths identified

DEBUG: org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - Rejected bean name 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor': no URL paths identified

DEBUG: org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - Rejected bean name 'org.springframework.context.annotation.internalRequiredAnnotationProcessor': no URL paths identified

DEBUG: org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - Rejected bean name 'org.springframework.context.annotation.internalCommonAnnotationProcessor': no URL paths identified

DEBUG: org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - Rejected bean name 'bookXmlView': no URL paths identified


Notice this line: Rejected bean name 'bookXmlView': no URL paths identified. Searching this indicated maybe a clash between <mvc:annotation-driven /> and my autodetectAnnotations in the xstream settings?

Any case, after invoking the link, I got the following log entry. Notice it forwards the view to /WEB-INF/views/bookXmlView.jsp:

DEBUG: org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name 'appServlet' processing GET request for [/test/page_init]

DEBUG: org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - Mapping [/page_init] to HandlerExecutionChain with handler [test.test.test.HomeController@a087de] and 2 interceptors

DEBUG: org.springframework.web.servlet.DispatcherServlet - Last-Modified value for [/test/page_init] is: -1

DEBUG: org.springframework.web.bind.annotation.support.HandlerMethodInvoker - Invoking request handler method: public org.springframework.web.servlet.ModelAndView test.test.test.HomeController.getObject()

DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Invoking afterPropertiesSet() on bean with name 'bookXmlView'

DEBUG: org.springframework.web.servlet.DispatcherServlet - Rendering view [org.springframework.web.servlet.view.JstlView: name 'bookXmlView'; URL [/WEB-INF/views/xmlView.jsp]] in DispatcherServlet with name 'appServlet'

DEBUG: org.springframework.web.servlet.view.JstlView - Added model object 'org.springframework.validation.BindingResult.books' of type [test.test.test.ObjectTest] to request in view with name 'bookXmlView'

DEBUG: org.springframework.web.servlet.view.JstlView - Forwarding to resource [/WEB-INF/views/xmlView.jsp] in InternalResourceView 'bookXmlView'

DEBUG: org.springframework.web.servlet.DispatcherServlet - Successfully completed request


Got it at last! First I tried a different marshaller - JAXB2 but xstream should work as well.

Next thing is the definition - turns out for some reason the configuration uses this (wrong):

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

using only InternalResourceViewResolver

while definition for org.springframework.web.servlet.view.BeanNameViewResolver is ignored. The solution for that is to define them both in one bean called ContentNegotiatingViewResolver as follows:

    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="viewResolvers">
            <list>
                    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
                    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                            <property name="prefix" value="/WEB-INF/jsp/" />
                            <property name="suffix" value=".jsp" />
                    </bean>
            </list>
    </property>
</bean>
<oxm:jaxb2-marshaller id="marshaller">
        <oxm:class-to-be-bound name="com.mycompany.dashboard.Person" />
</oxm:jaxb2-marshaller>

<bean name="person" class="org.springframework.web.servlet.view.xml.MarshallingView">
        <constructor-arg ref="marshaller" />
</bean>

That configuration solved my problems and person object I played with was not directed to a JSP view but marshaller turn is to an XML:

    @RequestMapping(value = "/person", method = RequestMethod.GET)
public ModelAndView addPerson() {
    Person person = new Person();
    person.setAddress("address 123");
    person.setAge(50);
    person.setName("Andrew");
    System.out.println("new person: " + person);
    ModelAndView mav = new ModelAndView("person",BindingResult.MODEL_KEY_PREFIX + "person",person);
    return mav;

Hope it would help others in the future too.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜