JAX-WS et Joda-Time?

Comment écrire un service JAX-WS pour que le @ WebParam de ma méthode @WebMethod soit un Joda-Time class comme DateTime? Est-ce que @XmlTypeAdapter fonctionne sur un paramètre? Je me déploie sur GlassFish 2.1.

permettez-moi de clarifier la question parce que les deux réponses jusqu'à présent ont porté sur la fixation de types personnalisés aux classes JAXB existantes, ce qui est lié mais pas la question que je pose. Comment faire pour que le @WebService suivant accepte les objets Joda DateTime comme paramètres?

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

}
12
demandé sur jaxzin 2011-02-24 18:51:11

4 réponses

vous devez Annoter le paramètre directement comme ci-dessous (je fais usage de XSDDateTimeMarshaller écrit par @DennisTemper comme l'une des réponses à votre question mais n'hésitez pas à le remplacer par une autre...):

@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
répondu dulon 2014-10-28 18:48:30

premier convertisseur d'écriture simple (en Calendar dans cet exemple, mais peut être facilement changé en 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);
    }

}

ensuite, vous devez présenter votre convertisseur à JAXB ( xjb fichier):

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

dans les modèles JAXB générés xjc produit l'annotation suivante:

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

Adapter2.class est un adaptateur généré qui enveloppe votre convertisseur POJO. Comme vous pouvez le voir Calendar est utilisé à la place de maladroit javax.xml.datatype.XMLGregorianCalendar . Si vous ajustez cet exemple à Joda-Time, veuillez le partager avec nous.

9
répondu Tomasz Nurkiewicz 2011-02-24 22:35:00

modèle de solution de suivi de puits ci-dessus

1.) Créer un adaptateur 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.) Annoter l'attribut jodatime avec (snipet d'une classe entity):

...

@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.) ajouter des fixations de type à votre 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>
3
répondu DennisTemper 2011-03-01 17:24:26

Voici une solution de Joda sans annotation. Nous avons généré des objets à partir de xsd et voulons qu'ils utilisent Joda à la place de XmlGregorianCalendar.

Note: quand j'ai essayé de passer un objet xmlgregoriancalendar correct aux méthodes unmarshal dans les classes, j'ai eu des erreurs de compilateur JaxB qui ont dit qu'il nécessitait une chaîne de caractères, pas XmlGregorianCalendar. Testé Avec String, et il semble bien fonctionner. Gestion rapide et sale des erreurs ici, alors arrangez ça comme vous voulez.

Espérons que cette aide.

pom Maven plugin extrait:

       <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-liaisons.fichier 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;
}
}
1
répondu Ed J 2012-03-08 05:45:15