If you are handling a legacy system, using Axis (1.4) webservices you must have come across Java2WSDL and WSDL2Java tools. The tools help you to generate a WSDL from a java class as well as generating stubs/skeletons from a WSDL. However if are dealing with <code>java.util.Date</code> fields in your code, you should notice following :


package com.aminur.test.ws.axis1.dateservice;

import java.util.Date;

public abstract class TestService {
	public abstract Date fetchEndDate();

	public void updateEndDate(Date dateToBeSet) {
	}
}

Now if you will use Java2WSDL like below :(ignore the variables in the attribute. Entire project is attached in end of post)

<target name="generate-wsdl" depends="init">
		<mkdir dir="wsdl" />
		<delete file="wsdl/${wsdl.name}" />
		<axis-java2wsdl classname="${basepackage}.TestService" style="wrapped" namespace="${service.namespace}" output="wsdl/${wsdl_nocustomize.name}" location="http://localhost:5000/services/TestConfiguration" porttypename="TestConfiguration" serviceelementname="TestService">
			<classpath refid="library.classpath" />
		</axis-java2wsdl>
	</target>
</textarea> 
<font color="navy">you will find wsdl as something like below:
<textarea name="code" class="xml" cols="80" rows="15"> 
 <element name="fetchEndDate">
    <complexType/>
   </element>
   <element name="fetchEndDateResponse">
    <complexType>
     <sequence>
      <element name="fetchEndDateReturn" type="xsd:dateTime"/>
     </sequence>
    </complexType>
   </element>
   <element name="updateEndDate">
    <complexType>
     <sequence>
      <element name="in0" type="xsd:dateTime"/>
     </sequence>
    </complexType>
   </element>
   <element name="updateEndDateResponse">
    <complexType/>
   </element>
  </schema>
 </wsdl:types>

you will find wsdl as something like below:

<element name="fetchEndDate">
    <complexType/>
   </element>
   <element name="fetchEndDateResponse">
    <complexType>
     <sequence>
      <element name="fetchEndDateReturn" type="xsd:dateTime"/>
     </sequence>
    </complexType>
   </element>
   <element name="updateEndDate">
    <complexType><span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"></span>
     <sequence>
      <element name="in0" type="xsd:dateTime"/>
     </sequence>
    </complexType>
   </element>
   <element name="updateEndDateResponse">
    <complexType/>
   </element>
  </schema>
 </wsdl:types>

Notice the xsd type for the return or the parameter. It is dateTime. When this WSDL will be used in target WSDL2Java, then the datatype for the parameter/return type will be changed to java.util.Calendar.

You can change the generated wsdl file manually to replace dateTime with date. However in the automated build process this will be a bottleneck. What I did is customized this generated wsdl file with a xsl style sheet to replace the type of the element. Following is the style sheet I used.


<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1.0">

	<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
	<xsl:strip-space elements="*"/>
	<xsl:template match="node()|@*">
		<xsl:choose>
			<!-- Axis 1 when generates wsdl from java, it converts xsd:date to xsd:datetime and that creates problem as then your WS interface will allow 2009-05-15T09:11:17 as valid entry. -->
			<xsl:when test="name()='element' and @type=('xsd:dateTime') and (@name=('fetchEndDateReturn') or @name=('dateToBeSet') )">
			
			 <element>
				 <xsl:copy-of select="namespace::* | @*[name()!='type']" />
				 <xsl:attribute name="type">xsd:date</xsl:attribute>
			 </element>
			</xsl:when>
			<!-- default behaviour is to copy the stuff -->
			<xsl:otherwise>
				<xsl:copy>
					<xsl:apply-templates select="node()|@*"/>
				</xsl:copy>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
</xsl:stylesheet>

And following is the snippet from build.xml file which uses the xsl to replace dateTime with date.

 
<target name="generate-wsdl-with-customization" depends="compile_with_debug">
		<mkdir dir="tmp" />
		<mkdir dir="wsdl" />
		<delete file="wsdl/${wsdl.name}" />
		<axis-java2wsdl classname="${basepackage}.TestService" style="wrapped" namespace="${service.namespace}" output="tmp/${wsdl.name}" location="http://localhost:5000/services/TestConfiguration" porttypename="TestConfiguration" serviceelementname="TestService">
			<classpath refid="library.classpath" />
		</axis-java2wsdl>
		<xslt force="true" basedir="tmp" destdir="wsdl" extension=".wsdl" style="customize.xsl" includes="*.wsdl" />
		<delete dir="tmp" />
	</target>

The wsdl file snippet generated after customization (and after compiling the abstract class in debug mode) is as below

 
<element name="fetchEndDate">
    <complexType/>
   </element>
   <element name="fetchEndDateResponse">
    <complexType>
     <sequence>
      <element name="fetchEndDateReturn" type="xsd:date"/>
     </sequence>
    </complexType>
   </element>
   <element name="updateEndDate">
    <complexType>
     <sequence>
      <element name="dateToBeSet" type="xsd:date"/>
     </sequence>
    </complexType>
   </element>
   <element name="updateEndDateResponse">
    <complexType/>
   </element>
  </schema>
 </wsdl:types>

Now the last part remaining is the insertion of following code in your server-config.wsdd as child of your service. This is required, to assign the correct (De)Serializer to the element.

<typeMapping xmlns:ns="http://www.w3.org/2001/XMLSchema" qname="ns:date" type="java:java.util.Date" serializer="org.apache.axis.encoding.ser.DateSerializerFactory" deserializer="org.apache.axis.encoding.ser.DateDeserializerFactory" encodingStyle="" /><span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"></span>