Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1]
Print
Author Topic: SuperTabNavigator + Proxy consistency + RemoteServices + Binding  (Read 9099 times)
openoli
Full Member
***
Posts: 44


View Profile Email
« on: November 11, 2010, 06:04:02 »

Hello,
I've some problems to find a good architecture for a SuperTabNavigator based application.
The basics regarding the tabs and dynamically proxy/mediator creation/registration are clear.
(Described in this post: http://forums.puremvc.org/index.php?topic=596.msg2626#msg2626 )

To explain the problem assume we'd build an SuperTabNavigator based application for a car rental service:

Please imagine following course of action:

First Tab "Cars":
We open a first tab named "Cars" that display's all available cars of our car rental service.
With opening the tab we dynamically create and register a "CarListMediator" and a "CarCollectionProxy" with unique id's.
The data came from a Remote Service, the RemoteService returns an ArrayCollection of CarVO
and populates the "CarCollectionProxy" data object. The data grid's data provider is bound to the model, it's all fine.

Second Tab "Customers":
We open a second tab named "Customers" that display's all customers of our car rental service.
With opening the tab we dynamically create and register a "CustomerListMediator" and a "CustomerCollectionProxy" with unique id's.
The data came from a Remote Service, the RemoteService returns an ArrayCollection of CustomerVO
and populates the dynamically created "CustomerCollectionProxy's" data object. The data grid's data provider is bound to the model, it's all fine.

Third Tab "Peter Miles":
We double click the customer "Peter Miles" that is listet in the second tab "Customers".
This action opens a third tab named "Peter Miles" that displays detailed informations of "Peter Miles" inside a form and a history of all cars that he ever rent until now inside a DataGrid.
With opening the tab we dynamically create and register a "CustomerFormMediator", "CustomerCarsListMediator" and a "CustomerProxy" and "CustomerCarsProxy" with unique id's. To make sure that the displayed data are up-to-date (perhaps an other logged-in user has modified the customer data) we call an other RemoteService that returns a CustomerVO and populates the CustomerProxy data object.
Moreover we get all cars that ever rent by the customer as an ArrayCollection of CarVO from a RemoteService wich poulates the "CustomerCarsProxy's" data object.

Fourth Tab "Ford Mustang":
We double click the car "Ford Mustang" that is listet in the first first tab "Cars".
This action opens a fourth tab named "Ford Mustang" that displays detailed information of the "Ford Mustang" (e.g. the mileage) inside a form and a list of all customers that ever rent this car until now inside a DataGrid.
With opening the tab we dynamically create and register a "CarFormMediator", "CarCustomersListMediator" and a "CarProxy" and "CarCustomersProxy" with unique id's. To make sure that the displayed data are up-to-date (perhaps an other logged-in user has modified the car data) we call an RemoteService that returns a CarVO and populates the "CarProxy's" data object.
Moreover we get all customers that ever rent the "Ford Mustang" as an ArrayCollection of CustomerVO from a RemoteService wich poulates the "CarCustomersProxy's" data object.

Now we modify the milage value inside the "Ford Mustang" tab e.g. from 15300 to 15400.

To update our backend with this new milage value we call a RemoteSercice "UpdateCar".

And here's my question:
To keep all the data in different tabs and proxies consitency and up-to-date, we must update the "CarProxy", the "CarCollectionProxy" and the "CustomerCarsProxy" with our modified CarVO.

What's the best way to to this ?
Or is the proxy model as described above not the best one  ?
Is it a good idea to keep the data redundant in the different proxies ?

I've take a look at RoleProxy inside the EmployeeAdmin's Demo, but I think this solution doesn't work here, cause we need different views to the data.

Sorry for the mass of text, hope you understand my problem.
Perhaps there's anybody out there who can help !

Many thanks in advance
Olaf
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: November 12, 2010, 08:48:56 »

As long as the data is all managed properly in a way you consider sane (i.e. maintainable and extensible), then the above setup sounds perfectly normal to me.

-=Cliff>
Logged
openoli
Full Member
***
Posts: 44


View Profile Email
« Reply #2 on: November 12, 2010, 09:59:20 »

Thanks for your reply Cliff but I think I don't get it yet.
I've created some fictitious code below that implements my "car rental service" example fragmentary.

My main question is, if it's the right or elegant way to have multipe, identical carVO's in different proxies.
And if this is a normal way, what do you think about the CarFormMediator solution. The CarFormMediator is responsible (in this course of action) to keep all related proxies up-to-date ?

Don't know why, but I don't have a good "feeling" with this but no other ideas.
If the general opinion is, that this solution is definitely ok, then I've to adjust my feeling :D
But currently I need somebody who can give me a leg-up... ???

CarFormMediator:
:
...
public function onUpdateCar( event:Event ):void
{
   carProxy.updateCarService( carForm.carVO, id );
}
...
override public function handleNotification( note: INotification ):void
{
   var type:String = note.getType() as String;
   var carVO:CarVO = note.getBody() as CarVO;

       switch ( note.getName() )
       {
           case ApplicationFacade.CAR_UPDATE_SUCCESS:
              if( type==id  )
              {
                   // take care of the proxy consistency and update all related proxies !
                   carCollectionProxy.updateItem( carVO );
                   customerCarsProxy.updateItem( carVO );
              }
              break;
       }
}
...

CarProxy:
:
...
public function get carVO():CarVO
{
    return data as CarVO;
}

public function updateCarService( carVO:CarVO, type:String ):void
{
    // keep the id of the calling component in mind
    _type = type;

   CursorManager.setBusyCursor();
   var delegate:CarServiceDelegate = new CarServiceDelegate( new Responder( onUpdateCarService, onFault ) );
   delegate.updateCar( carVO);
}

public function onUpdateCarService( event:ResultEvent ):void
{
   CursorManager.removeBusyCursor();
   this.setData( event.result as CarVO );
   sendNotification( ApplicationFacade.CAR_UPDATE_SUCCESS, this.carVO , _type );
}
...

CarCollectionProxy
:
...
public function get carCollection():ArrayCollection
{
    return data as ArrayCollection;
}
...
public function updateItem( carVO:CarVO ):void
{
   for ( var i:int=0; i<carCollection.length; i++ )
   {
      if ( carCollection[i].id == carVO.Id )
      {
          carCollection[i] = carVO;
          break; // exit loop
      }
   }
}
...

CustomerCarsProxy:
:
...
public function get customerCars():ArrayCollection
{
    return data as ArrayCollection;
}
...
public function updateItem( carVO:CarVO ):void
{
   for ( var i:int=0; i<customerCars.length; i++ )
   {
      if ( customerCars[i].id == carVO.Id )
      {
          customerCars[i] = carVO;
          break; // exit loop
      }
   }
}
...
« Last Edit: November 12, 2010, 11:16:50 by openoli » Logged
openoli
Full Member
***
Posts: 44


View Profile Email
« Reply #3 on: November 12, 2010, 11:37:25 »

Hello again,
thinking about the problem on my way home I can say why I don't feel comfortable with the solution above:
Cause this is a tab based application numerous proxies could be instantiated during the user is working with it.
For Example:
Each tab that represents a customer instantiates a CustomerCarsProxy object.
To keep all these proxies up-to-date, we have to take care of all instances of this proxy.
May the solution be to update each instance of all related proxies ?
Is there a possibility to get all instances of registrated proxies ?

Thanks again
Olaf
Logged
openoli
Full Member
***
Posts: 44


View Profile Email
« Reply #4 on: November 13, 2010, 08:08:35 »

I think I've got it !
Instead of modeling different proxies (e.g. CarCollectionProxy and CustomerCarsProxy) that handles the same kind of ArrayCollection at least, I'll just have one CarCollectionProxy. This proxy implements various service methods to get the data from the backend.
Each dynamically created tab (view) will registered it's own instance of CarCollectionProxy.
Each instance of CarCollectionProxy could contain different collections of CarVO.

If any commad calls the updateCarService() method from any CarCollectionProxy instance, the CAR_UPDATE_SUCCESS notification is fired.
Each mediator who is interested in, updates it's own instance of CarCollectionProxy proxy.
Cause we don't check the concret id/type when handling the notification, we could feel confident, that every instance of CarCollectionProxy would be updated !

Hope that's it  ;)


CarFormMediator:
:
public function onUpdateCar( event:Event ):void
{
   carProxy.updateCarService( carForm.carVO, id );
}
...
override public function handleNotification( note: INotification ):void
{
   var type:String = note.getType() as String;
   var carVO:CarVO = note.getBody() as CarVO;

       switch ( note.getName() )
       {
           case ApplicationFacade.CAR_UPDATE_SUCCESS:
              if( type==id  )
              {

              }
              // we don't check the id/type, cause we want to make sure that each instance of
              // CarCollectionProxy will updated !
              carCollectionProxy.updateItem( carVO );
              break;
       }
}
...

CarCollectionProxy:
:
...
public function get cars():ArrayCollection
{
    return data as ArrayCollection;
}
...
public function updateItem( carVO:CarVO ):void
{
   for ( var i:int=0; i<cars.length; i++ )
   {
      if ( cars[i].id == carVO.Id )
      {
          cars[i] = carVO;
          break; // exit loop
      }
   }
}
...
public function updateCarService( carVO:CarVO ):void
{
   CursorManager.setBusyCursor();
   var delegate:CarServiceDelegate = new CarServiceDelegate( new Responder( onUpdateCarService, onFault ) );
   delegate.updateCar( carVO );
}

public function onUpdateCarService( event:ResultEvent ):void
{
   CursorManager.removeBusyCursor();
   var carVO:CarVO = note.getBody() as CarVO;
   updateItem( carVO )
   sendNotification( ApplicationFacade.CAR_UPDATE_SUCCESS, carVO , id );
}

public function getAllCarsService():void
{
   CursorManager.setBusyCursor();
   var delegate:CarServiceDelegate = new CarServiceDelegate( new Responder( onGetAllCarsService, onFault ) );
   delegate.getAllCars();
}

public function onGetAllCarsService( event:ResultEvent ):void
{
   CursorManager.removeBusyCursor();
   this.setData( event.result as ArrayCollection);
   sendNotification( ApplicationFacade.GET_ALL_CARS_SUCCESS, cars , id );
}

public function getUserCarsService():void
{
   CursorManager.setBusyCursor();
   var delegate:CarServiceDelegate = new CarServiceDelegate( new Responder( onGetUSerCarsService, onFault ) );
   delegate.getUserCars();
}

public function onGetUserCarsService( event:ResultEvent ):void
{
   CursorManager.removeBusyCursor();
   this.setData( event.result as ArrayCollection);
   sendNotification( ApplicationFacade.GET_USER_CARS_SUCCESS, cars , id );
}

« Last Edit: November 13, 2010, 08:10:58 by openoli » Logged
Pages: [1]
Print