JAX-WS и Joda-Time?
Как написать службу JAX-WS, чтобы @WebParam моего @WebMethod был классом Joda-Time, например DateTime? Будет ли @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
);
}
Ответы
Ответ 1
Вы должны аннотировать параметр напрямую, например, ниже (я использую XSDDateTimeMarshaller, написанный @DennisTemper как один из ответов на ваш вопрос, но не стесняйтесь заменить другим...):
@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
);
}
Ответ 2
Сначала напишите простой конвертер (до 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, поделитесь им с нами.
Ответ 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.) Аннотировать атрибут jodatime с (snipet из класса сущности):
...
@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>
Ответ 4
Здесь не аннотированное решение Джоды. Мы создали объекты из xsd и хотим, чтобы они использовали Joda вместо XmlGregorianCalendar.
Примечание. Когда я попытался передать надлежащий объект XmlGregorianCalendar методам unmarshal в классах, у меня появились ошибки компилятора JaxB, в которых говорилось, что для него требуется тип String, а не 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>
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;
}
}