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.
Existem três novos tipos de classes que você precisará estar familiarizado com a compreender o pleno Serviço Worker Pattern.
No último tutorial você viu o padrão da estrutura de um projeto Cairngorm. Para completar esta estrutura, você precisará adicionar duas novas pastas:
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.
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 é 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
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:
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.
- LoginVO.cfc - Este componente corresponderá a classe ActionScript LoginVO que você criou anteriormente.
- 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