According to Cairngorm architecture, we always have a fault handler in every command class for each service.
How we can create a single Class for handling Fault handler event for all the services.
By "always having a fault handler", do you mean by contract, as in in implementing an interface?
You can write a base command class that all of your other command classes extend. The base can implement the on fault handler and all other sub-classes can optionally override it.
public class BaseCommand implements ICommand
{
public function execute( event:Event ):void
{
}
public function onFault( event:Event ):void
{
}
}
// -- no need to implement onFault in sub-class
public class MyCommand extends BaseCommand
{
public function execute( event:Event ):void
{
}
}
Create a base class that you extend all other classes from, put the fault handler there. Such as:
FaultHandlerCairngormCommand extends SequenceCommand implements IResponder
[BaseCommand.as]
public class BaseCommand extends SequenceCommand implements IResponder
{
public function execute( event:CairngormEvent ):void
{
super.execute(event);
}
public function fault( info:Object ):void
{
throw new Error("Generic request failure"); //or handle as you please
}
public function result(data:Object):void
{
throw new Error("The result method implementation defined in IResponder for all extensions of BaseCommand must be overrriden in any sub-class");
}
}
[MyCommand.as]
// -- no need to implement onFault in sub-class
public class MyCommand extends BaseCommand
{
public function execute( event:Event ):void
{
remoteObjectDelegate.doYourServerOperation(this);
}
override public function result(data:Object):void
{
trace("happily handling the data"); //without this override an error will be thrown so the developer will know to correct
}
}
Related
I don't know how to define a callback that doesn't need any parameter. In order to describe the question, let me make up a setup - mine is different but contains several more classes, harder to digest.
Lets say we have
public class CustomerA {
public Payment payWithCash() {...}
}
and
public class CustomerB {
public Payment payWithCreditCard() {...}
}
and in addition
public abstract class Factory {
public Callback<Void, Payment> getPaymentCallback();
// Some other methods
...
}
then here comes the problem: I'd like to implement something like this
public class CashFactoryA extends Factory {
public Callback<Void, Payment> getPaymentCallback() {
return CustomerA::payWithCash;
}
}
and in a different class
public class CashFactoryB extends Factory {
public Callback<Void, Payment> getPaymentCallback() {
return CustomerB::payWithCreditCard;
}
}
What happens is, that the compiler complains, that CustomerB does not define payWithCreditCard(Void) and CustomerA likewise fails for payWithCash(Void).
So how to state this correct that there is no parameter to the Callback?
I am aware that I could probably solve my problem as well with interfaces, but I like to understand how to solve this with a Callback.
Thank you in advance!
Consider making Factory generic:
public abstract class Factory<T> {
public Callback<T, Payment> getPaymentCallback();
// Some other methods
...
}
And then you can do
public class CashFactoryA extends Factory<CustomerA> {
public Callback<CustomerA, Payment> getPaymentCallback() {
return CustomerA::payWithCash;
}
}
and
public class CashFactoryB extends Factory<CustomerB> {
public Callback<CustomerB, Payment> getPaymentCallback() {
return CustomerB::payWithCreditCard;
}
}
EDIT:
This answer is a wrong approach.
First, you are trying to refer payWithCash from not a instance of CustomerA but the class CustomerA, so payWithCash must be static method.
public class CustomerA {
public static Payment payWithCash() {...}
}
Then use lambda expression which is the same interface as your Callback.
public class CashFactoryA extends Factory {
public Callback<Void, Payment> getPaymentCallback() {
return param -> CustomerA.payWithCash();
}
}
The code above has the same meaning as the code below. The param argument will be ignored as a result.
public class CashFactoryA extends Factory {
public Callback<Void, Payment> getPaymentCallback() {
return new Callback<Void, Payment>(){
#Override
public Payment call(Void param) {
return CustomerA.payWithCash();
}
};
}
}
I have problem with Abstract Factory pattern implementation on Spring. I am using Spring 3 MVC and Hibernate 3, which works fine if I don't use Abstract Factory Method pattern.
I am not sure what I have to add to the Controller to have access the Factory Class (CategoryFactory).
Is there anything missing in the Controller or bean initiating ?
class SectionsController extends MultiActionController {
/* Do I have to initiate the CategoryFactory here? */
public ModelAndView secList() throws Exception {
CategoryFactory.CategoryType type = CategoryFactory.CategoryType.valueOf("view");
modelMap.addAttribute("sectionList", CategoryFactory.findCategory(type).list(id));
return new ModelAndView("Form", modelMap);
}
}
Abstract Factory
public abstract class Category {
public abstract List list(int departId);
}
public class CategoryFactory {
public enum CategoryType { firstclass, secondClass, ... }
public static Category findCategory(CategoryType categoryType) {
// Create type specific Category implementation
}
}
It shoud be:
class SectionsController extends MultiActionController {
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
public ModelAndView secList() throws Exception {
CategoryFactory.CategoryType type=CategoryFactory.CategoryType.valueOf("view");
modelMap.addAttribute("sectionList",CategoryFactory.findCategory(type).list(hibernateTemplate,id);
return new ModelAndView("Form", modelMap);
}
}
in my implementation, I have an interface as: ICachingManager. I've got now one implementation. I also created a manager class as:
public class CachingManager
{
#region Members
private ICachingManager service;
#endregion
#region Constructors
public CachingManager(ICachingManager service)
{
this.service = service;
}
#endregion
#region Public Methods
public void EnCache<T>(string key, T value)
{
this.service.EnCache<T>(key, value);
}
public T DeCache<T>(string key)
{
return this.service.DeCache<T>(key);
}
#endregion
}
In case I had one implementation, then I can easily register the CachingManager class with Unity, automatically Unity resolves and injects the ICachingManager.
In case I had more than one implementation using named types, then how can I can make use of Unity? Do I need to make use of an Abstract Factory to decide on which named type to initialize?
Is it a good idea to make use of such a composite class or use directly implementations of the interface with Abstract Factory?
You don't have to create an abstract factory. You can inject a given named implementation:
public class MyClient
{
[Dependency("NamedManager")]
public ICachingManager CachingManager { get; set; }
// or in the constructor
public MyClient([Dependency("NamedManager")] ICachingManager cachingManager) {
// ...
}
}
or you can configure the container to do the same thing:
public class MyClient
{
public MyClient(ICachingManager cachingManager) {
// ...
}
}
...
void ContainerBuilder() {
...
Container.RegisterType<MyClient>(
new InjectionConstructor(
new ResolvedParameter<ICachingManager>("NamedManager")));
...
}
I am trying to dispatch an custom YouTubeEvent from my Player.as and wish my Main.as would listen and create the video player...Apparently my eventHandler can't catch the event to create the videoplayer.......My flex debug mode is so screw up I can't even use it...My code is as follow..I really appreciate any reply or help.....
My custom event..
package com.youtube.events {
import flash.events.Event;
public class YouTubeEvent extends Event{
public static const PLAYER_READY:String="PLAYER_READY";
public function YouTubeEvent(type:String){
super(type);
}
}
}
My Main.as
public class SearchYoutube extends Sprite
{
private var videoPlayer:Player;
public function SearchYoutube()
{
/*********************Load Video Player****************************/
loadPlayer();
}
private function loadPlayer():void{
videoPlayer= new Player();
videoPlayer.addEventListener(YouTubeEvent.PLAYER_READY, playerReady);
//playReady would never be excuted....
}
private function playerReady(event:YouTubeEvent):void{
videoPlayer.createPlayer(); //This handler would never be executed...
addChild(videoPlayer); //This handler would never be executed...
}
}
Player.as
//only show part of codes here
public function Player(){
}
public function createPlayer():void{
_loader = new Loader();
_loader.contentLoaderInfo.addEventListener(Event.INIT, onLoaderInit);
}
private function onLoaderInit(event:Event):void {
_loader.content.addEventListener("onReady", onPlayerReady);
}
private function onPlayerReady(event:Event):void {
dispatchEvent(new YouTubeEvent(YouTubeEvent.PLAYER_READY));
}
YouTubeEvent.PLAYER_READY is dispatched some time after calling createPlayer(). You should call createPlayer() after videoPlayer.addEventListener(YouTubeEvent.PLAYER_READY, playerReady):
private function loadPlayer():void
{
videoPlayer= new Player();
videoPlayer.addEventListener(YouTubeEvent.PLAYER_READY, playerReady);
videoPlayer.createPlayer();
}
This short tutorial will get you on the right path on using custom events with Flex.
I am having a problem where I dispatch a custom event but the listener does not receive it (i.e. myHandler() in the code below). If I put everything in one mxml file, it works. When I separate the responsibilities in to separate classes, it fails. It is not clear to me what I am missing.
Any help you be appreciated.
Here is my code (update() in ViewModel.as is the entry point):
ChangeEvent.as
import flash.events.Event;
public class ChangeEvent extends Event
{
public function ChangeEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
// Set the new property.
this.isEnabled = isEnabled;
}
// Define static constant.
public static const ENABLE_CHANGED:String = "enableChanged";
// Define a public variable to hold the state of the enable property.
public var isEnabled:Boolean;
// Override the inherited clone() method.
override public function clone():Event {
return new ChangeEvent(type, isEnabled);
}
}
Model.as
public class Model extends EventDispatcher
{
private function TriggerEvent():void
{
var eventObj:ChangeEvent = new ChangeEvent(ChangeEvent.ENABLE_CHANGED);
dispatchEvent(eventObj);
}
}
ViewModel.as
public class ViewModel
{
import mx.controls.Alert;
import ChangeEvent;
private var model:Model;
public function ViewModel()
{
model = new Model();
addEventListener(ChangeEvent.ENABLE_CHANGED, myHandler);
}
public function update():void {
model.LoadData();
}
private function myHandler(event:Event):void {
Alert.show("An event occurred.");
}
}
Do I have to 'register' the event in ViewModel.as similar to the metadata tag in mxml?
e.g.
[Event(name="enableChange", type="ChangeEvent")]
You have to add the event listener on the model object (since it is the one dispatching the event).
model = new Model();
model.addEventListener(ChangeEvent.ENABLE_CHANGED, myHandler);
Hope that helps.