19 Haziran 2009 Cuma

Troobleshooting: Date becomes XMLGregorianCalendar when stubs are generated at client side, how to prevent this?

The Problem Part:

The environment: Netbeans 6.5 Ide and Glassfish as, on x64 linux machine (open suse).

Here is the sample web service with java.util.Date type:

package com.example.date;

import java.util.Date;

import javax.jws.WebMethod;

import javax.jws.WebParam;

import javax.jws.WebService;

@WebService()

public class DateWebService {

@WebMethod(operationName = "dateOperation")

public Date dateOperation(@WebParam(name = "date")

Date date) {

return date;

}

}

The wsdl is at http://localhost:8080/DateProject/DateWebServiceService?WSDL

The dependent xsd is at http://localhost:8080/DateProject/DateWebServiceService?xsd=1

The input and output types for dateOperation is as follows:

<xs:complexType name="dateOperation">

<xs:sequence>

<xs:element name="date" type="xs:dateTime" minOccurs="0"/>

(<xs:sequence>

</xs:complexType>

<xs:complexType name="dateOperationResponse">

<xs:sequence>

<xs:element name="return" type="xs:dateTime" minOccurs="0"/>

</xs:sequence>

<xs:complexType>

It is obvious that java.util.Date is mapped to xs:dateTime.

Lets see what happens when we generate the client stubs from the wsdl. (This is done by right clicking the project in Netbeans and selecting New Web Service Client and entering the wsdl to the related input.)

The generated stubs are at the following location:



Java.util.Date becomes javax.xml.datatype.XMLGregorianCalendar when xml is mapped to Java types againL (Comments are omitted from the following generated code for simplicity..)

package com.example.date;

import javax.xml.bind.annotation.XmlAccessType;

import javax.xml.bind.annotation.XmlAccessorType;

import javax.xml.bind.annotation.XmlSchemaType;

import javax.xml.bind.annotation.XmlType;

import javax.xml.datatype.XMLGregorianCalendar;

@XmlAccessorType(XmlAccessType.FIELD)

@XmlType(name = "dateOperation", propOrder = {

"date"

})

public class DateOperation {

@XmlSchemaType(name = "dateTime")

protected XMLGregorianCalendar date;

public XMLGregorianCalendar getDate() {

return date;

}


public void setDate(XMLGregorianCalendar value) {

this.date = value;

}

}

The reason for this is explained here: http://forums.java.net/jive/message.jspa?messageID=166006

So, the question is what sould be done to get java.util.Date instead of XMLGregorianCalendar when the stubs are generated at the client side?


The Solution Part:

Data conversion at the client side is a solution: http://www.velocityreviews.com/forums/t462336-convert-jaxb-xmlgregoriancalendar-to-javasqldate.html

However, this may not be the case if you definitely want to get Date back when stubs are generated..

Prepare the following file i named jax-ws-jaxb-customization.xml:


<?xml version="1.0" encoding="UTF-8"?>

<jaxws:bindings  node="wsdl:definitions/wsdl:types/xsd:schema"

                                xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"

                                xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"

                                xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"

                                xmlns:xsd="http://www.w3.org/2001/XMLSchema" wsdlLocation="../wsdl/localhost_8080/DateProject/DateWebServiceService.wsdl">

<jaxb:globalBindings>

                               <jaxb:serializable/>

                               <jaxb:javaType name="java.util.Date"

                                                      xmlType="xsd:dateTime"/>

                </jaxb:globalBindings>

</jaxws:bindings>

Use Netbeans Wsdl Customizer :

Right click the web service under Web Service References, seleck Edit Web Service Attributes and select the second tab named WSDLCustomization

Select the below External Binding File part and add jax-ws-jaxb-customization.xml as follows:

Now, examine the generated stubs again, DateOperation is now as follows (again comments are removed for simplicity):

package com.example.date;

import java.io.Serializable;

import java.util.Date;

import javax.xml.bind.annotation.XmlAccessType;

import javax.xml.bind.annotation.XmlAccessorType;

import javax.xml.bind.annotation.XmlElement;

import javax.xml.bind.annotation.XmlSchemaType;

import javax.xml.bind.annotation.XmlType;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import org.w3._2001.xmlschema.Adapter1;

@XmlAccessorType(XmlAccessType.FIELD)

@XmlType(name = "dateOperation", propOrder = {

"date"

})

public class DateOperation

implements Serializable

{

@XmlElement(type = String.class)

@XmlJavaTypeAdapter(Adapter1 .class)

@XmlSchemaType(name = "dateTime")

protected Date date;

public Date getDate() {

return date;

}

public void setDate(Date value) {

this.date = value;

}

}

And now there is a difference in the generated stubs, an Adapter1 is also generated:

package com.example.date;

import java.io.Serializable;

import java.util.Date;

import javax.xml.bind.annotation.XmlAccessType;

import javax.xml.bind.annotation.XmlAccessorType;

import javax.xml.bind.annotation.XmlElement;

import javax.xml.bind.annotation.XmlSchemaType;

import javax.xml.bind.annotation.XmlType;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import org.w3._2001.xmlschema.Adapter1;

@XmlAccessorType(XmlAccessType.FIELD)

@XmlType(name = "dateOperation", propOrder = {

"date"

})

public class DateOperation

implements Serializable

{

@XmlElement(type = String.class)

@XmlJavaTypeAdapter(Adapter1 .class)

@XmlSchemaType(name = "dateTime")

protected Date date;

public Date getDate() {

return date;

}

public void setDate(Date value) {

this.date = value;

}

}

So, problem solved for now :)

Edit on 22.06.2009  14.15 : The display problem in xml part of the post is fixed by now :)

1 yorum:

  1. see also http://hilaltarakci.blogspot.com/2009/10/revisited-troobleshooting-date-becomes.html

    YanıtlaSil