Cuando comence la «conversion» de la aplicacion Cairngorm a Mate me tope (aqui en Mendoza se usa mucho la palabra Topa) con un «pequeño» problema. El login originalmente estaba planteado usando el login de BlazeDS.
BusinessDelegate.as
package org.cubikalabs.todolist.business
{
...
public class BusinessDelegate
{
public function login(username:String, password:String):void
{
var token : AsyncToken = ServerConfig.getChannelSet("my-amf").login(username, password);
token.addResponder(responder);
}
public function logout():void
{
ServerConfig.getChannelSet("my-amf").logout().addResponder(responder);
}
}
}
Bueno, resulta que la llamada directa al login/logout usando el ChannelSet no estaba contemplada en Mate… En el foro de Mate encontre esto:
http://mate.asfusion.com/forums/topic.php?id=774
Me puse a laburar en una solución como indica el foro, tratando de generar un Mate Tag para la invocación directa y mas natural. El framework esta muy bien escrito y no me costo mucho entender y hacer funcionar mi solución.
El resultado, que todavia no valido con los patrones de Mate, son 2 tags de similar utilización que el RemoteObjectInvoker :
<mate:ChannelSetLoginInvoker username="{ event.username }" password="{ event.password }" channelSetName="my-amf">
<mate:ChannelSetLogoutInvoker channelSetName="my-amf">
Ejemplo de uso:
<mate:EventHandlers type="{ SecurityEvent.LOGIN }">
<mate:ChannelSetLoginInvoker username="{ event.username }" password="{ event.password }"
channelSetName="my-amf">
<mate:resultHandlers>
<mate:MethodInvoker generator="{ TodoListManager }"
method="setLoginState"
arguments="{ [ TodoListConstants.LOGIN_STATE_SECURE ] }" />
<mate:EventAnnouncer type="{ TodoListEvent.GET_TODOLIST }" />
</mate:resultHandlers>
<mate:faultHandlers>
<mate:InlineInvoker method="log" arguments="{ [ 'Login error: TODO!' ]}" />
</mate:faultHandlers>
</mate:ChannelSetLoginInvoker>
</mate:EventHandlers>
<mate:EventHandlers type="{ SecurityEvent.LOGOUT }">
<mate:ChannelSetLogoutInvoker channelSetName="my-amf">
<mate:resultHandlers>
<mate:MethodInvoker generator="{ TodoListManager }"
method="setLoginState"
arguments="{ [ TodoListConstants.LOGIN_STATE_INSECURE ] }" />
</mate:resultHandlers>
<mate:faultHandlers>
<mate:InlineInvoker method="log" arguments="{ [ 'Error en Logout' ]}" />
</mate:faultHandlers>
</mate:ChannelSetLogoutInvoker>
</mate:EventHandlers>
Y Funciona!!! Aqui estan las tres clases que cree dentro de mate para ello. Veremos que dicen los padres del framework. El ChannelSetInvoker es la clase comun a ChannelSetLoginInvoker y ChannelSetLogoutInvoker, donde ambas sobreescriben el metodo invoke para realizar sus acciones y controles correspondientes.
package com.asfusion.mate.actions.builders
{
import com.asfusion.mate.actionLists.IScope;
import com.asfusion.mate.actions.IAction;
import com.asfusion.mate.core.ISmartObject;
import mx.messaging.ChannelSet;
import mx.messaging.config.ServerConfig;
import mx.rpc.AsyncToken;
/**
* ServiceInvoker is the base class for the following channel set invokers:
* <ul><li>ChannelSetLoginInvoker</li>
* <li>ChannelSetLogoutInvoker</li></ul>
*
* @see com.asfusion.mate.actions.builders.ChannelSetLoginInvoker
* @see com.asfusion.mate.actions.builders.ChannelSetLogoutInvoker
*/
public class ChannelSetInvoker extends ServiceInvoker implements IAction
{
/*-.........................................channelSetName..........................................*/
private var _channelSetName:String;
/**
* Lets you specify a channelSetName value on the client; not supported for destinations that use the JavaAdapter.
* This allows you to provide more than one channelSetName that can be accessed from a single destination on the server.
*
*/
public function get channelSetName():String
{
return _channelSetName;
}
public function set channelSetName(value:String):void
{
_channelSetName = value;
}
/*-.........................................instance..........................................*/
/**
* If this property is null, a new RemoteObject instance is created on
* the <code>prepare</code> method. Otherwise, this instance will be used.
* The class that will be used to create the instance if none is provided is
* <code>mx.rpc.remoting.mxml.RemoteObject</code>
*
* @default null
*/
public function get instance():ChannelSet
{
return currentInstance;
}
public function set instance(value:ChannelSet):void
{
currentInstance = value;
}
/*-----------------------------------------------------------------------------------------------------------
* Override protected methods
-------------------------------------------------------------------------------------------------------------*/
/*-.........................................createInstance..........................................*/
/**
* @inheritDoc
*/
override protected function prepare(scope:IScope):void
{
super.prepare(scope);
if(!currentInstance)
{
if(channelSet)
{
currentInstance = channelSet;
} else {
currentInstance = ServerConfig.getChannelSet(channelSetName);
}
}
if(username && password)
{
if(username is ISmartObject)
{
username = ISmartObject(username).getValue(scope);
}
if(password is ISmartObject)
{
password = ISmartObject(password).getValue(scope);
}
}
}
/*-.........................................run..........................................*/
/**
* @inheritDoc
*/
override protected function run(scope:IScope):void
{
var currentChannelSet:ChannelSet = ( currentInstance as ChannelSet );
token = invoke( currentChannelSet );
scope.lastReturn = token;
}
/*-.........................................invoke..........................................*/
/**
* this is an abstract method that is override by
* <ul><li>ChannelSetLoginInvoker</li>
* <li>ChannelSetLogoutInvoker</li></ul>
*
* @see com.asfusion.mate.actions.builders.ChannelSetLoginInvoker
* @see com.asfusion.mate.actions.builders.ChannelSetLogoutInvoker
*/
protected function invoke( channelSet:ChannelSet ):AsyncToken
{
return null;
}
}
}
package com.asfusion.mate.actions.builders
{
import com.asfusion.mate.actions.IAction;
import mx.messaging.ChannelSet;
import mx.rpc.AsyncToken;
public class ChannelSetLoginInvoker extends ChannelSetInvoker implements IAction
{
/*-.........................................invoke..........................................*/
/**
* @inheritDoc
*/
override protected function invoke( channelSet:ChannelSet ):AsyncToken
{
var localToken:AsyncToken;
if( !channelSet.authenticated )
{
localToken = channelSet.login( username as String, password as String);
} else {
throw( new Error( "ChannelSet is already authenticated." ) );
}
return localToken;
}
}
}
package com.asfusion.mate.actions.builders
{
import com.asfusion.mate.actions.IAction;
import mx.messaging.ChannelSet;
import mx.rpc.AsyncToken;
public class ChannelSetLogoutInvoker extends ChannelSetInvoker implements IAction
{
/*-.........................................invoke..........................................*/
/**
* @inheritDoc
*/
override protected function invoke( channelSet:ChannelSet ):AsyncToken
{
var localToken:AsyncToken;
if( channelSet.authenticated )
{
localToken = channelSet.logout();
} else {
throw( new Error( "ChannelSet is not authenticated." ) );
}
return localToken;
}
}
}