JAX-WS和Joda-Time?

如何编写JAX-WS服务,以便@WebMethod的@WebParam是像DateTime这样的Joda-Time类? 参数上的@XmlTypeAdapter会起作用吗? 我正在部署到GlassFish 2.1。

让我澄清一下这个问题,因为到目前为止这两个答案都集中在将自定义类型绑定到现有的JAXB类上,这与我要问的问题有关。 如何使以下@WebService接受joda DateTime对象作为参数?

import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebService; import javax.jws.soap.SOAPBinding; import org.joda.time.DateTime; @WebService @SOAPBinding(style = SOAPBinding.Style.RPC) public interface Resender { @WebMethod void resend( @WebParam(name = "start") DateTime start, @WebParam(name = "end") DateTime end ); } 

你必须直接注释参数,如下所示(我正在使用@DennisTemper编写的XSDDateTimeMarshaller作为你问题的答案之一,但可以用另一个替换…):

 @WebService @SOAPBinding(style = SOAPBinding.Style.RPC) public interface Resender { @WebMethod void resend( @WebParam(name = "start") @XmlJavaTypeAdapter(type = DateTime.class, value = XSDDateTimeMarshaller.class) DateTime start, @WebParam(name = "end") @XmlJavaTypeAdapter(type = DateTime.class, value = XSDDateTimeMarshaller.class) DateTime end ); } 

首先编写简单的转换器(在本例中为Calendar ,但可以很容易地改为Joda-Time):

 public class XsdDateTimeConverter { public static Calendar unmarshal(String dateTime) { final GregorianCalendar calendar = new GregorianCalendar(); calendar.setTime(DatatypeConverter.parseDate(dateTime).getTime()); return calendar; } public static String marshal(Calendar calendar) { return DatatypeConverter.printDate(calendar); } } 

接下来,您必须将转换器引入JAXB( xjb文件):

     

在生成的JAXB模型中, xjc生成了以下注释:

 @XmlJavaTypeAdapter(Adapter2.class) @XmlSchemaType(name = "date") protected Calendar date; 

其中Adapter2.class是包装POJO转换器的生成适配器。 如您所见,使用Calendar而不是笨拙的javax.xml.datatype.XMLGregorianCalendar 。 如果您将此示例调整为Joda-Time,请与我们分享。

以下解决方案模板

1.)创建XSML适配器

 import java.util.Date; import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.adapters.XmlAdapter; import org.joda.time.DateTime; @XmlTransient public class XSDDateTimeMarshaller extends XmlAdapter { @Override public DateTime unmarshal(Date date) throws Exception { return new DateTime(date.getTime()); } @Override public Date marshal(DateTime dateTime) throws Exception { return new Date(dateTime.getMillis()); } } 

2.)使用(来自实体类的snipet)注释jodatime属性:

 ... @XmlRootElement(name="MyEntity", namespace="http://www.mycompany.com/module") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(propOrder={"...", "...", "timeStamp", "...", "..."}) public class MyEntity ... @XmlElement(namespace="http://www.mysite.com/module") @XmlJavaTypeAdapter(XSDDateTimeMarshaller.class) @NotNull @Type(type="org.joda.time.contrib.hibernate.PersistentDateTime") @Column(name="TIME_STAMP") private DateTime timeStamp; ... } 

3.)为myentity.xsd添加类型绑定

              ...  ....       

这是一个非注释Joda解决方案。 我们已经从xsd生成了对象,并希望它们使用Joda而不是XmlGregorianCalendar。

注意:当我尝试将正确的XmlGregorianCalendar对象传递给类中的unmarshal方法时,我得到了JaxB编译器错误,表示它需要类型String,而不是XmlGregorianCalendar。 用String测试,它似乎工作正常。 这里有快速而肮脏的error handling,所以请随意修复。

希望这可以帮助。

Maven pom插件片段:

   org.jvnet.jaxb2.maven2 maven-jaxb2-plugin  src/main/resources/schemas/ true  jaxb-custom-bindings.xml      generate     

jaxb-custom-bindings.xml文件:

       

 public class XSDDateTimeToJodaDateTimeMarshaller { private static final Logger LOG = LoggerFactory.getLogger(XSDDateTimeToJodaDateTimeMarshaller.class); public static DateTime unmarshal(String xmlGregorianCalendar) { DateTime result= new DateTime(xmlGregorianCalendar); return result; } public static String marshal(DateTime dateTime) { String result = "MARSHALLING_ERROR"; try { result = DatatypeFactory.newInstance().newXMLGregorianCalendar(dateTime.toGregorianCalendar()).toXMLFormat(); } catch (DatatypeConfigurationException e) { LOG.error("Error marshalling Joda DateTime to xmlGregorianCalendar",e); } return result; } 

}

  public class XSDDateToJodaLocalDateMarshaller { private static final Logger LOG = LoggerFactory.getLogger(XSDDateToJodaLocalDateMarshaller.class); public static LocalDate unmarshal(String xmlGregorianCalendar) { return new LocalDate(xmlGregorianCalendar); } public static String marshal(LocalDate localDate) { String result = "MARSHALLING_ERROR"; try { result = DatatypeFactory.newInstance().newXMLGregorianCalendar(localDate.toDateTimeAtStartOfDay().toGregorianCalendar()).toXMLFormat(); } catch (DatatypeConfigurationException e) { LOG.error("Error marshalling Joda LocalDate to xmlGregorianCalendar",e); } return result; } }