make axis2 to use specific return type - axis2

I am using an axis2 webservice, in which I am using following messageFormatter (org.apache.axis2.json.JSONMessageFormatter):
<messageFormatter contentType="application/json" class="org.apache.axis2.json.JSONMessageFormatter"/>
and following messageBuilder(org.apache.axis2.json.JSONOMBuilder):
<messageBuilder contentType="application/json" class="org.apache.axis2.json.JSONOMBuilder"/>.
I have one element which I return as a String, Wsdl contract for which is as follows:
<xs:element minOccurs="0" name="totalCostStr" nillable="true" type="xs:String">
My problem here is when I receive the corresponding JSON and if totalCostStr is greater than 0.00, I am getting totalCostStr at client side in JSON as a string "0.00"
and when value totalCostStr is greater than 0, I get value at client side, in JSON as float (e.g. 12.65) and not as a string "12.65".
Is there a way to force axis to return totalCostStr as a Float or String always??
Thanks in advance,
Chetan

This is a strange behaviour :/
You can for to use always as float using the type float in wsdl element
<xs:element minOccurs="0" name="totalCostStr" nillable="true" type="xs:float"/>
This should work...

Related

How to check WCF data element skipped in XML?

In my WCF I defined an object "Product" as below:
<xs:complexType name="Product">
<xs:sequence>
<xs:element name="Name" type="xs:string"/>
<xs:element name="Postcode" type="xs:string" nillable="true" minOccurs="0"/>
<xs:element name="ProductID" type="xs:string" />
</xs:sequence>
</xs:complexType>
Please note the element "Postcode" is nillable="true" minOccurs="0", this means when client application call the web service, they can either provide empty value for this element as below:
<Product>
<Name>Product 1</Name>
<Postcode></Postcode>
<ProductID>10</ProductID>
</Product>
Or they can simple skip "Postcode" element so the incoming message becomes this (Postcode isn't there)
<Product>
<Name>Product 1</Name>
<ProductID>10</ProductID>
</Product>
My question is, in my host program how do I check if the element "Postcode" exists in the incoming XML message? I am asking because if it doesn't there and I call the method to get Postcode value, then the program will throw an error:
string postcode = product.Postcode - this call will throw an error?
Thank you all very much for any ideas/suggestions.
Charles
You are not correct in your assertion that using nillable in your definition permits the two cases you have listed.
In fact, the nillable xsd attribute permits the construction:
<Postcode xsi:nil='true'/>
which is semantically different from Postcode being either empty, or just not present at all.
In answer to your question,
how do I check if the element "Postcode" exists in the incoming XML
message
I don't quite understand why you want to define Postcode with minOccurs=0. When wcf receives this type across the wire it will attempt to deserialise to a predefined C# type. In C#, types either have properties or they don't have.
eg.
public class Product
{
public string Postcode { get; set; }
}
is not the same things as
public class Product
{
}
So by allowing callers to construct two different versions of your Product type you are actually forced to define two separate C# types to deserialise to, which means you'll need to expose your service operation twice, once for callers who want to use Product with postcode, and one for those who want to use Product without.
I would suggest that you redefine your Product type to include the Postcode element - after all because it's a string your callers can just leave it null if they do not wish to use it.

An element with any type of child elements except empty string

I have very little knowledge in xsd and in an urgent need for a solution to a petty problem.
I need to define an element(named tag) which may have any type and number of child elements(and texts as well) but must not contain an empty string.
Example: <tag1> co<sub1>2</sub1> <b1>laser</b1></tag1>,<tag1>co2</tag1>,<tag1><i1>laser</i1></tag1> are allowed (let's say that even <tag1><i1></i1></tag1> is also allowed). But <tag1></tag1> not allowed. Please let me know if there is a very simple way of doing this.
If you are using XSD 1.1, you can use an assertion to check the condition you describe:
<xs:element name="tag" type="non-empty"/>
<xs:complexType name="non-empty">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:any/>
</xs:sequence>
<xs:assert test="child::* or not(string(.) eq '')"/>
</xs:complexType>
In XSD 1.0, there isn't quite such a simple approach; if I were you and working in XSD 1.0, I'd change the design to something easier to express in XSD 1.0.
In 1.0, it's easy to require that the tag element have one or more children, without constraining the children:
<xs:complexType name="non-empty" mixed="true">
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:any/>
</xs:sequence>
</xs:complexType>
<xs:element name="tag" type="non-empty"/>
It's also easy to specify that the tag element can have any non-empty string (I'm taking you at your word here, and allowing strings consisting only of white space -- be careful what you ask for):
<xs:simpleType name="non-empty">
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="tag" type="non-empty"/>
What's not possible in 1.0 is (a) declaring an element as having either a simple or a complex type, or (b) constraining the textual content of a complex type with mixed content.
Good luck.

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.

XSD minOccurs="1" for string

I have a string field named "accountNumber" as part of an object used in a webservice. I need this field to have minOccurs="1" but WITHOUT nillable="true".
If I define that field as <XmlElement(IsNullable:=True)> then I get minOccurs="1" and nillable="true". If I define <XmlElement(IsNullable:=False)> then I don't get nillable="true", but I get minOccurs="0" instead.
So, how do I define my object to get this in my XSD:
<s:element minOccurs="1" maxOccurs="1" name="accountNumber" type="s:string" />
My class definition is very simple:
<Serializable()> _
<XmlType(Namespace:="http://mysite.org")> _
Public Class MyServiceWS
'some other definitions
<XmlElement(IsNullable:=True)> <VBFixedString(64)> Public accountNumber As String
End Class
Thank you for any help.
EDIT Oct 16, 2012: reverse engineering XSD
I reverse engineered XSD with the following fields:
<xs:element name="TEST1" minOccurs="1" maxOccurs="1" type="xs:string"/>
<xs:element name="TEST2" minOccurs="0" maxOccurs="1" type="xs:string"/>
<xs:element name="TEST3" minOccurs="1" maxOccurs="1" nillable="true" type="xs:string"/>
<xs:element name="TEST4" minOccurs="0" maxOccurs="1" nillable="false" type="xs:string"/>
I used the following command: xsd.exe MyClass.xsd /classes /language:vb /f
The following results were produced:
'''<remarks/>
Public TEST1 As String
'''<remarks/>
Public TEST2 As String
'''<remarks/>
<System.Xml.Serialization.XmlElementAttribute(IsNullable:=true)> _
Public TEST3 As String
'''<remarks/>
Public TEST4 As String
Judging from this result, it doesn't seem to be possible to do what I want to accomplish.
EDIT Oct 17, 2012: found a post with similar issue
For all those interested in this issue, I found a post with similar problem. There was no solution provided.
How to make a dotnet webservice set minOccurs=“1” on a string value
As far as I know, what I am asking is not possible to automate through .NET. I would have to alter the WSDL manually.
I have posted a detailed answer on another thread with the same problem: How to make a dotnet webservice set minOccurs=“1” on a string value.
However the short answer is no. It's not possible for string types.
String types have a default value of String.Empty, and minOccurs won't be set to 1 unless there is no default value (which is only possible using IsNullable = true for string).

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.