开发者

How do I represent dates without the timezone using Apache CXF?

开发者 https://www.devze.com 2023-03-08 10:40 出处:网络
I have a WSDL that specifies an element\'s type to be xs:date. When I use Apache CXF to generate the Java classes, it renders the variable as an javax.xml.datatype.XMLGregorianCalendar (all good so f

I have a WSDL that specifies an element's type to be xs:date.

When I use Apache CXF to generate the Java classes, it renders the variable as an javax.xml.datatype.XMLGregorianCalendar (all good so far).

When CXF renders an XML document containing this, it renders it in th开发者_如何学运维is form (where -06:00 represents the time zone):

2000-01-18-06:00

How can I configure CXF not to render the timezone?


GregorianCalendar gcal = new GregorianCalendar();
start = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);
start.setTimezone(DatatypeConstants.FIELD_UNDEFINED);

Don't ask me why in every bit of the sane logic - when marshalling the XMLgregorianCalendar to xs:date it retains the time zone.

I always thought - the time zone could be more applicable to xs:dateTime, but what I know ... about types.

For me, it doesn't make sense to have the time zone by default, for a xs:date type and this is a problem in the marshalling logic.


To complete Filip answer (thanks to him!), maybe it will help some of you ...

I had to declare a new XmlAdapter on the concern field date with the annotation @XmlJavaTypeAdapter

public class YourDTO {
   // ... 
   @XmlElement
   @XmlSchemaType(name = "dateTime")
   @XmlJavaTypeAdapter(type = XMLGregorianCalendar.class, value = XmlDateAdapter.class)
   public Date yourDate;
   // ...
}

The adapter

public class XmlDateAdapter extends XmlAdapter<XMLGregorianCalendar, Date> {

@Override
public XMLGregorianCalendar marshal(Date date) throws Exception {
    GregorianCalendar gcal = new GregorianCalendar();
    gcal.setTime(date);
    XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);
    xmlDate.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
    return xmlDate;
}
// ...

SOAP message date format before

2017-04-18T00:00:00+02:00

SOAP message date format after

2017-04-18T00:00:00


By default wsdl's xsd:date gets mapped to XMLGregorianCalendar. If this is not what you want then if you are using CXF's wsdl to java tool then you can provide a binding file to override this default mapping:

<jaxws:bindings wsdlLocation="YOUR_WSDL_LOCATION"
          xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
          xmlns:xs="http://www.w3.org/2001/XMLSchema"
          xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
          xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <jaxws:bindings  node="wsdl:definitions/wsdl:types/xs:schema[@targetNamespace='THE_NAMESPACE_OF_YOUR_SCHEMA']">
      <jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <jxb:javaType name="java.util.Date" xmlType="xs:date"
                      parseMethod="org.apache.cxf.tools.common.DataTypeAdapter.parseDate"
                      printMethod="org.apache.cxf.tools.common.DataTypeAdapter.printDate"/>
      </jxb:globalBindings>
  </jaxws:bindings>
</jaxws:bindings>

You can refer to http://cxf.apache.org/docs/wsdl-to-java.html section "How to map xsd:dateTime to java.util.Date?" for more details.


I found my comment above from 2012 and now I feel compelled to add an answer. I'm making some changes to a web service that, unfortunately, must continue to run on Java 6. I was asked to suppress the timezone/offset portion of all date and time fields in my XML responses. I did this with a JAXB binding file and 3 pairs of adapter methods for date, time and datetime XML types. Note that my solution uses the JodaTime library.

Here is my JAXB 2.1 binding file:

<?xml version="1.0" encoding="UTF-8"?>
<bindings 
        xmlns="http://java.sun.com/xml/ns/jaxb" 
        version="2.1"
        xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <globalBindings>
        <javaType 
            name="org.joda.time.DateTime"
            xmlType="xs:dateTime"
            parseMethod="com.jimtough.jaxb.DataTypeCondapter.parseDateTime"
            printMethod="com.jimtough.jaxb.DataTypeCondapter.printDateTime" />
        <javaType 
            name="org.joda.time.DateTime"
            xmlType="xs:date"
            parseMethod="com.jimtough.jaxb.DataTypeCondapter.parseDate"
            printMethod="com.jimtough.jaxb.DataTypeCondapter.printDate" />
        <javaType 
            name="org.joda.time.LocalTime"
            xmlType="xs:time"
            parseMethod="com.jimtough.jaxb.DataTypeCondapter.parseTime"
            printMethod="com.jimtough.jaxb.DataTypeCondapter.printTime" />
    </globalBindings>
</bindings>

Here is my Java 6 compatible utility class with the adapter methods:

package com.jimtough.jaxb;

import java.util.Date;

import javax.xml.bind.DatatypeConverter;

import org.joda.time.DateTime;
import org.joda.time.LocalTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;

/**
 * My bizarrely named 'condapter' is a blend of the Java {@code DatatypeConverter}
 * and the Apache CXF {@code DataTypeAdapter} that provides Jodatime {@code DateTime}
 * support instead of {@code java.util.Date}.
 * 
 * @author jtough
 */
public class DataTypeCondapter {

    private DataTypeCondapter() {}

    // Jim Tough - 2017-02-22
    // JodaTime formatters claim to be threadsafe
    private static final DateTimeFormatter DTF_DATE = ISODateTimeFormat.date();
    private static final DateTimeFormatter DTF_DATETIME = ISODateTimeFormat.dateHourMinuteSecondMillis();
    private static final DateTimeFormatter DTF_TIME = ISODateTimeFormat.hourMinuteSecondMillis();

    public static DateTime parseDate(String s) {
        if (s == null) {
            return null;
        }
        Date date = DatatypeConverter.parseDate(s).getTime();
        return new DateTime(date);
    }

    public static String printDate(DateTime dt) {
        if (dt == null) {
            return null;
        }
        return DTF_DATE.print(dt);
    }

    public static LocalTime parseTime(String s) {
        if (s == null) {
            return null;
        }
        Date date = DatatypeConverter.parseTime(s).getTime();
        DateTime dt = new DateTime(date);
        return dt.toLocalTime();
    }

    public static String printTime(LocalTime lt) {
        if (lt == null) {
            return null;
        }
        return DTF_TIME.print(lt);
    }

    public static DateTime parseDateTime(String s) {
        if (s == null) {
            return null;
        }
        Date date = DatatypeConverter.parseDateTime(s).getTime();
        return new DateTime(date);
    }

    public static String printDateTime(DateTime dt) {
        if (dt == null) {
            return null;
        }
        return DTF_DATETIME.print(dt);
    }

}
0

精彩评论

暂无评论...
验证码 换一张
取 消