使用Spring配置CXF以使用MOXY进行XML编组/解组 [英] Configuring CXF with Spring to use MOXY for XML marshalling/unmarshalling

查看:108
本文介绍了使用Spring配置CXF以使用MOXY进行XML编组/解组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Java服务器应用程序,它使用CXF提供SOAP和REST Web服务。目前它使用JAX-B的参考实现进行XML编组/解组,但我已经将它配置为用杰克逊代替Jettison进行JSON编组/解组。我使用Spring进行DI和应用程序上下文配置。

I have a Java server application that uses CXF to provide SOAP and REST web services. Currently it uses the reference implementation of JAX-B for XML marshalling/unmarshalling, but I have configured it to replace Jettison with Jackson for JSON marshalling/unmarshalling. I use Spring for DI and application context configuration.

REST Web服务配置片段如下所示:

The REST web service configuration snippets looks as follows:

web.xml

<servlet>
    <display-name>Myapp REST Services</display-name>
    <servlet-name>MyappWebServices</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>MyappWebServices</servlet-name>
    <url-pattern>/services/*</url-pattern>
</servlet-mapping>

applicationContext.xml

<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

<bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />

<jaxrs:server id="myappCoreSvcRest" address="/rest">
    <jaxrs:serviceBeans>
        <ref bean="fooService" />
        <ref bean="barService" />
    </jaxrs:serviceBeans>

    <jaxrs:providers>
        <ref bean="jsonProvider" />
    </jaxrs:providers>
</jaxrs:server>

此配置有效,将返回XML或JSON,具体取决于HTTP Accept标头。我喜欢这个配置的是它基于Spring,并且创建和使用备用JSON编码器非常容易。有关配置CXF的详细信息,请访问此处

This configuration works and will return either XML or JSON depending on the HTTP Accept header. What I like about this configuration is that it is based in Spring and it is super easy to create and use an alternate JSON encoder. Details on configuring CXF can be found here.

我的问题是现在我有一个新的(额外的)REST Web服务要提供,我想为这个新的使用不同的JAX-B XML绑定网络服务。我知道MOXy可以做到这一点,但我无法弄清楚如何配置CXF端点,以便它将使用MOXy进行编组/解组(以及如何告诉Moxy我的自定义XML映射文件)。我还希望这个新的Web服务返回XML或JSON,具体取决于Accept标头。我也读过MOXy 2.4+也可以处理它!

My problem is that now I have a new (additional) REST web service to provide and I would like to use a different JAX-B XML binding for this new web service. I understand that MOXy can do this, but I am unable to figure out how to configure a CXF end point so that it will use MOXy for marshalling/unmarshalling (and furthermore how to tell Moxy about my custom XML mapping file). I also would like this new web service to return either XML or JSON depending on the Accept header. I also have read that MOXy 2.4+ can handle that too!

理想情况下,我可以将MOXy用于这个新端点,而不会影响其他现有的servlet。

Ideally I could use MOXy for this new endpoint without affecting the other existing servlets.

推荐答案

注意:我是 EclipseLink JAXB(MOXy) 领导和 JAXB(JSR-222) 专家组。

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

我不知道CXF的确切配置,但是下面我提供了一些使用MOXy和Spring的链接。请随时 与我联系 ,我可以帮助您实现这个:

Off hand I do not know the exact config for CXF, but below I have provided some links to using MOXy with Spring. Please feel free to contact me, and I can help you implement this:

  • http://blog.bdoughan.com/p/contact_01.html

我的问题是,现在我有一个新的(额外的)REST Web服务提供给
,我想为这个
新的Web服务使用不同的JAX-B XML绑定。我知道MOXy可以做到这一点,但我无法
来弄清楚如何配置一个CXF终点,以便它将使用
MOXy进行编组/解组(以及如何告诉Moxy
关于我的自定义XML映射文件)。

My problem is that now I have a new (additional) REST web service to provide and I would like to use a different JAX-B XML binding for this new web service. I understand that MOXy can do this, but I am unable to figure out how to configure a CXF end point so that it will use MOXy for marshalling/unmarshalling (and furthermore how to tell Moxy about my custom XML mapping file).

当使用MOXy和JAX-RS实现时,你可以使用 ContextResolver 从MOXy的外部映射文件引导:

When using MOXy with a JAX-RS implementation you can use a ContextResolver to bootstrap from MOXy's external mapping file:

package blog.bindingfile.jaxrs;

import java.io.*;
import java.util.*;
import javax.ws.rs.Produces;
import javax.ws.rs.ext.*;
import javax.xml.bind.*;     
import org.eclipse.persistence.jaxb.JAXBContextFactory;

import blog.bindingfile.Customer;

@Provider
@Produces({"application/xml", "application/json"})
public class CustomerContextResolver implements ContextResolver<JAXBContext> {

    private JAXBContext jc;

    public CustomerContextResolver() {
        ClassLoader cl = Customer.class.getClassLoader();
        InputStream bindings =
            cl.getResourceAsStream("blog/bindingfile/binding.xml");
        try {
            Map<String, Object> props = new HashMap<String, Object>(1);
            props.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, bindings);
            jc = JAXBContext.newInstance(new Class[] {Customer.class} , props);
        } catch(JAXBException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                bindings.close();
            } catch(IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public JAXBContext getContext(Class<?> clazz) {
        if(Customer.class == clazz) {
            return jc;
        }
        return null;
    }

} 

对于Complext示例

  • http://blog.bdoughan.com/2011/04/moxys-xml-metadata-in-jax-rs-service.html

有关在春天使用MOXy的更多信息

  • http://wiki.eclipse.org/EclipseLink/Examples/MOXy/Spring

我也希望这个新的Web服务返回XML或JSON
,具体取决于Accept标头。我也读过MOXy 2.4+可以
处理它!

I also would like this new web service to return either XML or JSON depending on the Accept header. I also have read that MOXy 2.4+ can handle that too!

是的,JSON绑定被添加到EclipseLink 2.4 。要在您的应用程序中利用它,应该只需创建一个 MessageBodyReader 和一个 MessageBodyWriter

Yes, JSON binding is being added to EclipseLink 2.4. To leverage this in your application it should be a simple matter of creating a MessageBodyReader and a MessageBodyWriter:

package org.example;

import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import javax.xml.transform.stream.StreamSource;

import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.ext.*;
import javax.xml.bind.*;

@Provider
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class MOXyJSONProvider implements 
    MessageBodyReader<Object>, MessageBodyWriter<Object>{

    @Context
    protected Providers providers;

    public boolean isReadable(Class<?> type, Type genericType,
        Annotation[] annotations, MediaType mediaType) {
        return true;
    }

    public Object readFrom(Class<Object> type, Type genericType,
            Annotation[] annotations, MediaType mediaType,
            MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
            throws IOException, WebApplicationException {
            try {
                Class<?> domainClass = getDomainClass(genericType);
                Unmarshaller u = getJAXBContext(domainClass, mediaType).createUnmarshaller();
                u.setProperty("eclipselink.media-type", mediaType.toString());
                u.setProperty("eclipselink.json.include-root", false);
                return u.unmarshal(new StreamSource(entityStream), domainClass).getValue();
            } catch(JAXBException jaxbException) {
                throw new WebApplicationException(jaxbException);
            }
    }

    public boolean isWriteable(Class<?> type, Type genericType,
        Annotation[] annotations, MediaType mediaType) {
        return true;
    }

    public void writeTo(Object object, Class<?> type, Type genericType,
        Annotation[] annotations, MediaType mediaType,
        MultivaluedMap<String, Object> httpHeaders,
        OutputStream entityStream) throws IOException,
        WebApplicationException {
        try {
            Class<?> domainClass = getDomainClass(genericType);
            Marshaller m = getJAXBContext(domainClass, mediaType).createMarshaller();
            m.setProperty("eclipselink.media-type", mediaType.toString());
            m.setProperty("eclipselink.json.include-root", false);
            m.marshal(object, entityStream);
        } catch(JAXBException jaxbException) {
            throw new WebApplicationException(jaxbException);
        }
    }

    public long getSize(Object t, Class<?> type, Type genericType,
        Annotation[] annotations, MediaType mediaType) {
        return -1;
    }

    private JAXBContext getJAXBContext(Class<?> type, MediaType mediaType) 
        throws JAXBException {
        ContextResolver<JAXBContext> resolver 
            = providers.getContextResolver(JAXBContext.class, mediaType);
        JAXBContext jaxbContext;
        if(null == resolver || null == (jaxbContext = resolver.getContext(type))) {
            return JAXBContext.newInstance(type);
        } else {
            return jaxbContext;
        }
    }

    private Class<?> getDomainClass(Type genericType) {
        if(genericType instanceof Class) {
            return (Class<?>) genericType;
        } else if(genericType instanceof ParameterizedType) {
            return (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0];
        } else {
            return null;
        }
    }

}

你可以也可以创建 JSONProvider 的扩展名:

You may also be able to create an extension of JSONProvider:

  • http://cxf.apache.org/apidocs/org/apache/cxf/jaxrs/provider/JSONProvider.html

更多信息

  • MOXy as Your JAX-RS JSON Provider - Client Side
  • MOXy as Your JAX-RS JSON Provider - Server Side
  • Specifying EclipseLink MOXy as Your JAXB Provider

这篇关于使用Spring配置CXF以使用MOXY进行XML编组/解组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆