如何编写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
);
}
答案 0 :(得分:9)
首先编写简单转换器(在此示例中为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
文件):
<globalBindings>
<javaType
name="java.util.Calendar"
xmlType="xs:dateTime"
parseMethod="XsdDateTimeConverter.unmarshal"
printMethod="XsdDateTimeConverter.marshal"
/>
<javaType
name="java.util.Calendar"
xmlType="xs:date"
parseMethod="XsdDateTimeConverter.unmarshal"
printMethod="XsdDateTimeConverter.marshal"
/>
</globalBindings>
在生成的JAXB模型中,xjc
生成了以下注释:
@XmlJavaTypeAdapter(Adapter2.class)
@XmlSchemaType(name = "date")
protected Calendar date;
其中Adapter2.class
是包装POJO转换器的生成适配器。如您所见,Calendar
被用来代替笨拙的javax.xml.datatype.XMLGregorianCalendar
。如果您将此示例调整为Joda-Time,请与我们分享。
答案 1 :(得分:3)
以上解决方案模板
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<Date, DateTime> {
@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
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/XMLSchema http://www.w3.org/2001/XMLSchema.xsd"
targetNamespace="http://www.mysite.com/module"
xmlns:tns="http://www.mysite.com/module"
attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc"
jaxb:version="2.1">
<xsd:annotation>
<xsd:appinfo>
<jaxb:globalBindings>
<jaxb:javaType name="org.joda.time.DateTime"
xmlType="xsd:dateTime"
parseMethod="com.mycompany.myproduct.marshaller.XSDDateTimeMarshaller.unmarshal"
printMethod="com.mycompany.myproduct.marshaller.XSDDateTimeMarshaller.marshal"/>
<jaxb:javaType name="org.joda.time.DateTime"
xmlType="tns:date"
parseMethod="com.mycompany.myproduct.marshaller.XSDDateTimeMarshaller.unmarshal"
printMethod="com.mycompany.myproduct.marshaller.XSDDateTimeMarshaller.marshal"/>
</jaxb:globalBindings>
</xsd:appinfo>
</xsd:annotation>
<xsd:element name="MyEntity" type="tns:MyEntity"/>
<xsd:complexType name="MyEntity">
<xsd:sequence>
...
<xsd:element name="timeStamp" type="tns:date"/>
....
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="date">
<xsd:restriction base="xsd:dateTime" />
</xsd:simpleType>
</xsd:schema>
答案 2 :(得分:3)
您必须直接注释参数,例如下面的内容(我正在使用@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
);
}
答案 3 :(得分:1)
这是一个非注释Joda解决方案。我们已经从xsd生成了对象,并希望它们使用Joda而不是XmlGregorianCalendar。
注意:当我尝试将正确的XmlGregorianCalendar对象传递给类中的unmarshal方法时,我得到了JaxB编译器错误,表示它需要类型String,而不是XmlGregorianCalendar。用String测试,它似乎工作正常。这里处理快速而肮脏的错误,所以请随意修复。
希望这有帮助。
Maven pom插件片段:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<configuration>
<schemaDirectory>src/main/resources/schemas/</schemaDirectory>
<removeOldOutput>true</removeOldOutput>
<bindingIncludes>
<bindingInclude>jaxb-custom-bindings.xml</bindingInclude>
</bindingIncludes>
</configuration>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
jaxb-custom-bindings.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<globalBindings>
<javaType
name="org.joda.time.DateTime"
xmlType="xs:dateTime"
parseMethod="com.yourcompanyname.XSDDateTimeToJodaDateTimeMarshaller.unmarshal"
printMethod="com.yourcompanyname.XSDDateTimeToJodaDateTimeMarshaller.marshal"
/>
<javaType
name="org.joda.time.LocalDate"
xmlType="xs:date"
parseMethod="com.yourcompanyname.XSDDateToJodaLocalDateMarshaller.unmarshal"
printMethod="com.yourcompanyname.XSDDateToJodaLocalDateMarshaller.marshal"
/>
</globalBindings>
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;
}
}