CF / Lucee incompatibility for createObject() / SOAP request

Have you tried doing

XTM_getXTMInfo = ws.getXTMInfo({password="****", userId=javacast("int", 123), client="******"},{});

(notice the javacast("int", 123a))

In my previous life I did a lot of WebService stuff and JavaCast [JavaCast() :: Lucee Documentation] is your friend

Thanks for looking into this. Is the “a” after 123 a typo in this sentence ?

(notice the javacast("int", 123a) )

Yes, I’ve tried this:

XTM_getXTMInfo = ws.getXTMInfo({password="******", userId=JavaCast("int", 99), client="******"},{});

Made no difference.
Same for

<cfparam name="id" default="99" type="integer">
...
XTM_getXTMInfo = ws.getXTMInfo({password="******", userId=#id# client="******"},{});

Gunter, I appreciate that you used FR to find the indication of the call wanting an int, and it’s great that Mark shared the javacast, but since you’re still having problems applying those discoveries, would you please use one of the tools (whether SOAPUI or the soapclient svc) to let the WEB SERVICE tell you FOR SURE what datatype it expects for userid? :slight_smile:

FWIW, I had been holding off suggesting javacast simply because the FIRST focus is to find WHAT datatype it expects. You seem to be dancing all around this simple suggestion I have made from the very first reply yesterday. I don’t understand why.

Was it perhaps challenging for you to find what the tools were reporting as the datatype? Again, since we can’t access the web service remotely, we can’t tell “for you”. Someone may propose that if you share the WSDL, we could look directly at it or point our own wsdl browsing tool at that. But note that often the wsdl will include references to still other wsdl which is pulled in dynamically, so we’d again not have access to that if it’s also not publicly accessible.

Bottom line: does your view of the wsdl or use of either tool show you WHAT datatype is expected for setuserid? Since that seems to be a setter that’s called implicitly, it may not appear in the definition of that getXTMInfo method you’re actually calling, but there should be definition SOMEWHERE in the wsdl that would define it.

As always, just trying to help.

I’m sorry, you’re right. But I’m not avoiding it, I simply couldn’t find that info in the SOAPUI application.
I downloaded the WSDL file (XTMCustomerMTOMWebService.xml (266.6 KB) ), and this is specified:

  <xs:complexType name="loginAPI">
    <xs:sequence>
      <xs:element name="client" minOccurs="0" type="xs:string"/>
      <xs:element name="integrationKey" minOccurs="0" type="xs:string"/>
      <xs:element name="language" minOccurs="0" type="tns:languageCODE"/>
      <xs:element name="password" minOccurs="0" type="xs:string"/>
      <xs:element name="userId" minOccurs="0" type="xs:long"/>
      <xs:element name="username" minOccurs="0" type="xs:string"/>
    </xs:sequence>

So, it is expecting a long … Now I’m confused :thinking:

Thanks for your help, very appreciated!

Yeah, that was a typo.

Using a CFParam wouldn’t cast the 99 to anything specifically. It would just test it when passed in.

If you can send the WSDL we can see what that function actually accepts.

Can you then do a

<cfdump var="#ws#">

It will tell you what all the functions are and their params.

Hi Mark, the WSDL file was in my previous post: XTMCustomerMTOMWebService.xml (266.6 KB)

As you deducted it expects a long, so JavaCast('long', 1234) should help!

Unfortunately not, same error :neutral_face:

In case it is helpful … I had a similar problem and this was the code I used to manually make a request to the problematic webservice. I apologize that it is not commented very well but just to break it down:

‣ calls a remote webservice : svcUserAdmin Web Service (working url)
‣ notice the function is set to allow the manual entry of the variables (ex: …example.domain.com…) including AuthUserName, AuthPassword and DomainName
‣ notice the method called is GetUsers
‣ notice that after examining the webservice you can see that the result node name is: UserInfo … it would not take much for you to find your node name and required params to pass into your modified version of this function

<cfscript>
GetUsers_Result=GetSmarterMailUserData(method="GetUsers",resultNodeName="UserInfo", paramsAsXML="<AuthUserName>Administrator</AuthUserName><AuthPassword>fake_password_string</AuthPassword><DomainName>example.domain.com</DomainName>");
</cfscript>
<cffunction name="GetSmarterMailUserData">
	<cfargument name="method" default="GetUsers" />
	<cfargument name="resultNodeName" default="UserInfo" />
	<cfargument name="paramsAsXML" default="<DomainName>welikeit.net</DomainName>" />
	<cfsavecontent variable="soapBody"><cfoutput>
		<?xml version="1.0" encoding="utf-8"?>
			<soap:Envelope
				xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
				xmlns:xsd="http://www.w3.org/2001/XMLSchema"
				xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
			<soap:Body>
				<#method# xmlns="http://tempuri.org/">
					#paramsAsXML#
				</#method#>
			</soap:Body>
		</soap:Envelope>
	</cfoutput></cfsavecontent>
	<cfhttp url="http://mail.ilikeit.net/Services/svcUserAdmin.asmx" method="post" result="httpResponse">
		<cfhttpparam type="header" name="SOAPAction" value="http://tempuri.org/#method#" />
		<cfhttpparam type="xml" value="#trim( soapBody )#" />
	</cfhttp>
	<cfsavecontent variable="NamespaceCleanerXSLT"><?xml version="1.0" encoding="utf-8"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="xml" indent="no"/><xsl:template match="/|comment()|processing-instruction()"><xsl:copy><!-- go process children (applies to root node only) --><xsl:apply-templates/></xsl:copy></xsl:template><xsl:template match="*"><xsl:element name="{local-name()}"><!-- go process attributes and children --><xsl:apply-templates select="@*|node()"/></xsl:element></xsl:template><xsl:template match="@*"><xsl:attribute name="{local-name()}"><xsl:value-of select="."/></xsl:attribute></xsl:template></xsl:stylesheet></cfsavecontent>
	<cfif find( "200", httpResponse.statusCode )>
	    <cfset soapResponse = xmlParse(XmlTransform(httpResponse.fileContent,NamespaceCleanerXSLT),false) />
	    <cfset responseNodes = xmlSearch(soapResponse,"//#resultNodeName#") />
	    <cfif arrayLen(responseNodes)>
	    	<cfreturn responseNodes>
		<cfelse>
			<!--- find a node named Message (case sensative) and select it's parent --->
		    <cfset responseNodes = xmlSearch(soapResponse,"//Message/../") />
		    <cfif Len(responseNodes)>
		    	<cfreturn responseNodes[1]>
			<cfelse>
				<cfreturn soapResponse />
			</cfif>
		</cfif>
	</cfif>
</cffunction>

Here is a snippet of my own result handler. Perhaps you can adapt it to your own use.

Note: all results have a namespace, this causes parse issues so I clean out that namespace using this transformation trick. Your use will vary.

	<cfsavecontent variable="NamespaceCleanerXSLT"><?xml version="1.0" encoding="utf-8"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="xml" indent="no"/><xsl:template match="/|comment()|processing-instruction()"><xsl:copy><!-- go process children (applies to root node only) --><xsl:apply-templates/></xsl:copy></xsl:template><xsl:template match="*"><xsl:element name="{local-name()}"><!-- go process attributes and children --><xsl:apply-templates select="@*|node()"/></xsl:element></xsl:template><xsl:template match="@*"><xsl:attribute name="{local-name()}"><xsl:value-of select="."/></xsl:attribute></xsl:template></xsl:stylesheet></cfsavecontent>
	<cfif find( "200", httpResponse.statusCode )>
	    <cfset soapResponse = xmlParse(XmlTransform(httpResponse.fileContent,NamespaceCleanerXSLT),false) />
	    <cfset responseNodes = xmlSearch(soapResponse,"//#resultNodeName#") />
	    <cfif arrayLen(responseNodes)>
	    	<cfreturn responseNodes>
		<cfelse>
			<!--- find a node named Message (case sensative) and select it's parent --->
		    <cfset responseNodes = xmlSearch(soapResponse,"//Message/../") />
		    <cfif Len(responseNodes)>
		    	<cfreturn responseNodes[1]>
			<cfelse>
				<cfreturn soapResponse />
			</cfif>
		</cfif>
	</cfif>

Hi. Thanks for looking into this issue and your input.
Your solution is similar to one of my previous posts (https://lucee.daemonite.io/t/cf-lucee-incompatibility-for-createobject-soap-request/6276/3?u=gunter), but because this is kind of doing it all manual with raw XML and HTTP requests, @carehart suggested to find the problem with the CFML web service feature before making the long run with manual stuff.

Thanks. Will come in handy when the CFML web service functions are not fixable and I need to do it manually.

According to the online help for JavaCast:

ColdFusion:

Converts the data type of a ColdFusion variable to a specified Java type to pass as an argument to Java or .NET object. Use only for scalar, string, and array arguments.

Lucee:

Converts the data type of a CFML variable to pass as an argument to an overloaded method of a Java object.
Use only for scalar and string arguments.

So, meaning it is usable only for Java objects (so, not for “webservice” objects), and only for scalar and string arguments.

So JavaCast() holds no possible solution here anyway, correct?

I could set-up a public accessible URL + login/password to this web service if somebody is willing to investigate it a little further. But for obvious reasons, I don’t want to put those details here.
I really want to migrate our application to Lucee, but unfortunately, I encounter several incompatibilities with CF 9.01, and as long I can’t fix them, I’m forced to migrate it to CF 2018 in the near future, which is not my preference.

Glad to look at it.

My go-to solution years ago was using the WSDL2Java.jar that was with cold fusion that creates a java version of the api and you can call all of that but it’s ugly as hell. PM me some details and I can see if I can get you a workaround.

Thanks Mark.
Mark found out it works perfectly on his setup (5.2.9.31).
I tried it on an express version of 5.2.9.31, and indeed, works as it should be.
So, probably something broke between 5.2.9.31 and 5.3.3.62. Will try with some express versions in between to see where exactly.

It looks like it broke between 5.2.9.31 and 5.3.1.95. Tried with all subsequent versions, none of them works. Tried with that latest snapshot (5.3.5.42), but same problem.

If somebody is willing to investigate this a bit further, or even fix it in code, here is a test code which can be used by everyone. The problem with this webservice is the same as on our private server:

<cfscript>
	ws = createObject ("webservice", "https://www.xtm-cloud.com/project-manager-gui/services/v2/XTMCustomerMTOMWebService?wsdl", {wsversion=1, refreshWSDL=true});
	XTM_getXTMInfo = ws.getXTMInfo({password="test", userId=1, client="test.com"},{});

	XTM_getXTMInfo_xtmInfo_logo = XTM_getXTMInfo.xtmInfo.logo;
	XTM_getXTMInfo_xtmInfo_version = XTM_getXTMInfo.xtmInfo.version;
	XTM_getXTMInfo_xtmInfo_companyname = XTM_getXTMInfo.xtmInfo.companyname;
	XTM_getXTMInfo_xtmInfo_website = XTM_getXTMInfo.xtmInfo.website;
</cfscript>

<cfoutput>
	#XTM_getXTMInfo_xtmInfo_logo#
	<br>
	#XTM_getXTMInfo_xtmInfo_version#
	<br>
	#XTM_getXTMInfo_xtmInfo_companyname#
	<br>
	#XTM_getXTMInfo_xtmInfo_website#
	<br>
</cfoutput>

When you run this on Lucee 5.2.9.31, you should receive this output/error, which is expected because the credentials are not good, but the function call is accepted:


However, when tested on 5.3.3.62, you get this error, which is not as expected:

Bugreport: [LDEV-2597] - Lucee

Thanks!

nice comprehensive bug report :slight_smile: