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

后端 未结 4 2005
暗喜
暗喜 2021-02-04 05:52

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

相关标签:
4条回答
  • 2021-02-04 06:06
    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.

    0 讨论(0)
  • 2021-02-04 06:11

    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 讨论(0)
  • 2021-02-04 06:24

    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.

    0 讨论(0)
  • 2021-02-04 06:30

    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

    0 讨论(0)
提交回复
热议问题