I think what you really need is
to modify the serialization on the AXIS side.
The XML response that you enclosed last time round,
indicates that the toplevel ContainerBean is serialized differently
than any "child" ContainerBeans that it holds. As you pointed out
yourself, on the wire they have different namespaces. They are
defined distinctly in the schema/wsdl. They are really 2 distinct
things. TypeA contains TypeB, where TypeA == ContainerBean, when used as a
toplevel bean, and TypeB== ContainerBean, when contained within a toplevel
bean.
The change you made to the WSDL tells the .NET side - these
two types are the same thing. It tells the .NET side,
There is only one type, it is a type that can contain an array of
instances of itself. But the XML you get on the wire isn't
that. The XML on the wire shows a type that contains an array of
instances of something else (TypeA and TypeB). They use different xml
namespaces, you see, so even though the elements are the same names, .NET
can't/won't deserialize. Therefore telling .NET "these types are the
same thing" doesn't help you. That assertion doesn't agree with the
reality on the wire.
So to fix this
option 1:
- change the WSDL to indicate that all child
ContainerBeans (those that are stored within a toplevel ContainerBean), use a
different xml namespace from toplevel ContainerBeans. FCor child CB's, it
is ""; for toplevel, it is http://soap.session.ip.contextmedia.com .
In other words, change the WSDL to reflect the reality of the XML on the
wire. This is not wholly satisfactory because now the programming model on
.NET side will reflect the reality of the XML - in other words, there will be a
TypeA and a TypeB, and you cannot cast an instance of one to an instance of the
other. Maybe this is ok.
option 2:
- change the AXIS server with various wsdd magic to
serialize toplevel and child ContainerBeans the same way, using the same
namespace. I don't know what that magic might
be. [I think this was your original question.
] This has the added advantage that there will be just
one true ContainerBean type, and instances of toplevel CBs will be of the same
type of any child CBs that they hold.
I changed the wsdl. ContainerBean is now defined as
(my changes are in blue):
<complexType
name="ContainerBean"> <sequence> <element
name="ID" nillable="true"
type="xsd:string"/> <element
name="accessPermissions"
type="xsd:int"/> <element
name="accountID" nillable="true"
type="xsd:string"/> <element
name="childContainers"> <complexType> <sequence> <element
maxOccurs="unbounded" name="item"
type="tns1:ContainerBean"/> </sequence> </complexType> </element> <element
name="creationDate" nillable="true"
type="xsd:dateTime"/> <element
name="deliveryPermissions"
type="xsd:int"/> <element
name="description" nillable="true"
type="xsd:string"/> <element
name="lastModifiedDate" nillable="true"
type="xsd:dateTime"/> <element
name="name" nillable="true"
type="xsd:string"/> <element
name="parentID" nillable="true"
type="xsd:string"/> <element name="type"
type="xsd:int"/> <element name="userID"
nillable="true"
type="xsd:string"/> </sequence> </complexType>
I made my .NET client point to the
modified WSDL. I still get the same error. My .NET client cant serialize the
beans after top level.
I didn't change the java code on server
side though. All I did was changed WSDL manually and added this webreference on
.NET side.
Thx
Praveen
----- Original Message -----
Sent: Wednesday, February 16, 2005 1:08
PM
Subject: Re: array of recursive beans
(doc/literal style)
Try changing your WSDL so there is no additional
ArrayOd_tns1_ContainerBean type.
Basically, the definition
of ContainerBean:
<complexType
name="ContainerBean">
<sequence>
. .
. <element maxOccurs="unbounded"
name="item" type="tns1:ContainerBean"/>
</sequence> </complexType>
Not sure if this is valid though, it's just my
guess.
Eugene
----- Original Message -----
Sent: Wednesday, February 16, 2005
12:39p
Subject: Re: array of recursive beans
(doc/literal style)
Thanks for the response Dino.
I am using Axis rc1.2 nightly build from Feb
8th.
I think you are right regarding desinging the
interfaces. Its better to work on WSDL and schema before working on
java code but I have all the java classes built. These are not new services.
I have all these services for long time and everything was working great
until I moved to doc/literal style. I was using rpc/encoded style
before.
I looked at the WSDL generated by Axis and it
looked fine to me. May be somone can look at my WSDL and see where it is
wrong. Two elements that need to look at are:
<complexType name="ArrayOf_tns1_ContainerBean">
<sequence>
<element maxOccurs="unbounded"
minOccurs="0"
name="item"
type="tns1:ContainerBean" />
</sequence>
</complexType>
AND
<element name="getRootContainersResponse">
<complexType>
<sequence>
<element maxOccurs="unbounded"
name="item"
type="tns1:ContainerBean" />
</sequence>
</complexType>
</element>
Both have the right definitions for array of
beans. Looks like getRootContainerResponse defines namespace properly but
not the ArrayOf_tns1_ContainerBean (look
at the soap response file).
Also, I am attaching the soap response. It
looks like the problem is due to the namespace of each array
element.Namespaces are defined properly for the top level elements
array but for the recursive elements, namespace is
empty.
Any help is appreciated.
Thanks
Praveen
----- Original Message -----
Sent: Wednesday, February 16, 2005
11:59 AM
Subject: RE: array of recursive beans
(doc/literal style)
Is this a v1.2 RC thing, or are you using AXIS v1.1?
And, how
are you designing the interface?
There is a line of thinking that says, if you want
interop, then start by designing the interface in a platform-independent
manner. In other words, WSDL and W3C XML Schema. This
applies whether you are using AXIS, .NET, or something else. Some
people call this "contract first" or "schema-first design".
Schema-first design is a hassle you don't need if you
are doing like-to-like communications. So don't do it.
AXIS-to-AXIS is easy. .NET-to-.NET is
easy. Just define your Interface in actual code (write your
Java interface), specify some magic in the WSDD, and boom, you can
connect.
It's when you want to mix and match clients and
servers that this approach falls down. Simple cases are ok, but
nested arrays and structs don't work. In other
words, starting with a .net server-side class and expecting the
dynamically-generated WSDL to give good interop with an AXIS client, is
wishful thinking. Likewise for the converse. or any other
combination of unlike webservices stacks.
It sounds like you started with a Java class, and you
are using Java2WSDL on it. I would suggest that you start with the
schema and WSDL, then generate the server-side Java interfaces and support
classes with WSDL2Java. Then provide the server-side
implementations. You may need adapters between the classes generated
from the schema, and the existing application on the server
side.
Likewise, generate the .NET (client-side) proxies
from the WSDL.
-Dino
MS
I have a method getRootContainers that
returns array of ContainerBean[]. Each ContainerBean has reference to an
array of child ContainerBean[]. With Eugene's help I could make the array
stuff work. the method sucessfully returns the array of COntainerBean[]
and .NET reads it fine. But .NET client doesn't read them recursively. It
only build the top level array fine but each ContainerBean has array of
other ContainerBean. My service in wsdd looks as follows:
<service name="CMISOAPContainerService" provider="java:RPC"
style="wrapped" use="literal">
<parameter name="allowedMethods" value="copyContainer
createContainer deleteContainer getContainer getContainerIcon
getContainerProperties getRootContainers getContainerObjects
getContentObjectsForContainer getRootContainers moveContainer
updateContainer createQueryContainer updateQueryContainer
createTaxonomy"/>
<parameter name="scope" value="session"/>
<parameter name="className"
value="com.contextmedia.ip.session.soap.CMISOAPContainerService"/>
<operation name="getRootContainers" qname="ns:getRootContainers"
xmlns:ns="http://soap.session.ip.contextmedia.com"
returnQName="ns:item" returnType="ns:ContainerBean[]" >
<parameter name="depth" qname="ns:depth"
type="xsd:int" mode="IN" />
</operation>
<typemapping
languageSpecificType="java:com.contextmedia.ip.session.soap.ContainerBean[]"
qname="soapenc:Array"
deserializer="org.apache.axis.encoding.ser.ArrayDeserializerFactory"
serializer="org.apache.axis.encoding.ser.ArraySerializerFactory"
encodingStyle=""
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"/>
<beanMapping qname="bean:ContainerBean"
xmlns:bean="http://soap.session.ip.contextmedia.com"
languageSpecificType="java:com.contextmedia.ip.session.soap.ContainerBean"/>
</service>
I had to add <operation> and
<typeMapping> tags after seeing Eugene's sample. w/o those two tags,
even the first level of ContainerBean[] was not working.
Not sure what else I am missing, How do I
make the recursive bean stuff work? Is there any special configuration in
WSDD file to make array of recursive beans work.
Thanks,
Praveen
**************************************************************
Praveen Peddi Sr Software Engg, Context Media, Inc.
email:[EMAIL PROTECTED] Tel: 401.854.3475
Fax: 401.861.3596 web: http://www.contextmedia.com
**************************************************************
Context Media- "The Leader in Enterprise Content Integration"
|