Wednesday, June 28, 2006

ColdFusion auto WSDL generation weird behaviour

ColdFusion auto generates WSDL's for web services. When it does this, it has to provide a name for the web service. The servie name is defined as follows in the wsdl:

<wsdl:service name="myAPIService">
<wsdl:port binding="impl:myAPI.cfcSoapBinding" name="myAPI.cfc">
<wsdlsoap:address location="http://www.somedomain.com/myAPI.cfc" />
</wsdl:port>
</wsdl:service>

The weird behaviour that I have observed is that the name it gives can be with different case on different ocassions. For example in above service I have seen names like:
myAPIService
MyAPIService
myapiService

all for the same cfc on the same server. The difference I found was the way the wsdl was called the first time after a change had been made to the cfc. So if, I called the wsdl as:
http://www.somedomain.com/myAPI.cfc?wsdl
the service name would be myAPIService

If wsdl was http://www.somedomain.com/MyAPI.cfc?wsdl
the service name would be MyAPIService

If wsdl was http://www.somedomain.com/myapi.cfc?wsdl
the service name would be myapiService

Now this can create many problems when calling your webservice from other platforms. I resolved this by always calling the wsdl immediately after making changes to it in the format I wanted.

Monday, June 26, 2006

ColdFusion MX "complex type" errors

If you have a CF component or a web service that returns a custom defined complex data type and you dont return each member of the object, you may get the foll. error:





org.xml.sax.SAXParseException: Premature end of file.





For example I had a component function like:





<cffunction returntype="saveResult" output="No" name="editContact" access="public">

<cfargument name="id" required="Yes" type="numeric">

<cfargument name="first_name" required="Yes" type="string">

<cfargument name="last_name" required="Yes" type="string">



<cfset result= createObject("componnet", "saveResult")>

<cfset result.error=" 0">

<cfset result.msg="">

do something...



<cfreturn result>

</cffunction>








the "result" object was defined in result.cfc as:


<cfcomponent>

<cfproperty name="error" type="numeric">

<cfproperty name="msg" type="string">

<cfproperty name="errorObj" type="error">

</cfcomponent>






The "error" object was defined in error.cfc as:

<cfcomponent>

<cfproperty name="errorCode" required="Yes" type="string">

<cfproperty name="errorNumber" required="Yes" type="numeric">

</cfcomponent>



Now when I was calling the "editContact" function, I was getting the foll. error on CF 7:

Here is the fault returned when invoking the web service operation:

AxisFault faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException faultSubcode: faultString: org.xml.sax.SAXParseException: Premature end of file. faultActor: faultNode:




On CFMX 6.1 I was getting this error:



Could not perform web service invocation "editRecipient" because AxisFault faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException faultSubcode: faultString: org.xml.sax.SAXParseException: Document root element is missing. faultActor: faultNode: faultDetail: {http://xml.apache.org/axis/}stackTrace: org.xml.sax.SAXParseException: Document root element is missing. at com.macromedia.crimson.parser.Parser2.fatal




To resolve this I had to explicitly set values for each of the members of the complex data types as follows:





<cffunction returntype="saveResult" output="No" name="editContact" access="public">

<cfargument name="id" required="Yes" type="numeric">

<cfargument name="first_name" required="Yes" type="string">

<cfargument name="last_name" required="Yes" type="string">



<cfset result= createObject("component", "saveResult")>

<cfset result.error=" 0">

<cfset result.msg="">

<cfset result.errroObj=" createObject("component", "error")>

<cfset result.errorObj.errorCode="">

<cfset result.errorObj.errorNumber=0>





do something...



<cfreturn result>

</cffunction>







This shows that CF web service methods have to explicitly define all members of a complex data type if the return type is a complex data type.