Archive for the 'SOAP' Category
Guttershark Service Manager: SOAP
Ok folks, here’s how you can hook up soap with guttershark.
Here’s a main class: (there are a couple things I explain next)
package { public class Main extends Sprite { private var sm:ServiceManager; public function Main() { sm=ServiceManager.gi(); sm.createSOAPService("myWSDL","http://www.example.com/wsdl",3,5000); callSoap(); } public function callSoap() { sm.myWSDL.someMethod({ params:{someParameter:"hello world"}, resultHandlerClass:MySoapResultHandler, onResult:onSoapResult, onFault:onSoapFault, onFirstCall:onFirstCall, onMethodNotAvailable:onMethodNotAvailable, }); } public function onFirstCall():void { trace("trying soap service"); showLoader(); } public function onSoapFault(sf:SoapFault):void { trace("fault"); } public function onSoapResult(sr:SoapResult):void { trace("result"); trace(sr.raw); trace(sr.handler); //instance of resultHandlerClass. } public function onMethodNotAvailable():void { trace("method was not available on wsdl"); } } }
When you create a soap service (createSOAPService), the service manager downloads your WSDL and parses it out. It stores some information that you can get at runtime. For example, if you wanted to list out the supported methods on this wsdl:
sm.myWSDL.listMethods();
That’s generally all that you need, and that’s only needed in support of debugging.
Generating the Soap Message
The service manager generates the soap message to send to the server based off of the params object you give it. In the above code example, it’s going to generate a soap message that looks like this:
<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> <someMethod xmlns="http://webservicelocation/"> <someParameter>hello world</someParameter> </someMethod> </soap:Body> </soap:Envelope>
Handling the Result
The service manager requires you to give it a “result handler class.” This handler class gives you a hook to handle the soap result, before it’s handed off to your callbacks.
In the above example, there is this line (part of call props):
resultHandlerClass:MySoapResultHandler,
“MySoapResultHandler” needs to be a class that you create, to handle the result. Here’s that class:
package { import net.guttershark.support.servicemanager.soap.SoapFaultError; import net.guttershark.support.servicemanager.soap.SoapResultHandler; public class MySoapResultHandler extends SoapResultHandler { public var somePropertyOnTheResult; override protected function process():void { super.process(); super.setNamespace(); super.setBody(); super.setFault(); //if it get's passed this its an ok result. if(soapFault) throw new SoapFaultError(soapFault); somePropertyOnTheResult = soapBody.someResult.toString(); } } }
The reason we create this soap result handler class is to delegate processing of the result XML into this class, and abstract it out of your application and the service manager.
There’s one thing to note that’s special about the SoapResultHandler, if you throw a “SoapFaultErorr”, anywhere from the process method, it will be raised back up through the service manager, and trigger your “onFault” callback.
So, in the above handler class, if “soapFault” is set, it throws an error - as mentioned this will ultimately trigger your onFault callback.
Now let’s take a look at an updated “onResult” callback function from the Main class, to do something with our handler:
public function onSoapResult(sr:SoapResult):void { trace("result"); trace(sr.raw); //raw soap xml response. trace(sr.handler); //this is the instance of your result handler - an instance of MySoapResultHandler. trace(sr.handler.somePropertyOnTheResult); }
After the service manager processes your soap result handler, it calls your onResult handler. There’s a property on the SoapResult class called “handler”, which will be an instance of your handler class.
The service manager uses your handler class as a middle man so you can do what you want with the result - before it’s passed on. Hopefully you can see how nice this is. It keeps everything abstract from your application, and allows you to just focus on business logic. And also not clutter the methods that do all the work with a result.
Generally, for every soap method you’re going to call, you create a soap handler class. Each soap handler class can process the result specifically for that method call.
Other things to note
There’s one additional property you can set on a service call “showSoapRequest”:
sm.myWSDL.someMethod({ params:{someParameter:"hello world"}, resultHandlerClass:MySoapResultHandler, onResult:onSoapResult, onFault:onSoapFault, onFirstCall:onFirstCall, onMethodNotAvailable:onMethodNotAvailable, showSoapRequest:true, // });
This option will trace the generated soap request that’s being sent to the server.
Integrating Soap With The Model
Here’s a model file:
<xml version="1.0" encoding="utf-8"> <model> <services> <service id="mySoapService" wsdl="mySoapServiceWSDL" attempts="3" timeout="5000" /> <wsdl id="mySoapServiceWSDL" endpoint="http://www.example.com/wsdl" /> </services> </model>
And here’s the update class file:
package { import net.guttershark.control.DocumentController; public class Main extends DocumentController { override protected function flashvarsForStandalone():Object { return { model:"model.xml", initServices:true, } } override protected function setupComplete():void { callSoap(); } public function callSoap() { sm.myWSDL.someMethod({ params:{someParameter:"hello world"}, resultHandlerClass:MySoapResultHandler, onResult:onSoapResult, onFault:onSoapFault, onFirstCall:onFirstCall, onMethodNotAvailable:onMethodNotAvailable, showSoapRequest:true, }); } public function onFirstCall():void { trace("trying soap service"); showLoader(); } public function onSoapFault(sf:SoapFault):void { trace("fault"); } public function onSoapResult(sr:SoapResult):void { trace("result"); trace(sr.raw); trace(sr.handler); //instance of resultHandlerClass. trace(sr.handler.somePropertyOnTheResult); } public function onMethodNotAvailable():void { trace("method was not available on wsdl"); } } }
Crossdomain Issues
With SOAP, Flash has to send over a header called “SOAPAction”, so you’re crossdomains need to allow headers for this.
Conclusion
Soap services are greatly simplified with guttershark - which allows you to focus on business logic of you’re application. Additionally, I hate wasting time on code that’s already been written, don’t you?
Additionally, you should read through the source of the classes that support SOAP functionality. They are in “net.guttershark.support.servicemanager.soap.”
6 comments