A base Cairngorm Event Flow que é tratada na parte 3 é essencial para qualquer aplicação Cairngorm, mas a maioria das aplicações interage com um servidor. O Serviço para trabalhar com o padrão que foi discutido no tutorial anterior é fundamental para este processo. Para aprender e expandir o Cairngorm Flow, você precisa aprender alguns novos elementos do Cairngorm.

O Servidor - Interações e Elementos

Existem três novos tipos de classes que você precisará estar familiarizado com a compreender o pleno Serviço Worker Pattern.

  • ServiceLocator [Referência] - O ServiceLocator é um singleton que contém referências para todos os serviços que a sua aplicação irá utilizar. E geralmente inclui chamadas HTTPService, WebService, ou RemoteObject.
  •  Business Delegate - O Business Delegate tem três funções: para localizar o serviço que é necessário, para efetuar uma chamada para um método sobre o serviço, bem como a rota do resultado para o especificado respondedor. Geralmente, há uns Negócios delegados para cada serviço.
  • Value Object – Value Objects são classes que por definição não exigem qualquer métodos, apenas propriedades. Eles permitem a aplicação transferir dados strongly-typed  complexos do objetos para e do servidor.

Organizando seu projeto Cairngorm (Com Server Interaction)

No último tutorial você viu o padrão da estrutura de um projeto Cairngorm. Para completar esta estrutura, você precisará adicionar duas novas pastas:

  • /business - Esta pasta contém normalmente dois tipos de arquivos: o ServiceLocator (chamado Services.mxml) e Business Delegates.
  • /vo - Esta pasta contém o valor dos objetos que são passados de e para o servidor

Entendendo o processo

Antes de começar a elaborar a interação com servidor para o seu projeto, você precisa entender o pleno Serviço Worker pattern. A Figura 1 ilustra todo o processo.

Full Cairngorm Diagram Final
Figure 1 - Cairngorm Event Flow with Server Interaction

Fase I – Executando

  • O usuário está visualizando um componente que tem um botão login. Quando o botão é clicado, esse componente enviará um evento chamado LoginEvent que se estende do CairngormEvent.
  • O FrontController irá receber o LoginEvent e executar o comando que é mapeado para o evento. Para este exemplo, será nomeado LoginCommand e implementará ICommand.
  • O comando é executado e receberá o LoginEvent como um argumento. O LoginCommand cria uma instância Delegate enquanto passar uma referência ao Responder. O Comando então chama o método especificado no Delegate.
  • O Delegate recebe o serviço do ServiceLocator e convida o método específico sobre o serviço.
  • O serviço definido no ServiceLocator recebe as informações que são passadas para ele a partir da chamada do Delegate.

Phase II – A Aplicação processa a camada
Phase III – Responde

  • O serviço que está definido no ServiceLocator retorna o resultado do processamento do lado do servidor.
  • O Delegate recebe o resultado e passa-o para o responder  especificado.
  • O Responder recebe o resultado indicando um login bem-sucedido.
  • O ModelLocator terá uma constante predefinida para o " Logged in View ". O Responder mudará workflowState para este valor.
  • Desde o ponto de vista é obrigado a workflowState, irá automaticamente atualizar-se para a nova posição.

Nota: Tradicionalmente, o Command e Responder eram da mesma classe em uma aplicação Cairngorm. Se estiver trabalhando com outros desenvolvedores, os pedidos serão provavelmente codificados desta forma. Contudo, a maioria dos desenvolvedores (incluindo Adobe Consulting) estão agora separando estas classes em duas classes diferentes. Pelo menos em um projecto complexo, é possível que não faça sentido para esses itens separados, mas em um grande pedido poderá ser vantajosa na organização e prática para ter duas classes diferentes

O ServiceLocator

O ServiceLocator é um singleton que contém referências para todos os serviços que o pedido será utilizado. Esses serviços podem ser RemoteObjects, HTTPServices, WebServices, personalizado ou serviços. Tal como o FrontController, esta classe é geralmente instanciado no seu arquivo principal da aplicação. Ao contrário de muitos dos outros projetos Cairngorm que você criou, esta classe pode ser definida em MXML (bem como ActionScript). Para definir corretamente esta em MXML, deve haver um namespace que aponta para a pasta business da pasta Cairngorm. Neste caso, o namespace cairngorm é tipicamente usado. O ServiceLocator no Código Exemplo 1 dispõe de um serviço definido, loginService

Actionscript:

  • <?xml version="1.0" encoding="utf-8"?>
  • <cairngorm:ServiceLocator
  •     xmlns:cairngorm="com.adobe.cairngorm.business.*"
  •     xmlns:mx="http://www.adobe.com/2006/mxml">
  •    
  •     <!– Login Service –>
  •     <mx:RemoteObject id="loginService"
  •         showBusyCursor="true"
  •         destination="ColdFusion"
  •         source="CairngormTest.CairngormLogin">
  •        
  •         <mx:method name="login" /> 
  •        
  •     </mx:RemoteObject>
  •    
  • </cairngorm:ServiceLocator>

Code Example 1 - Simples ServiceLocator

O ServiceLocator é normalmente chamado Services.mxml e reside na pasta business do seu projeto Cairngorm
 Comandos com Server Interaction
No último tutorial você hard-coded alguns valores no LoginCommand para verificar se um determinado nome de usuário e senha. Aqui foi o método execute:

Actionscript:

    public function execute(event:CairngormEvent):void {

        var loginEvent:LoginEvent = event as LoginEvent;

        if( (loginEvent.username == "david") && (loginEvent.password == "password")) {

            modelLocator.workflowState = ViewModelLocator.WELCOME_SCREEN;

        }

    }

    Code Example 2 – Comandos com Without Delegate

    Esta metodologia será uma realidade para qualquer comando que não tem interação com o servidor, mas se você tem interação com o servidor, terão de ser modificados para incluir o delegate. Primeiro você terá que tomar uma decisão. Tal como referido anteriormente, você pode ter separado Comandos e respondedores, ou eles podem ser a mesma classe. Para este exemplo, que será a mesma classe. O Comando irá agora também ter necessidade de se implementar a classe mx.rpc.IResponder (observe que com.adobe.cairngorm.business.Responder está obsoleta e deve deixar de ser utilizado).

    A outra alteração inicial é que execute o método agora instanciando uma classe chamada LoginDelegate (que será criado em breve). A classe LoginDelegate exigi um argumento em seu construtor, o Respondedor do serviço. Neste caso, o comando irá funcionar tanto como o comando e a resposta, assim você só precisa inserir a palavra-chave this dentro do parêntese. Se optar por ter um respondedor separado, você iria inserir a referência a ele aqui (em vez da palavra-chave this).

    Actionscript:

    package net.davidtucker.CairngormSample.commands {

       import com.adobe.cairngorm.commands.ICommand;

        import com.adobe.cairngorm.control.CairngormEvent;

        import mx.controls.Alert;

        import mx.rpc.IResponder;

        import net.davidtucker.CairngormSample.business.LoginDelegate;

        import net.davidtucker.CairngormSample.events.LoginEvent;

        import net.davidtucker.CairngormSample.model.ViewModelLocator;

       

        public class LoginCommand implements ICommand,IResponder {

       

            public var modelLocator:ViewModelLocator = ViewModelLocator.getInstance();

           

            public function LoginCommand() {

            }

           

            public function execute(event:CairngormEvent):void {

                var loginEvent:LoginEvent = event as LoginEvent;

                var delegate:LoginDelegate = new LoginDelegate( this );

                delegate.login(loginEvent.loginAttempt);

            }

           

            public function result( event:Object ):void {

                if(event.result == true) {

                    modelLocator.workflowState = ViewModelLocator.WELCOME_SCREEN;

                } else {

                    mx.controls.Alert.show("Password Incorrect","ERROR");

                }

            }

           

            public function fault( event:Object ):void {

                trace("Service Error");

            }

           

        }

    }

    Code Example 3 - Command with Server Interaction Through a Delegate

    Value Objects

    O Value Object não prorrogar ou implementa qualquer classe Cairngorm. Tal como referido anteriormente, ele simplesmente é uma classe que só é obrigado a ter propriedades, mas não métodos. Por exemplo, se você criou um Value Object para uma entrada - ele teria uma propriedade de um nome de usuário e senhaActionscript:

     

    package net.davidtucker.CairngormSample.vo {

        [RemoteClass(alias="CairngormTest.LoginVO")]

        public class LoginVO {

            public var username:String;

            public var password:String;

            public function LoginVO(username:String,password:String) {

                this.username = username;

                this.password = password;

            }

        }

    }

    Code Example 4 - Value Object for Login

    A metatag RemoteClass é importante notar. Esta permitirá o correspondente objeto server-side  (Componente do ColdFusion, classe PHP, Classe de Java, etc…) Para ser mapeado para este Valor de Objeto. Neste caso, é mapeado para um componente do ColdFusion chamado LoginVO no pasta  CairngormTest..
    Business Delegates
    O padrão de projeto final na Micro-Arquitetura do Cairngorm é o Business Delegate. Uns Business Delegate essencialmente é a camada de abstração entre seus serviços e o resto da sua aplicação. Como declarado anteriormente, tem três funções. Primeiras, o Business Delegate localizará o serviço que é necessário no ServiceLocator. Segundo, solicitará um método de serviço. Finalmente, ele criará uma rota de resposta que volta para o responder especificado (normalmente ou um comando responder separado).
    Uma classe Delegada não estende ou implementa classes Cairngorm, mas ela geralmente segue as seguintes diretrizes.

    •          O Delegate tem pelo menos duas propriedades: Uma chamada serviço o qual é uma referência para um serviço no ServiceLocator e um chamado responder que é a resposta para as chamadas de serviço.
    •          Existe um método para cada método server-side que você estará chamando.
    •          Ambos o responder e as variáveis de serviço são fixadas no construtor.

    Actionscript:

    package net.davidtucker.CairngormSample.business {

       

        import mx.rpc.IResponder;

        import net.davidtucker.CairngormSample.vo.LoginVO;

        import com.adobe.cairngorm.business.ServiceLocator;

       

        public class LoginDelegate {

            private var responder : IResponder;

            private var service : Object;   

           

            public function LoginDelegate( responder:IResponder ) {

                this.responder = responder;

                this.service = ServiceLocator.getInstance().getRemoteObject("loginService");

            }

           

            public function login(login:LoginVO):void {

                var call:Object = service.login( login );

                call.addResponder( responder );

            }

           

        }

    }

    Code Example 5 - Service Delegate

    Existem muitos benefícios em ter esta camada. Se codificada corretamente, você deve ser capaz de mudar a interação de servidor (indo de PHP até ColdFusion por exemplo) e só ter que mudar o código em seu ServiceLocator e seu Delegate. Você também pode facilmente inserir "stub code" simular a interação de servidor real durante as primeiras fases de desenvolvimento.
    The Application Tier
    Neste exemplo, a Camada de Aplicação será lidada por uma instalação do ColdFusion 8. Conterá dois componentes de Coldfusion. Estes componentes são propositadamente simples.

    1. LoginVO.cfc - Este componente corresponderá a classe ActionScript LoginVO que você criou anteriormente.
    2. CairngormLogin.cfc - Este componente apresentará o processo de login atual.

    Neste exemplo, A aplicação Flex passará por um objeto LoginVO ActionScript para o método login do CairngormLogin.cfc por uma chamada RemoteObject. Isto será mapeado para um objeto de LoginVO.cfc. Se este objeto LoginVO.cfc tem o username "David" e a senha de "password" o método retornará true. Se não, retornará false.

    Coldfusion:

    <cfcomponent displayname="LoginVO" hint="Login VO For CairngormTest" output="false">

     

        <cfset this.username = "" />

        <cfset this.password = "" />

       

    </cfcomponent>

    Code Example 6 - LoginVO.cfc

    Coldfusion:

    <cfcomponent displayname="CairngormLogin" hint="CFC to Test Cairngorm Service Interaction" output="false">

        <cffunction name="login" displayname="login" access="remote" output="false" returntype="boolean">

            <cfargument name="loginAttempt" type="LoginVO" required="true" />

                <cfif (loginAttempt.username EQ "david") AND (loginAttempt.password EQ "password")>

                    <cfreturn true />

                <cfelse>

                    <cfreturn false />

                </cfif>

        </cffunction>

    </cfcomponent>

    Code Example 7 - CairngormLogin.cfc