Java JAX-WS和Joda时间?
如何编写JAX-WS服务,使@WebMethod的@WebParam成为类似DateTime的Joda时间类?参数上的@XmlTypeAdapter是否有效?我正在部署GlassFish 2.1 让我澄清这个问题,因为到目前为止,这两个答案都集中在将自定义类型绑定到现有JAXB类上,这是相关的,但不是我要问的问题。如何使以下@WebService接受joda DateTime对象作为参数Java JAX-WS和Joda时间?,java,soap,jax-ws,jodatime,Java,Soap,Jax Ws,Jodatime,如何编写JAX-WS服务,使@WebMethod的@WebParam成为类似DateTime的Joda时间类?参数上的@XmlTypeAdapter是否有效?我正在部署GlassFish 2.1 让我澄清这个问题,因为到目前为止,这两个答案都集中在将自定义类型绑定到现有JAXB类上,这是相关的,但不是我要问的问题。如何使以下@WebService接受joda DateTime对象作为参数 import javax.jws.WebMethod; import javax.jws.WebParam;
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
);
}
首先编写简单的转换器(在本例中为日历,但可以轻松更改为Joda Time): 接下来,您必须将转换器引入JAXB(
xjb
file):
其中,
Adapter2.class
是一个生成的适配器,用于封装POJO转换器。如您所见,使用了Calendar
而不是笨拙的javax.xml.datatype.xmlgoriiancalendar
。如果您将此示例调整为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<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());
}
}
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>
...
....
这是一个非注释Joda解决方案。我们已经从xsd生成了对象,希望它们使用Joda而不是XmlGregorianCalendar
注意:当我试图向类中的unmarshal方法传递一个适当的XmlGregorianCalendar对象时,我得到了JaxB编译器错误,它说它需要类型字符串,而不是XmlGregorianCalendar。使用字符串进行测试,它似乎工作正常。这里的错误处理又快又脏,所以请随意修复
希望这有帮助
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>
}
您必须直接对参数进行注释,如下所示(我使用@DennisTemper编写的XSDDateTimeMarshaller作为您问题的答案之一,但请随意替换为另一个…:
因为我是用JAXB注释手工编写Java类的,所以我假设在相反的方向上不存在任何问题,同时跳过xjb文件?还有一点,您重复了很容易找到的映射JAXB类字段的示例,但我的问题是关于通过JAX-WS注释作为SOAP服务公开的方法的参数。您是否有过JAXB类型在该上下文中适应的经验或示例?请查看我更新的问题,我认为我在最初编写时措辞不正确。感谢您的尝试,但我正在寻找问题的答案,如前所述,这是一个可以接受Joda DateTime对象作为(at)的(at)Web服务标签放错地方了,至少今天的maven插件是这样。检查工作示例。它位于内部,但多行xml不适用于注释。
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());
}
}
...
@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;
...
}
<?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>
<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>
<?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;
}
}
@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
);
}