Can a WCF data contract be recursive? For example a binary tree? Is there a difference with ASMX services in supporting recursive data structures? - wcf

In SOA I believe that the wsdl does not support recursive data types but I saw some examples where the proxy actually works. Anybody knows more about this?

Recursive type definitions are allowed and even cyclic object graphs are allowed and serializable. However, in order to keep from running out of stack space while serializing and deserializing, you'll need to create a custom behavior overriding the CreateSerializer method and setting the preserveObjectReferences parameter to true when its creating a DataContractSerializer. See James Kovacs' blog for more.

Please define what you mean by recursive. The following is a valid XML Schema for use in a WSDL:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="Node" type="NodeType"/>
<xs:complexType name="NodeType">
<xs:sequence>
<xs:element name="Node" type="NodeType"/>
</xs:sequence>
</xs:complexType>
</xs:schema>

Related

Remove Type form Apache apache.cxf.tools.wsdlto.WSDLToJava in generated source

I am trying to consume a WSDL, generate source form WSDL and XSDs in gradle using org.apache.cxf.tools.wsdlto.WSDLToJava. It generates classname as it is in XSDs and WSDL, but I want change all the generated class names in similar way. I know I can add binding file to it, but I would need to have entry for every element in the WSDL.
Please help me with a generic for all the properties.
e.g XSD below :
<xs:complexType name="SomeType">
<xs:sequence>
<xs:element name="SomeType2" type="CommonNS:Some2Type"/>
<xs:element name="SomeType3" type="CommonNS:Some3Type" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
The classes generated are :
com.something.SomeType
com.something.Some2Type
com.something.Some3Type
But I want to generate it as :
com.something.Some
com.something.Some2
com.something.Some3

WCF contract mismatch case that is working

I have a WCF service hosted on 2 servers. There was a function called GetData(param1).
I changed this function to accept 2 parameters i.e. GetData(param1,param2).
I updated the service on server1 and I updated the client code.
A weird thing is happening. the updated client code still works with the outdated service although the functions don't match. The function is being called and the results are returned. The added parameter is an enumeration value type if that helps. But why have such a non-deterministic behavior? and how does it work?
This thing is that when you design your method in a procedural way all you input parameters are optional by default and are populated with default values if you don't specify them explicitly. Assume you have a method with the following signature:
[OperationContract]
void TestMethod(string param1, int param2);
You will get the following WSDL for it:
<xs:element name="TestMethod">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="param1" nillable="true" type="xs:string" />
<xs:element minOccurs="0" name="param2" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:element>
As you can see minOccurs attribute has 0 value which means the element is optional. So this is not surprising that your method works even after you added a new parameter.
If you want to avoid this behavior try to design your contracts in a message way by using MessageContract or at least wrapping all you parameters in a container class. And specify explicitly which parameter is required and if it allows default value via DataMember attribute.
Hope it helps!
If your service has installed more than once place. Recheck your endpoint address to ensure its pointing right hosted server.

Why is JAXB generating the wrong XML for my WCF service?

I have a WCF service that expects an object which I'll call StuffContainer. Our client is trying to generate an XML-serialized StuffContainer using JAXB, but it's coming out wrong. They're ending up with type names where they should have property names, so we're not able to deserialize it.
I know nothing about JAXB, but I gather it creates some auto-generated classes based on our XSD, which can be used to build the XML-serialized object.
Here's the relevant snippet of our auto-generated XSD:
<xs:complexType name="StuffContainer">
<xs:sequence>
<xs:element minOccurs="0" name="myStuff" nillable="true" type="tns:ArrayOfStuff"/>
</xs:sequence>
</xs:complexType>
...
<xs:complexType name="ArrayOfStuff">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Stuff" nillable="true" type="tns:Stuff"/>
</xs:sequence>
</xs:complexType>
Our client's code looks something like this:
ObjectFactory objectFactory = new ObjectFactory();
ArrayOfStuff arrayOfStuff = objectFactory.createArrayOfStuff();
JAXBElement<ArrayOfStuff> arrayOfStuffJAXBElement = objectFactory.createArrayOfStuff(arrayOfStuff);
StuffContainer stuffContainer = objectFactory.createStuffContainer();
stuffContainer.setStuff(arrayOfStuffJAXBElement);
Here's the XML they're getting:
<StuffContainer xmlns="..."><ArrayOfStuff>...</ArrayOfStuff></StuffContainer>
But I need it to be:
<StuffContainer xmlns="..."><myStuff>...</myStuff></StuffContainer>
I think this is because the JAXBElement<ArrayOfStuff> that they're getting from the objectFactory has its QName set to "ArrayOfStuff", and this ends up getting used instead of the property name myStuff. But like I said I know nothing about JAXB so I'm not sure what they should be doing differently.
Is there something either that I can change in the XSD, or that I can ask our client to change in their code, so that it generates the correct XML?
There may be multiple methods on the generated ObjectFactory class. The ones corresponding to nested elements have an entire path built into the method name.

why did not got any error while validating my xml?

My Xml is not getting correctly validated against the XSD.
I expect the browser to through atleast some kind of generic error messages when i open xml file
My Xml file is below
note.Xml
<?xml version="1.0"?>
<note
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:SchemaLocation="note.xsd">
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
My Xsd file is below
note.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3schools.com"
xmlns="http://www.w3schools.com"
elementFormDefault="qualified"><xs:element name="note">
<xs:complexType>
<xs:sequence>
<xs:element name="from" type="xs:string"/>
<xs:element name="heading" type="xs:string"/>
<xs:element name="body" type="xs:string"/>
</xs:sequence>
<xs:attribute name="to" type="xs:string" use="required"/>
</xs:complexType>
</xs:element></xs:schema>
Both the note.xml and note.xsd files are in the same folder.
Can somebody guide why i am not getting any error? So Can anyone help me how to validate my xml file with xsd? Thank you,
Three problems:
xsi:schemaLocation attribute value
should be a white-space separate
sequence of namespace URI and schema
document URI, like xsi:schemaLocation="http://www.w3schools.com note.xsd"
You wrote:
I expect the browser to through
atleast some kind of generic error
It's not clear that you are actually
using some validation tool. No
browser validates XML Schema when
you open an XML document.
Your schema targets the
http://www.w3schools.com namespace
URI, but your document is under null
(or empty) namespace URI. This will
end up in validation error, even if
you use the
xsi:noNamespaceSchemaLocation
instead of the xsi:schemaLocation
attribute. Maybe you want to add a
default namespace declaration in
your input source like
xmlns="http://www.w3schools.com"...

asmx wsdl string length

I have a VB class in an .asmx file in Visual Studio 2008:
public class foo
public bla as String
end class
It generates the wsdl value:
<s:complexType name="foo">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="bla" type="s:string" />
</s:sequence>
</s:complexType>
But what I want the wsdl to generate is:
<xs:element name="bla" type="xs:string"
sql:datatype="varchar(25)" minOccurs="1" maxOccurs="1">
</xs:element>
Is there a way to do this?
Or can I edit the generated WSDL?
You can use The System.Xml.Serialization.XmlElementAttribute to mark the property IE:
<XmlElement(DataType := "varchar(25)")>
(my vb is a little rusty if this isn't correct
syntax)
You can save off the WSDL and edit it, however, if you change the WSDL, a proxy generated from it may not be able to communicate with your service.
Edit: If you have the target schema, I would suggest that you use xsd.exe or wsdl.exe to generate the classes you need to serialize to valid documents according to that schema.