Thanks, However, when running wsdl2java, I can't see any trace of the elements, and
I'm also pretty sure the static typedescriptions in my generated classes are not affected by the element declarations, meaning that the xml serialization is unaffected by the presence of the <element> tags in my WSDL/XSD. Of course I might be wrong here, but I will definitely check it out. ________________________________________ From: Anne Thomas Manes [mailto:[EMAIL PROTECTED] Sent: 25. januar 2006 17:05 To: [email protected] Subject: Re: (Sorry) Client side serialization of abstract types. (Was: Complex problem) You need to specify the types for these two elements: <xs:element name="CreateDigitalCameraParameters" substitutionGroup="gb:CreateItemDefinition"/> <xs:element name="CreateComputerParametersType" substitutionGroup="gb:CreateItemDefinition"/> Anne On 1/25/06, glenn bech <[EMAIL PROTECTED]> wrote: (Sorry for the premature send) Following the idea outlined here http://www.xfront.com/ElementHierarchy.html I have an object hiearachy and are trying to create a JAX-RPC service using axis 1.3 However I believe Axis generates wrong code for serialization. Have anyone else seen this before? The element Create>>ItemAttributes can hold any element extending the AbstractCreateItemDefinition type. However, on serialization things go wrong, and the client sends the server XML like this ; <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/ " xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance "> <soapenv:Body> <Create xmlns="http://www.glennbech.com/abstractiontest/abstract/"> <ItemType xsi:type="xsd:string" xmlns=""> [EMAIL PROTECTED]</ItemType> <ItemID xsi:type="xsd:int" xmlns="">1</ItemID> <ItemAttributes xmlns=""> <ns1:CreateItemDefinition xsi:type="ns1:AbstractCreateItemDefinition" xmlns:ns1="http://www.glennbech.com/abstractiontest/abstract/"/> </ItemAttributes> </Create> </soapenv:Body> </soapenv:Envelope> I think this is due to the Typedescription generated for the class CreateItemAttributes: static { typeDesc.setXmlType(new javax.xml.namespace.QName(" http://www.glennbech.com/abstractiontest/abstract /", ">>Create>ItemAttributes")); org.apache.axis.description.ElementDesc elemField = new org.apache.axis.description.ElementDesc (); elemField.setFieldName("createItemDefinition"); elemField.setXmlName(new javax.xml.namespace.QName("http://www.glennbech.com/abstractiontest/abstract /", "CreateItemDefinition")); elemField.setXmlType(new javax.xml.namespace.QName("http://www.glennbech.com/abstractiontest/abstract /", "AbstractCreateItemDefinition")); elemField.setNillable(false); typeDesc.addFieldDesc(elemField); } Any Ideas ? WSDL <definitions xmlns=" http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:http=" http://schemas.xmlsoap.org/wsdl/http/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soapenc=" http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:gb="http://www.glennbech.com/abstractiontest/abstract/" targetNamespace=" http://www.glennbech.com/abstractiontest/abstract/"> <import namespace="http://www.glennbech.com/abstractiontest/abstract/" location="abstract.xsd"/> <import namespace="http://www.glennbech.com/abstraction/concrete/" location="concrete.xsd"/> <message name="CreateRequest"> <part name="parameters" element="gb:Create"/> </message> <message name="CreateResponse"> <part name="parameters" element="gb:CreateResponse"/> </message> <portType name="Provisioning"> <operation name="create"> <input message="gb:CreateRequest"/> <output message="gb:CreateResponse"/> </operation> </portType> <binding name="Provisioning" type="gb:Provisioning"> <soap:binding style="document" transport=" http://schemas.xmlsoap.org/soap/http"/> <operation name="create"> <soap:operation soapAction="gb#Create" style="document"/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="Provisioning"> <port name="Provisioning" binding="gb:Provisioning"> <soap:address location="http://localhost:8888/axis/services/Provisioning"/> </port> </service> </definitions>' Abstract.xsd <xs:schema targetNamespace="http://www.glennbech.com/abstractiontest/abstract/" xmlns=" http://www.glennbech.com/abstractiontest/abstract/" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:complexType name="AbstractCreateItemDefinition" abstract="true"/> <xs:element name="CreateItemDefinition" type="AbstractCreateItemDefinition" abstract="true"/> <xs:element name="CreateResponse" type="xs:int"/> <xs:element name="Create"> <xs:complexType> <xs:sequence> <xs:element name="ItemType" type="xs:string"/> <xs:element name="ItemID" type="xs:int"/> <xs:element name="ItemAttributes" minOccurs="0"> <xs:complexType> <xs:sequence> <xs:element ref="CreateItemDefinition"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema> Concrete.xsd <xs:schema targetNamespace=" http://www.glennbech.com/abstractiontest/concrete/" xmlns="http://www.glennbech.com/abstractiontest/concrete/" xmlns:gb=" http://www.glennbech.com/abstractiontest/abstract/" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:complexType name="CreateComputerParametersType"> <xs:complexContent> <xs:extension base="gb:AbstractCreateItemDefinition"> <xs:sequence> <xs:element name="cpu_speed" type="xs:int"/> <xs:element name="mb_ram" type="xs:int"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="CreateDigitalCameraParametersType"> <xs:complexContent> <xs:extension base="gb:AbstractCreateItemDefinition"> <xs:sequence> <xs:element name="megapixels" type="xs:int"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:element name="CreateDigitalCameraParameters" substitutionGroup="gb:CreateItemDefinition"/> <xs:element name="CreateComputerParametersType" substitutionGroup="gb:CreateItemDefinition"/> </xs:schema> ________________________________________ From: Anne Thomas Manes [mailto:[EMAIL PROTECTED] Sent: 24. januar 2006 14:21 To: [email protected] Subject: Re: Complex problem The use of a substitutionGroup combined with an abstract type allows you to do what you want: change both the name and type of the element. A subtitutionGroup allows you to change the name of an element, but the type of a substitutionGroup element must be the same as the original element, or it must be derived from type of the original element. Using abstract types lets you also change the element type. An alternative solution is to use the <choice> compositor. If you'd like to read up a little more on substitution groups and abstract types, see: http://www.w3schools.com/schema/schema_complex_subst.asp http://www.w3.org/TR/xmlschema-0/#SubsGroups http://www.zvon.org/xxl/XMLSchemaTutorial/Output/ser_substitution_st0.html http://www.xml.com/pub/a/2000/11/29/schemas/part1.html?page=7 (page down a bit) http://www.xfront.com/ElementHierarchy.html Regards, Anne On 1/24/06, glenn bech <[EMAIL PROTECTED]> wrote: Hi Anne, thank you for looking into my case, I can see from the mailing list that you're one of the ones pulling the load around here.-) Anyways ; I realize now that the substitutiongroup attribute belongs to elements, and not types. Personally, I'm a bit confused about the use of *both* in my case, the abstract schema I have to work with require me to use an xs:extension, and put the element in a substitution group. However, it is "company policy" and I cannot get around it. Question; Is it "common" to both use Substitution groups and abstract types as in my case ? Question; Since substitution groups belong to elements only, I cannot see how it affects Axis at all, as to my knowledge the WSDL2Java generator only spits our classes related to the Types I define, and I find noe trace in the classe's typedesc's of the substitution groups. Am I Missing something? ________________________________________ From: Anne Thomas Manes [mailto:[EMAIL PROTECTED] Sent: 23. januar 2006 14:20 To: [email protected] Subject: Re: Complex problem The substitutionGroup attribute is only valid as part of an element definition, not as part of a complexType definition. This: <xs:complexType name="CreateComputerParameters" substitutionGroup="gb:CreateItemDefinition"> <xs:complexContent> <xs:extension base="gb:AbstractCreateItemDefinition"> <xs:sequence> <xs:element name="cpu_speed" type="xs:int"/> <xs:element name="mb_ram" type="xs:int"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> Should be this: <xs:element name="CreateComputerParameters" substitutionGroup="gb:CreateItemDefinition" type="tns:CreateComputerParameters"/> <xs:complexType name="CreateComputeParameters"> <xs:complexContent> <xs:extension base="gb:AbstractCreateItemDefinition"> <xs:sequence> <xs:element name="cpu_speed" type="xs:int"/> <xs:element name="mb_ram" type="xs:int"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> Anne On 1/23/06, glenn bech <[EMAIL PROTECTED]> wrote: Hi All, This is a rather lengthy post, I hope someone will take the time to read it through, as I've been struggling with the problem for a while. It describes a complex, "real life", "business" scenario. This one is for you experts out there! Novices, please skip this post .) Here is a summary; When creating an application with messages involving abstract schema types and substitution groups, Axis as a client serializes messages wrong, ignoring the concrete implementations in the serialization process using the generated base class for serialization". I've currently been assigned to create a so called "provisioning" interface to a company's internal database. In practice, this means making the existing database modifiable through a well defined web services interface. I've been trying out axis, but have some major issues. The company impose a "standard" for data provisioning, that manifests itself as an abstract XML Schema, and an abstract WSDL file. The WSDL file define very generic "Update", "Save" , "Delete" and "Create" messages. It does not specify "what" to "Update", "Save", "Delete" etc. That is deferred to implementations like mine. I've created an identical setup, since I cannot reveal the identity of my customer. First of all, there is a very generic XSD file that I cannot modify, It's part of company policy. It defines a complex type, "AbstractCreateItemDefinition". This is the base message type for all messages that "create" items in the system. The idea is to "extend" this Abstract type with create messages for real items, i.e CreateComputerDefinition, CreateVacumCleanerDefinition. Please also notice the ref="CreateItemDefinition", this is the "magic" that lets us put in any element that "extends" AbstractCreateDefinition here. <xs:schema targetNamespace="http://www.glennbech.com/abstractiontest/abstract/" xmlns=" http://www.glennbech.com/abstractiontest/abstract/" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:complexType name="AbstractCreateItemDefinition" abstract="true"/> <xs:element name="CreateItemDefinition" type="AbstractCreateItemDefinition" abstract="true"/> <xs:element name="Create"> <xs:complexType> <xs:sequence> <xs:element name="ItemType" type="xs:string"/> <xs:element name="ItemID" type="xs:int"/> <xs:element name="ItemAttributes" minOccurs="0"> <xs:complexType> <xs:sequence> <xs:element ref="CreateItemDefinition"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema> <xs:element name="CreateResponse" type="xs:int"/> The WSDL file defines the "Provisioning" port, with only one operation "Create". <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/ " xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xs="http://www.w3.org/2001/XMLSchema " xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/ " xmlns:gb="http://www.glennbech.com/abstractiontest/abstract/" targetNamespace=" http://www.glennbech.com/abstractiontest/abstract/"> <import namespace="http://www.glennbech.com/abstractiontest/abstract/" location="abstract.xsd"/> <import namespace="http://www.glennbech.com/abstraction/concrete/" location="concrete.xsd"/> <message name="CreateRequest"> <part name="parameters" element="gb:Create"/> </message> <message name="CreateResponse"> <part name="parameters" element="gb:CreateResponse"/> </message> <portType name="Provisioning"> <operation name="Create"> <input message="gb:CreateRequest"/> <output message="gb:CreateResponse"/> </operation> </portType> <binding name="Provisioning" type="gb:Provisioning"> <soap:binding style="document" transport=" http://schemas.xmlsoap.org/soap/http"/> <operation name="Create"> <soap:operation soapAction="gb#Create" style="document"/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="Provisioning"> <port name="Provisioning" binding="gb:Provisioning"> <soap:address location="http://localhost:8888/axis/services/Provisioning "/> </port> </service> There is only one XSD that I have to write, that is the one defining the actual Items that I want to provision (Create Update Delete and Get) Please note that they are declared as a part of a substitution group gb:CreateItemDefinition, matching the "ref" defined in the abstract XML schema listed previously,. <xs:schema targetNamespace=" http://www.glennbech.com/abstractiontest/concrete/" xmlns=" http://www.glennbech.com/abstractiontest/concrete/ " xmlns:gb="http://www.glennbech.com/abstractiontest/abstract/" xmlns:xs=" http://www.w3.org/2001/XMLSchema "> <xs:complexType name="CreateComputerParameters" substitutionGroup="gb:CreateItemDefinition"> <xs:complexContent> <xs:extension base="gb:AbstractCreateItemDefinition"> <xs:sequence> <xs:element name="cpu_speed" type="xs:int"/> <xs:element name="mb_ram" type="xs:int"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="CreateDigitalCameraParameters" substitutionGroup="gb:CreateItemDefinition"> <xs:complexContent> <xs:extension base="gb:AbstractCreateItemDefinition"> <xs:sequence> <xs:element name="megapixels" type="xs:int"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> </xs:schema> I run WSDL2Java on the WSDL file wsdl2java -S -s -W -D -a -o src\ web\abstract.wsdl ...successfully. Everything looks very nice. CreateConmputerParameters are generated to extend the abstract class. Generated files are listed here. Directory of C-.....\src\com\glennbech\www\abstractiontest\concrete 23.01.200611:21<DIR>. 23.01.200611:21<DIR>.. 23.01.200611:21 4573 CreateComputerParameters.java 23.01.200611:21 3730 CreateDigitalCameraParameters.java 2 File(s)8303 bytes Directory of C:\.....\src\com\glennbech\www\abstractiontest\_abstract 23.01.200611:48<DIR>. 23.01.200611:48<DIR>.. 23.01.200611:21 2524 AbstractCreateItemDefinition.java 23.01.200611:42 6009 Create.java 23.01.200611:21 4315 CreateItemAttributes.java 23.01.200611:21 3973 deploy.wsdd 23.01.200611:21 492 Provisioning_BindingImpl.java 23.01.200611:2110686 Provisioning_BindingStub.java 23.01.200611:21 408 Provisioning_PortType.java 23.01.200611:21 646 Provisioning_Service.java 23.01.200611:21 5703 Provisioning_ServiceLocator.java 23.01.200611:48 901 test.xml 23.01.200611:21 682 undeploy.wsdd So I write a test class that invokes a call the service public static void main(String[] args) throws Exception { final String nsURI = " http://www.glennbech.com/abstractiontest/abstract/"; final String serviceName = "Provisioning"; final String endPointURI = " http://localhost:8888/axis/services/Provisioning"; final String wsdlURI = " http://localhost:8888/axis/abstract.wsdl"; ServiceFactory serviceFactory = ServiceFactory.newInstance(); Service provisioningService = serviceFactory.createService(new URL(wsdlURI), new QName(nsURI, serviceName)); Provisioning_BindingStub stub = new Provisioning_BindingStub(new URL(endPointURI), provisioningService); final int mhz = 3600; final int mbRam = 1024; // This is the really interesting line Create createComputer = new Create("[EMAIL PROTECTED] ", 1, new Crea teItemAttributes(new CreateComputerParameters(mhz, mbRam))); stub.create(createComputer); } I deploy the service adminclient -l http://localhost:9999/axis/services/AdminService src\com\glennbech\www\abstractiontest\_abstract\deploy.wsdd Now the trouble arrives... The Axis client side does not serialize my request object correctly. It does not recognize that I've actually constructed my "create" message with a CreateComputerParameters, but uses the abstract class as a base for Serialization. xis/services/Provisioning HTTP/1.0 Content-Type: text/xml; charset=utf-8 Accept: application/soap+xml, application/dime, multipart/related, text/* User-Agent: Axis/1.3 Host: localhost:8888 Cache-Control: no-cache Pragma: no-cache SOAPAction: "gb#Create" Content-Length: 543 <?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/ " xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance "> <soapenv:Body> <Create xmlns="http://www.glennbech.com/abstractiontest/abstract/"> <ItemType xmlns=""> [EMAIL PROTECTED]</ItemType> <ItemID xmlns="">1</ItemID> <ItemAttributes xmlns=""> <ns1:CreateItemDefinition xmlns:ns1=" http://www.glennbech.com/abstractiontest/abstract/"/> </ItemAttributes> </Create> </soapenv:Body> As you can see, the "Create" element has a nested "ItemAttributes" element, that again nest a "CreateItemDefinition" instead of the "CreateComputerParameters" that should have been serialized. Is this setup too complex for Axis to handle? Is this setup just to compelx in general? Should I call the standards department at my customer's company and tell them to re-define the provisioning standard so it is possible to implement it ? All Advice are welcome ! Best regards, Glenn Bech
