Simplificando remoting com flex

Apesar de existir um bom número de opções para facilitar o uso do remoting do Flex, desenvolvemos na DClick uma outra forma bastante simples que é adequada para projetos pequenos.

A API consiste em uma simples classe, Service, que deve ser extendida pelas classes de seu projeto que farão as chamadas remotas:

Actionscript:

1.package br.com.dclick.services
2.{
3.    import br.com.dclick.mm.components.utils.GenericLoader;
4.    import mx.controls.Alert;
5.    import mx.rpc.AsyncToken;
6.    import mx.rpc.events.AbstractEvent;
7.    import mx.rpc.events.FaultEvent;
8.    import mx.rpc.events.InvokeEvent;
9.    import mx.rpc.events.ResultEvent;
10.    import mx.rpc.remoting.RemoteObject;
11.
12.    public class Service
13.    {
14.        private static const SUFIX_RESULT = “Result”;
15.        private static const SUFIX_FAULT  = “Fault”;
16.
17.        protected var service:RemoteObject;
18.
19.        function Service( source:String = “”, destination:String = “” )
20.        {
21.            service = new RemoteObject( source );
22.            service.source = source;
23.            service.addEventListener( InvokeEvent.INVOKE, invoke );
24.            service.addEventListener( ResultEvent.RESULT, result );
25.            service.addEventListener( FaultEvent.FAULT, fault );
26.        }
27.
28.        private function invoke( event:InvokeEvent ):void
29.        {
30.            before();
31.        }
32.
33.        private function result( event:ResultEvent ):void
34.        {
35.            resultOrFault( event, defaultResultHandler, SUFIX_RESULT );
36.        }
37.
38.        private function fault( event:FaultEvent ):void
39.        {
40.            resultOrFault( event, defaultFaultHandler, SUFIX_FAULT );
41.        }
42.
43.        private function resultOrFault( event:AbstractEvent, defaultHandler, sufix:String )
44.        {
45.            removeEventListeners();
46.            try
47.            {
48.                var method:String = getMethod( event.token ) + sufix; /// xxxResult ou xxxFault
49.                if( this.hasOwnProperty( method ) )
50.                {
51.                    execute( method, event );
52.                }
53.                else
54.                {
55.                    defaultHandler( event )
56.                }
57.            }
58.            catch( e:Error )
59.            {
60.                throw e;
61.            }
62.            finally
63.            {
64.                after();
65.            }
66.        }
67.
68.        private function removeEventListeners():void
69.        {
70.            service.removeEventListener( InvokeEvent.INVOKE, invoke );
71.            service.removeEventListener( ResultEvent.RESULT, result );
72.            service.removeEventListener( FaultEvent.FAULT, fault );
73.        }
74.
75.        private function execute( method:String, event:AbstractEvent ):void
76.        {
77.            this[ method ]( event );
78.        }
79.
80.        private function getMethod( token:Object ):String
81.        {
82.            // nome do método executado no RemoteObject
83.            return AsyncToken( token ).message[ "operation" ];
84.        }
85.
86.        // método executado antes de todas as chamadas. Pode sofrer override.
87.        protected function before():void
88.        {
89.            GenericLoader.show();
90.        }
91.
92.        // método executado após todas as chamadas. Pode sofrer override.
93.        protected function after():void
94.        {
95.            GenericLoader.hide();
96.        }
97.
98.        // método default executado após o sucesso de uma chamada caso não haja um result handler adequado
99.        // na classe filha.
100.        protected function defaultResultHandler( event:ResultEvent ):void
101.        {}
102.
103.        // método default executado após a falha de uma chamada caso não haja um result handler adequado
104.        // na classe filha
105.        protected function defaultFaultHandler( event:FaultEvent ):void
106.        {
107.            var method:String = getMethod( event.token );
108.            trace( event.fault.getStackTrace() );
109.            Alert.show( event.fault.getStackTrace(), “Error in method ” + this + “.” + method + “()” );
110.        }
111.    }
112.}

Existem dois pontos chaves nesta classe:
1. Os event listeners adicionados no construtor. Eles permitem a execução de métodos genéricos antes e após as chamadas. No nosso caso mostramos um componente genérico de “loading”, que reforça para o usuário que alguma tarefa está sendo realizada.
2. A lógica executada no método resultOrFault. Este método descobre qual o nome do método executado no servidor e chama o handler adequado na classe filha, se houver.
Por exemplo, se foi executado um método “listUsers” no servidor e a chamada teve sucesso, a classe Service procura um método chamado “listUsersResult” na classe filha e o chama. Caso houvesse erro na chamada, procuraria pelo método “listUsersFault”.
As constantes “Result” e “Fault” são configuradas nas linhas 14 e 15.

O uso desta API é bastante simples. Vamos supor uma classe UserService:

Actionscript:

1.package br.com.dclick.services
2.{
3.    // imports omitidos
4.    public class UserService extends br.com.dclick.services.Service
5.    {
6.        function UserService()
7.        {
8.            // id do servico configurado
9.            super( “clientService” );
10.        }
11.
12.        function listUsers():void
13.        {
14.            service.listUsers();
15.        }
16.        function listUsersResult( event:ResultEvent ):void
17.        {
18.            var users:ArrayCollection = event.result as ArrayCollection;
19.            UserModel.getInstance().users = users;
20.        }
21.
22.        function login( user:UserVO ):void
23.        {
24.            service.login( user );
25.        }
26.        function loginResult( event:ResultEvent ):void
27.        {
28.            UserModel.getInstance().user = event.result as user;
29.        }
30.        function loginFault( event:FaultEvent ):void
31.        {
32.            Alert.show( “Erro”, “Login inválido” );
33.        }
34.    }
35.}

E para usar nosso serviço, basta:

Actionscript:

1.new UserService().listUsers();
2.new UserService().login( userVO );

É possível reutilizar uma instância do mesmo serviço, desde que os métodos chamados não utilizem variáveis de instância, o que não é recomendado de qualquer forma:

Actionscript:

1.var userService:UserService = new UserService();
2.userService.listUsers();
3.userService.login( userVO );

O código da classe Service está liberado sob a licensa LGPL.

Fonte: http://blog.dclick.com.br/2008/01/21/simplificando-remoting-com-flex/

Se gostou da matéria deixe um comentário or subscribe to the feed and get future articles delivered to your feed reader.

Comentários

Nenhum comentário ainda.

Deixe um comentário

(obrigatório)

(obrigatório)