Sunday, January 13, 2008

PHP Webservice consume from Flex

Yesterday I happened to write a very simple flex web service client which calls a PHP web services, while answering a post on WSO2 Oxygen Tanks Forum on Web service Framework for PHP. I thought I better share my little experience here. Please note I copied most of the code from Buddhika's and Colinrotherham's posts. Hope they will excuse me for publishing them here..

Our service is a greet service which just greet when you call it with your name. The final look of our simple application like this..












Well first forget the clientside, rather move to the server side. It will be written with Web Service Framework for PHP like following block.

  1 <?php
2
3 /** greet function
4 * @param string $name
5 * (map to xs:string)
6 * @return string $greetReturn
7 * (map to xs:string)
8 */

9
10
11 function greet($name)
12 {
13 $result = array ('greetReturn' => "Greetings, ".$name);
14
15 return $result;
16 }
17
18 $operations = array('greet' => 'greet');
19 $parameters = array('greet' => 'MIXED');
20
21 $service = new WSService(array
22 (
23 'operations' => $operations,
24 'opParams' => $parameters
25 ));
26
27 $service->reply();
28 ?>
29
As you can see we are putting doc comments on top of the service function inorder to generate the WSDL from it.. Then publish it with the web server in your computer.

And next we will go to the client. Here is my flex code.. Just make sure you have changed the url of the WSDL to the where actually you have hosted the PHP Service.

  1 <?xml version="1.0" encoding="utf-8"?>
2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*"
3 paddingBottom="0" paddingTop="0"
4 paddingLeft="0" paddingRight="0"
5 layout="vertical"
6 pageTitle="My Greeting Client">
7
8 <mx:Script>
9 <![CDATA[
10
11 import test.MyResponder;
12 import mx.rpc.soap.mxml.WebService;
13 import mx.rpc.AsyncToken;
14 import mx.rpc.events.FaultEvent;
15 import mx.rpc.AbstractService;
16 import mx.rpc.AsyncToken;
17 import mx.rpc.Responder;
18 import mx.utils.ArrayUtil;
19 import mx.rpc.IResponder;
20
21
22 private function callService():void
23 {
24 var webService:WebService;
25 webService = new WebService();
26 webService.wsdl = 'http://localhost/mytests/mails/greetService.php?wsdl';
27 webService.useProxy = false;
28 webService.showBusyCursor = true;
29
30 webService.loadWSDL();
31 var token:AsyncToken = AsyncToken(webService.greet(input.htmlText));
32
33 token.addResponder(new MyResponder(
34 function responseHanlder(data:Object):void
35 {
36 result.htmlText = data.result.toString();
37 }
38 ));
39
40 }
41 ]]>
42 </mx:Script>
43
44 <mx:Panel id="pnlMain" x="10" y="10" width="450" height="250"
45 layout="absolute" title="My Greeting Client">
46 <mx:TextArea x = "10" y="15" id="input" editable="true" width="400" height="50" />
47 <mx:TextArea x = "10" y="100" id="result" editable="false" width="400" height="50" />
48 <mx:Button x="10" y="170" label="Call WebService"
49 id="butJSDisplay" click="callService()"/>
50 </mx:Panel>
51
52 </mx:Application>

As you can see we are using class called MyResponder in order to handle the asynchronous call.
That willl be in the Test Package, so you will create a directory call 'Test' and put the MyResponder.as with the following content.

  1 package test
2 {
3
4 import mx.rpc.IResponder;
5
6 public class MyResponder implements IResponder
7 {
8 private var handler:Function;
9
10 public function MyResponder(ahandler:Function)
11 {
12 super();
13 this.handler = ahandler;
14 }
15 public function result(data:Object):void
16 {
17 handler(data);
18 }
19 public function fault(data:Object):void
20 {
21 handler(data);
22 }
23 }
24
25 }


Then you will need to compile this file (my_consumer.mxml) using mxml compiler in the Flex SDK.

mxmlc -use-network=true my_consumer.mxml

If this works, you will see a file my_consumer.swf which is a compiled flash file and you are done. But just one small thing, you have to embed this flash file inside some html code. Here is the conventional code for that.


  1 <!-- saved from url=(0014)about:internet -->
2 <html lang="en">
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>My Project</title>
6 <style>
7 body { margin: 0px; overflow:hidden }
8 </style>
9 </head>
10
11 <body scroll='no'>
12 <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
13 id="myproject" width="100%" height="100%"
14 codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">

15 <param name="movie" value="myproject.swf" />
16 <param name="quality" value="high" />
17 <param name="bgcolor" value="#869ca7" />
18 <!--<param name="allowScriptAccess" value="sameDomain" />
-->
19 <embed src="my_consumer.swf" quality="high" bgcolor="#869ca7"
20 width="100%" height="100%" name="myproject" align="middle"
21 play="true"
22 loop="false"
23 quality="high"
24 allowScriptAccess="sameDomain"
25 type="application/x-shockwave-flash"
26 pluginspage="http://www.adobe.com/go/getflashplayer">

27 </embed>
28 </object>
29 </body>
30 </html>


Looks like you can open the HTML from the browser and you are done. Yea but remember that your server has the crossdomain.xml and favicon.ico in the web server root directory. There are essential when you access a remote service from flex.

So that is all. Infact if you go to the forum thread, you may find attachments which actually contain the files describe here.

No comments: