2012-01-23 32 views
3

我有一個使用CXF提供SOAP和REST Web服務的Java服務器應用程序。目前,它使用JAX-B的參考實現進行XML編組/解組,但我已將其配置爲使用Jackson替換Jettison以進行JSON編組/解組。我使用Spring進行DI和應用程序上下文配置。使用Spring配置CXF以使用MOXY進行XML編組/解編

的REST Web服務配置摘錄如下所示:

的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的詳細信息,請參閱here

我的問題是,現在我有一個新的(額外的)REST Web服務提供,我想爲這個新的Web服務使用不同的JAX-B XML綁定。我明白MOXy可以做到這一點,但我無法弄清楚如何配置CXF端點,以便它將使用MOXy進行編組/解組(以及如何告訴Moxy關於我的自定義XML映射文件)。我也希望這個新的Web服務根據Accept頭返回XML或JSON。我也讀過,MOXY 2.4+也可以處理它!

理想情況下,我可以在不影響其他現有的servlet的情況下使用MOXy作爲此新端點。

回答

2

注:我是EclipseLink JAXB (MOXy)鉛和JAXB (JSR-222)專家小組的成員。


副手我不知道CXF的確切配置,但下面我提供了一些使用MOXY和Spring的鏈接。請隨時contact me,我可以幫你實現這一點:

我的問題是,現在我有一個新的(附加)REST Web服務 提供,我會喜歡爲此 新的Web服務使用不同的JAX-B XML綁定。我明白,MOXY可以做到這一點,但我無法 想出如何配置CXF端點,以便它將使用MOXy進行編組/解組(以及如何告訴Moxy 關於我的自定義XML映射文件)。

當使用莫西與JAX-RS的實現,你可以使用一個ContextResolver從莫西的外部映射文件來引導:

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例

的更多信息,使用莫西同春


我也想這個新的Web服務來回報XML或JSON 取決於Accept頭。我也讀過,MOXY 2.4+可以 也處理!

是的,JSON綁定正在添加到EclipseLink 2.4中。要在您的應用程序中利用這一點,應該是創造一個MessageBodyReader一個簡單的事情和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擴展:

更多信息

+0

這是否會解決上http://stackoverflow.com/questions/13630539/configure-cxf-jax-ws-service-to-work-問題與-MOXY? @布萊斯·杜漢 –

相關問題