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