You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by "McLay, Tony" <To...@COGNOS.com> on 2004/05/20 18:35:28 UTC

Derivation by restriction (of a restriction)

A recent schema change to a web service resulted in an ArrayStoreException. My initial reaction was that it was a simple bug, so I started by constructing a simple test service (see wsdl below). I now think that aligning the xml schema restriction mechanism with OO programming is a much deeper issue. 

Consider:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="badservice.axistests.com" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="badservice.axistests.com" xmlns:intf="badservice.axistests.com" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<wsdl:types>
		<schema targetNamespace="badservice.axistests.com" xmlns="http://www.w3.org/2001/XMLSchema">
			<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
			<simpleType name="BaseType">
				<restriction base="xsd:string"/>
			</simpleType>
			<simpleType name="DerivedType">
				<restriction base="impl:BaseType"/>
			</simpleType>
			<complexType name="ArrayOfBaseType">
				<complexContent>
					<restriction base="soapenc:Array">
						<attribute ref="soapenc:arrayType" wsdl:arrayType="impl:BaseType[]"/>
					</restriction>
				</complexContent>
			</complexType>
		</schema>
	</wsdl:types>
	<wsdl:message name="setTypesResponse">
	</wsdl:message>
	<wsdl:message name="setTypesRequest">
		<wsdl:part name="in0" type="impl:ArrayOfBaseType"/>
	</wsdl:message>
	<wsdl:message name="getTypesResponse">
		<wsdl:part name="getTypesReturn" type="impl:ArrayOfBaseType"/>
	</wsdl:message>
	<wsdl:message name="getTypesRequest">
   </wsdl:message>
	<wsdl:portType name="BadService">
		<wsdl:operation name="setTypes" parameterOrder="in0">
			<wsdl:input message="impl:setTypesRequest" name="setTypesRequest"/>
			<wsdl:output message="impl:setTypesResponse" name="setTypesResponse"/>
		</wsdl:operation>
		<wsdl:operation name="getTypes">
			<wsdl:input message="impl:getTypesRequest" name="getTypesRequest"/>
			<wsdl:output message="impl:getTypesResponse" name="getTypesResponse"/>
		</wsdl:operation>
	</wsdl:portType>
	<wsdl:binding name="BadServiceSoapBinding" type="impl:BadService">
		<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
		<wsdl:operation name="setTypes">
			<wsdlsoap:operation soapAction=""/>
			<wsdl:input name="setTypesRequest">
				<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="badservice.axistests.com" use="encoded"/>
			</wsdl:input>
			<wsdl:output name="setTypesResponse">
				<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="badservice.axistests.com" use="encoded"/>
			</wsdl:output>
		</wsdl:operation>
		<wsdl:operation name="getTypes">
			<wsdlsoap:operation soapAction=""/>
			<wsdl:input name="getTypesRequest">
				<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="badservice.axistests.com" use="encoded"/>
			</wsdl:input>
			<wsdl:output name="getTypesResponse">
				<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="badservice.axistests.com" use="encoded"/>
			</wsdl:output>
		</wsdl:operation>
	</wsdl:binding>
	<wsdl:service name="BadServiceService">
		<wsdl:port binding="impl:BadServiceSoapBinding" name="BadService">
			<wsdlsoap:address location="http://localhost:9300/axis/services/BadService"/>
		</wsdl:port>
	</wsdl:service>
</wsdl:definitions>


The schema will allow me to enter the DerivedType into an ArrayOfBaseType (validates according to xml schema). However, generating the server code (and client test case) does not allow this use. In fact in the generated java code, BaseType does not extend String (can't anyway - its final), and DerivedType does not extend BaseType. The service methods are defined in terms of the BaseType: e.g. 
	public void setTypes(BaseType[] in0) throws RemoteException;
	public BaseType[] getTypes() RemoteException;

and so there is no way to pass in an array of DerivedType's.

Likewise, the generated client testcase uses the BaseType, and I cannot write something like the following:
	DerivedType derivedType = new DerivedType();
	...
	binding.setTypes(new com.axistests.badservice.BaseType[]{derivedType});//WRONG - CAN'T DO THIS

The ArrayStoreException surfaces if you don't use the generated service api, but create your own axis service, create a MessageContext and Message using the derived type, and invoke the service directly with the context - falls over in JavaUtils, when an Attempt is made to store a DerivedType into an array of BaseType (basically the same 'type' problem).

I've been through the mailing lists, and not found anything that has specifically touched this issue (apologies if there is, I am useless at formulating appropriate search expressions). Trawling the internet, it seems that xml schema's derivation by restriction is a bit of a thorny issue in the OO world ('impedance mismatch', 'derivation does not align with inheritance', 'restriction is not a natural concept to OO' etc. etc.). I'm not convinced that one can even draw a parallel between inheritance and derivation in this respect (but xml schema states that subtyping rules apply, and validation backs this up).

So the questions: - is this a bug? is it by design? an executive decision? or am I missing something obvious?

Thanks
Tony 
  
       This message may contain privileged and/or confidential information.  If you have received this e-mail in error or are not the intended recipient, you may not use, copy, disseminate or distribute it; do not open any attachments, delete it immediately from your system and notify the sender promptly by e-mail that you have done so.  Thank you.