ColdFusion e Flex - aplicação completa - 1ª parte

Recebi alguns e-mails, comentários pelo Blog e conforme prometido estarei iniciando uma série de posts (5 creio eu :-D) desenvolvendo uma aplicação completa integrada com banco de dados com os seguintes requisitos: login, logout, acesso definido por perfil, operações CRUD como listagem, insert, update, delete. Utilizaremos o ColdFusion, MySQL e o Eclipse com o plugin do Flex Builder.

Pretendo comentar o código da melhor maneira, fazer algumas considerações e disponibilizar o source a medida que vamos evoluindo. Não pretendo focar em boas práticas de programação, no uso deste ou daquele framework, até para não complicar os posts, mas que estes posts sirvam para novos estudos e adaptações do mesmo para as melhores práticas possíveis. Posteriormente posto uma versão completa do mesmo usando Cairngorm, utilizando eventos, usando o pattern MVC, para estudos do pessoal.

Qualquer comentário que beneficie a todos é bem vindo e vamos ao que interessa!

Nesta primeira parte vamos desenvolver nosso banco de dados, o componente com a lógica de login e logout e nossa interface com o acesso definido por perfis funcionando.

Nesta série de posts estou utilizando o Plugin para o Eclipse do Flex Builder 3 Beta 3, recentemente disponibilizado no labs. Está estável e para esta nossa app ele dá conta do recado e você não precisa se preocupar com a licença do mesmo, pelo menos por 90 dias!hehehe

1. Com o Flex Builder aberto, selecione a perspectiva Flex Development.
2. Através do menu File selecione, File > New > Flex Project.
3. Dê o nome ao seu projeto (eu coloquei appcflex).
4. Desmarque a opção "Use default location" e abaixo em Folder certifique-se de estar apontando para a pasta C:\ColdFusion8\wwwroot\appcflex. Isso vai depender da instalação do seu CF.
5. em Application Type, selecione Web Application.
6. Em Server Tecnology, Application Servre Type, escolha ColdFusion. Marque a caixa Use Remote Objecta Access Service e marque logo abaixo, ColdFusion FlashRemoting. Dê Next
7. Na próxima tela apenas valide a localização do servidor e dê Next.
8. Na próxima tela em vez de appcflex.mxm, renomei para Main.mxm, defina a pasta de exibição e Finish.

A sequência deve estar conforme esta imagem (clique para ampliar).

Clique para ampliar

Crie um banco de dados chamado appcflex e nele crie a tabela tb_users com a seguinte estrutura:

/*Column Information For - appcflex.tb_users*/
cod_user varchar(50) PRI
name_user varchar(70)
login_user varchar(50)
pass_user varchar(50)
email_user varchar(70)
text_user varchar(255)
role_user varchar(50)

Se preferir baixe o sql e execute em seu programa de preferência (clique com o botão direito e escolha Salvar Como): tb_users.sql

Não esqueça de setar no Admin do CF o datasource para este nosso banco. Usei o mesmo nome para ele appcflex

Agora vamos ao nosso componente.

Crie uma pasta chamada model dentro da nossa pasta SRC (caso vc tenha deixado-a na definição do projeto)

Crei um CFC coma seguinte estrutura: (pode utilziar o plugin CFECLIPSE, excelente por sinal)

<cfcomponent>
<!---
Francisco Paulino
Tofinha
Blog Zellen
http://blog.zellen.com.br/
tofinha@gmail.com
15/12/2007
--->

<cfset variables.dsnBanco = "appcflex">

   <!--- funcao para realizar o login do usuario e definir seu perfil usando cflogin --->
   <cffunction name="loginUser" access="remote" returntype="struct">
      
      <cfargument name="username" type="string" required="true">
      <cfargument name="password" type="string" required="true">

      <cfset var qValidLogin = "">
      <!--- criando uma estrutura que sera utilziada pelo componente flex --->
      <cfscript>
         registro = StructNew();
         registro.login = "false";
         registro.name = "none";
         registro.role= "none";
      </cfscript>

      <cfquery name="qValidLogin" datasource="#variables.dsnBanco#">
         SELECT    
               cod_user,
               name_user,
               login_user,
               pass_user,
               email_user,
               text_user,
               role_user
         FROM    
               tb_users
         WHERE
               login_user = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(arguments.username)#">
         AND
               pass_user = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(arguments.password)#">
      </cfquery>
      
      <cflogin idletimeout="5">
         <cfif qValidLogin.RecordCount GT 0>
            <cfloginuser name="#qValidLogin.name_user#" password="#qValidLogin.pass_user#" roles="qValidLogin.role_user">
         <cfset registro.login = "true">
         <cfset registro.role = "#qValidLogin.role_user#">
            <cfif registro.login EQ "true">
               <cfset registro.name = "#qValidLogin.name_user#">
            </cfif>
         </cfif>
      </cflogin>
      
      <cfreturn registro>
      
   </cffunction>

   <!--- funcao para logout --->
   <cffunction name="logoutUser" access="remote">
      <cflogout/>
   </cffunction>

</cfcomponent>

Por fim chegamos a nossa aplicação em si.

Abra o arquivo Main.mxml e vamos começar a montar nossa app.

primeiro dentro da tag , abra um boco de código com a tag e digite o seguinte: (está comentado e creio que será de fácil entendimento)

<mx:Script>
      <![CDATA[
      Çspan style='color: #808080'ÈÇemÈ   //importamos os pacotes e classes que nossa aplicacao irá fazer uso
Ç/emÈÇ/spanÈ
         import mx.controls.Alert;
         import mx.collections.ArrayCollection;
         import mx.utils.ObjectUtil;
         import mx.rpc.events.ResultEvent;
         import mx.rpc.events.FaultEvent;
         
      Çspan style='color: #808080'ÈÇemÈ   // criamos uma variavel registro que sera o nosso Objeto a ser utilizado pela app
Ç/emÈÇ/spanÈ
         [Bindable]
         public var registro:Object;
         
         /* Chama o método que checa as informações de login do usuário */
         private function logIn():void
         {
            appCF.loginUser(username.text, password.text);
            loginButton.enabled = false;
         }
         
         /* Chama o método logoutUser() */
         private function logOut():void
         {
            appCF.logoutUser();
         }
         
         /* Mostra mesagens de erro retornadas pela chamada ao método do CFC */
         private function serverFault(event:FaultEvent):void
         {
            Alert.show( ObjectUtil.toString(event.fault) );
            Alert.show( "error" );
            loginButton.enabled = true;
         }
         
         /* Manipula resultado de uma chamada ao método loginuser do CFC */
         private function loginResult(event:ResultEvent):void
         {
         Çspan style='color: #808080'ÈÇemÈ   //resultado retornado é uma estrutura CF então podemos tratar como um objeto
Ç/emÈÇ/spanÈ            
            registro = event.result as Object;
            
            /*checa o valor do campo de login
            note que os nomes dos campos devem ser todos maiusculos quando retorna uma estrutura CF
            é realziado uma validação referente a estrutura retornada onde é setada com true e
            se o perfil é do administrador. Se for manda a para a tela do Administrador */

            if((registro.LOGIN == 'true') && (registro.ROLE == 'Administrador'))
            {
               appViews.selectedChild = secureViewAdmin;
            }
            /* se não for admin, testo o perfil como user. Se for manda a para a tela do Usuário */
            else if((registro.LOGIN == 'true') && (registro.ROLE == 'Usuario'))
            {
               appViews.selectedChild = secureViewUser;
            }
            /* se não for admin nem user exibo um alerta para verificar noemd e usuário e senha */
            else
            {
               loginButton.enabled = true;
               Alert.show("Verifique usuário e senha.", "Acesso Negado", mx.controls.Alert.OK);
            }
         }
         
         /* Manipula resultado de uma chamada ao método logoutUser do CFC, enviando para a
         tela de login e limpando os campos do formulário */

         private function logoutResult(event:ResultEvent):void
         {
            Alert.show("Logout efetuado com sucesso!", "Sair do Sistema", mx.controls.Alert.OK);
            username.text="";
            password.text="";
            loginButton.enabled = true;
            appViews.selectedChild=loginView;
         }
    ]]>
</mx:Script>

Agora, mais a baixo vamos fazer as chamdas ao nosso CFC e seus métodos.

<!-- Configura chamadas para métodos do nosso CFC -->
   <mx:RemoteObject id="appCF" destination="ColdFusion" source="appcflex.src.model.cfcApp" showBusyCursor="true">
      <mx:method name="loginUser" result="loginResult(event)" fault="serverFault(event)"/>
      <mx:method name="logoutUser" result="logoutResult(event)" fault="serverFault(event)" />
   </mx:RemoteObject>

Defini um id denominado appCF, o destination que é o ColdFusion e no source apontei para o nosso CFC. Em seguida com duas tags , fiz menção ao método de login e ao método de logout. bem simples.

Agora vamos montar nossas telas. Vamos utilizar o componente ViewStack para esta app. Após mais estudos vão preferir usar um framework como o Cairngorm, utilizar patterns etc, mas para simplificar vamos utilizar ele que é de simples entendimento e nos atende bem. Vou colocar o código completo que está comentado e por não ter muito registros dará para entender bem.

<!-- Componente ViewStack contendo a tela de login, tela do Administrador e a tela do usuário -->
   <mx:ViewStack id="appViews" width="100%" height="100%">
   
   <!-- tela de login -->
   <mx:HBox horizontalAlign="center" verticalAlign="middle" id="loginView" width="100%" height="100%">
            <mx:Panel id="loginScreen" title="APLICAÇÃO FLEX COM COLDFUSION" width="396" height="263" layout="absolute">
               
               <mx:Label x="135" y="27" text="Painel de Login" fontWeight="bold" fontSize="12"/>
               <mx:Form defaultButton="{loginButton}" width="265" height="91" x="10" y="55">
                <mx:FormItem label="Usuário:" fontWeight="bold">
                      <mx:TextInput id="username" />
                </mx:FormItem>
                <mx:FormItem label="Senha:" fontWeight="bold">
                   <mx:TextInput id="password" displayAsPassword="true"/>
                </mx:FormItem>
               </mx:Form>
               <mx:Image x="283" y="54" id="img_logo" source="assets/img/logo_zellen.jpg"/>
               
               <mx:ControlBar horizontalAlign="right">
               <mx:LinkButton label="Powered by Zellen Soluções Multimídia"
          click="navigateToURL(new URLRequest('http://www.zellen.com.br/'));"
          styleName="footerLink" textDecoration="none" alpha="0.2"
          color="#004000" fontFamily="Arial" fontWeight="bold"/>


               <mx:Spacer width="100%"/>
               
               <!-- Botões para iniciar operações na collection. -->
               <mx:Button id="loginButton" label="Entrar no Sistema"
                      enabled="{(username.text.length == 0 || password.text.length == 0) ? false : true}"
                        toolTip="{loginButton.enabled == true ? 'Entrar no Sistema' : 'Entre com usuário e senha'}"
                        click="logIn()"/>

               </mx:ControlBar>
               
            </mx:Panel>
   </mx:HBox>
   <!-- Fim da tela de login -->
   
   <!--Áreas de segurança do administrador, fica visivel após feito o login e conforme o perfil-->
   <mx:VBox id="secureViewAdmin" width="100%">
      <mx:Panel layout="absolute" title="Painel de Administração - {registro.NAME}" width="100%" height="100%">
         
         <mx:Button y="10" label="Sair do Sistema" click="logOut()" right="10"/>
         <mx:Label x="10" y="12" text="Área de seguranção, perfil: {registro.ROLE}" height="20"/>
         
      </mx:Panel>
   </mx:VBox>
   <!-- Fim da area de segurança do administrador -->
   
   <!--Áreas de segurança do usuário, fica visivel após feito o login e conforme o perfil-->
   <mx:VBox id="secureViewUser" width="100%">
      <mx:Panel layout="absolute" title="Painel do Usuário - {registro.NAME}" width="100%" height="100%">
         
         <mx:Button label="Sair do Sistema" click="logOut()" right="10" y="10"/>
         <mx:Label x="10" y="12" text="Área de seguranção, perfil: {registro.ROLE}" height="20"/>
         
      </mx:Panel>
   </mx:VBox>
   <!-- Fim da area de segurança do usuário-->
   
   </mx:ViewStack>
   <!-- Fim do componente ViewStack contendo a tela de login, tela do Administrador e a tela do usuário -->

Como podem ver defini dentro do ViewStack, primeiro a área de login, denominada loginView que tem os campos para entramos com username e senha e algumas coisas a mais, como o LinkButton e uma imagem que neste caso usei a minha logo.

Em seguida defini uma área chamada secureViewAdmin que só será exibida conforme o login e perfil de administrador. Nesta tela nos próximos posts teremos uma maior interação com os comandos CRUD.

E mais abaixo a última tela, denominada secureViewUser que é a tela do usuário comum que conforme o login e seu perfild e usuário, só irá visualizar os seus dados.

Bom é uma app simples, não sou um expert, ainda tenho muito que estudar e aprender, mas espero estar ajudando e demonstrando o quão simples é a integração do CF com Flex. A cada post vamos melhorando-a. No segundo post vamos trabalhar em cima da listagem dos dados em uma grid pelo perfil do administrador e visualização dos dados do usuário logado.

PS.: esta app inicial, com banco de dados, CFC, e MXML foi feita em pouco mais de 10 minutos, não mais que 15. :-D

Claro que não podia faltar a aplicação em funcionamento, bem como seu source! Se desejarem está em anexo a este post também o projeto completo!

Acesse aqui e para visualizar, lembre-se do botão direito sobre a mesma, View Source e bons estudos!

Abraços e bom estudo pessoal. Que o segundo post venha nos próximos dias! :-D

Posts do blog relacionadas

Comentários (A Moderação para comentários está habilitado. Seu comentário não aparecerá até ser aprovado.)
Marcos Parente's Gravatar Muito legal este exemplo.
# Postado por Marcos Parente | 19/12/07 12:52
Francisco Barros's Gravatar Obrigado por compartilhar o conhecimento.Ótimo exemplo! Ajudou muito.
Fico no aguardo das próximas postagens! \o
[]'s
# Postado por Francisco Barros | 24/12/07 03:00
BlogCFC was created by Raymond Camden. This blog is running version 5.9.002. Entre em Contato Clicky Web Analytics