6

I am Using CXF to host web services in a Spring context, which makes JAX-WS the default binding. And I'm using Java-First, which means annotated endpoint interfaces and classes.

Since default binding for JAX-WS uses XMLGregorianCalendar class for dates, when I call my web service passing a java.util.Date it is converted to XMLGregorianCalendar on the server.

There are many posts and documentation on how to change this to bind date values to java.util.Date, but all are related to wsdl2java tool, such as:

<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:dateTime"
                      parseMethod="org.apache.cxf.tools.common.DataTypeAdapter.parseDateTime"
                      printMethod="org.apache.cxf.tools.common.DataTypeAdapter.printDateTime"/>
      </jxb:globalBindings>
  </jaxws:bindings>
</jaxws:bindings>

Since I'm using Spring, I'm looking for a way to do this in Spring context configuration files (or CXF configuration files). A snippet of my file:

<jaxws:endpoint id="jaxwsDocumentGroupWsEndpoint" implementor="#documentGroupWsEndpoint" address="/documentGroup">
<!-- SOMETHING TO WRITE HERE TO TELL CXF TO USE java.util.Date ??? -->
</jaxws:endpoint>
Donal Fellows
  • 120,022
  • 18
  • 134
  • 199
Iravanchi
  • 4,969
  • 9
  • 38
  • 54
  • 1
    In case anyone encountered the same problem, I could resolve mine using JAXB annotations. See this question: http://stackoverflow.com/questions/3953433/tell-jaxb-to-unmarshal-xsdatetime-to-date-class-using-annotations – Iravanchi Oct 18 '10 at 07:59
  • Can you be more specific, about what artifact you want to customize? If it is JAX-WS artifact (SEI), than provide a Java code for the interface. Or if that is JAXB bean, show us the generated code. – dma_k Nov 21 '11 at 16:50

1 Answers1

5

The solution for your problem is hidden into class generation.

You should generate your classes with the following binding:

<jaxb:globalBindings generateMixedExtensions="true">
        <jaxb:javaType 
            name="java.util.Calendar" 
            xmlType="xs:dateTime"           
            parseMethod="com.test.DataTypeBinder.unmarshalDateTime" 
            printMethod="com.test.DataTypeBinder.marshalDateTime" />

</jaxb:globalBindings>

And include in your class path the following class:

public class DataTypeBinder {
private static DateFormat dateTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); 
    private static DateFormat date = new SimpleDateFormat("yyyy-MM-dd"); 

    public static Calendar unmarshalDate(String value) {
        if (value == null || value.length() == 0) {
            return null;
        }
        Date d = null;

        try {
            d = date.parse(value);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } 
        Calendar c = Calendar.getInstance();
        c.setTime(d);
        return c;
    }

    public static  String marshalDate(Calendar value) {
        if (value == null) {
            return null;
        }

        return date.format(value.getTime());
    }   


    public static Calendar unmarshalDateTime(String value) {
        if (value == null || value.length() == 0) {
            return null;
        }
        Date d = null;

        try {
            d = dateTime.parse(value);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } 
        Calendar c = Calendar.getInstance();
        c.setTime(d);
        return c;
    }

}

Then JAXB is going to include in your generated classes the following type declaration:

@XmlElement(type = String.class)
@XmlJavaTypeAdapter(Adapter1 .class)
@XmlSchemaType(name = "dateTime")
protected Calendar transactionDate;
AValchev
  • 1,382
  • 13
  • 15
  • 3
    This solution may work, but may be worth noting that SimpleDateFormat is not thread safe... http://stackoverflow.com/questions/6840803 – Forge_7 Apr 07 '14 at 15:25
  • @Forge_7 is there any trade safe solution ? – kozla13 Aug 26 '14 at 11:51
  • 1
    @kozla13 simply instantiate the SimpleDateFormat as a local variable whenever it is used, rather than store it as a static (or instance) variable. – Forge_7 Aug 27 '14 at 19:33