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