Friday, December 02, 2005

Changing the target endpoint on a web service object

Just answered a question for a customer that I should probably get out into the googlesphere for others to know.

When you create a web service object in ColdFusion MX, what you are really creating is a Java object that acts as a proxy to the web service. This object derives from an Apache Axis type, org.apache.axis.client.Stub, which in turn implements the standard JAX-RPC type javax.xml.rpc.Stub. Why is this important? Well, these object have an API that you can use to affect the operation of the proxy.

Specifically, you can change the endpoint that the stub will send the HTTP POST that contains the SOAP request. Here is a code snippet that invokes a CFC web service named service.cfc that has an operation "echo" which takes a string and returns it.

ws = CreateObject("webservice", "http://localhost:8500/service.cfc?WSDL");
ret = ws.echo("hello world");


Now lets say we want to watch the request with tcpmon, the TCP/HTTP sniffer that is bundled in with Axis, JRun and ColdFusion. First we start up tcpmon (called 'sniffer' by JRun), on Windows you run c:/CFusionMX7/runtime/bin/sniffer.exe.

Fill in a listener port (try 8501) and then a target hostname (localhost) and port (8500 if CF is running its internal webserver, or port 80 if you are running a standard web server). Click the "Add" button and then switch to the "Port 8501" tab. Just to make the output look nice, check the "XML Format" check box at the bottom so tcpmon will make the SOAP more readable.

Now we can run this CFML cfscript snippet:


ws._setProperty("javax.xml.rpc.service.endpoint.address", "http://localhost:8501/service.cfc");
ret = ws.echo("Through the tunnel");


You will see the SOAP request in the to pane, and the response in the bottom pane.

How does this work? Well JAX-RPC defines a standard property name, "javax.xml.rpc.service.endpoint.address", that will change the URL the stub will send to request to.
Note that we do NOT use "?WSDL" on this URL as this is the endpoint that gets the request, not the URL of the WSDL document.

What else can you do to the Stub? Well, you can read the Javadocs for Stub class in Axis at http://ws.apache.org/axis/java/apiDocs/org/apache/axis/client/Stub.html
and you will see a few interesting APIs. With the addition of the get/set SOAP Header functions in CFMX7 however, ColdFusion already provides access to almost everything via those functions or tag attributes to cfobject or cfinvoke.

3 comments:

Anonymous said...

I'd also point readers at this (long!) thread on the Macromedia ColdFusion forums about calling SalesForce.com web services:

The SOAP Challenge - SF says we can't do it!

Sean A Corfield
An Architect's View

website design New York City said...

thanks u r information

Unknown said...

in general, how to you "re-instatiate" the stub that has lost a connection to a webservice? No change to DNS, no change to WSDL, but have an issue where the remote publishing server, on reboot, causes CF to fail trying to call the already established stateless web service. If we recycle CF, then the web service calls work again. To be clear, CF is the consumer. It logs in to the published WS (not CF) to make the WS call. When the publisher reboots, the CF calls fail. It acts like cf is hanging on to a "session" that goes away when the publisher reboots. Have tried refreshing the wsdl, turning off the DNS cache, even deleting the stub directory - no joy anywhere; only a stop/start of cf services allows us to reconnect. If I had to guess i would say it lost something in the SOAP binding that the Stub generates.