Discussions

J2EE patterns: RTTI killer pattern.

  1. RTTI killer pattern. (46 messages)

    In a recent design we needed the client to add various types of orders into a back-end database through EJB.

    Each order type is a subclass of Order. Examples of subclasses include AddOrder, MoveOrder and ConnectOrder.

    So what we wanted the cliet code to look like was this:

    public boolean addOrder(Order ord);

    The above allows you to add all kinds of orders through a single ejb method.

    In the ejb, we would like the call to be forwarded to a method handling a specific type of order.

    private boolean addConcreteOrder(AddOrder order)
    {...}

    private boolean addConcreteOrder(MoveOrder order)
    {...}

    And so on.

    But how do we get from addOrder to addConcreteOrder without resorting to a hard-to-maintain chain of instanceof calls?

    This is what we did:

    public boolean addOrder(Order ord)
    {
      Class paramTypes[] = {ord.getClass()};
      Object params[] = {ord};

      Method m = this.getClass().getDeclaredMethod("addConcreteOrder", paramTypes);

      // invoke the appropriate addOrder version
      boolean isOK = (boolean)m.invoke((Object)this, params);

      return isOK;
    }

    Seems to work very well.

    Threaded Messages (46)

  2. RTTI killer pattern.[ Go to top ]

    Since Order is the base class for all the orders, why don't you let the order to perform the add operation? In this way you eliminate the all the overhead that comes when using reflection. Of course I assume at this point the order is initialized.
    Something like:

    public void addOrder(Order order) throws OrderAddException
    {
       order.add();//override this mth for each order type
    }
  3. RTTI killer pattern.[ Go to top ]

    What you are proposing sounds fine from a pure "polymorphic" perspective. However, the original poster did not make it clear what 'Order' was. I have to assume an "Order" instance came from the client as a value object. In this event, one would not want to make one's value objects dependent on my EJB interface. No?
  4. RTTI killer pattern.[ Go to top ]

    "Java Architect ", you are right. The idea is that the client should be allowed to do this:

    void some_client_func()
    {
      if(some criterion)
      {
         MoveOrder order = new MoveOrder();
         orderEjb.addOrder((Order)order);
      }
      else
      if(some other criterion)
      {
         AddOrder order = new AddOrder();
         orderEjb.addOrder((Order)order);
      }
    }

    The EJB remote interface only exposes addOrder(Order); but this is fine due to the idiom described in the original post. So the idea is to simplify the EJB remote interface - instead of having to add an overloaded version each time a new order type is introduced to the system.
  5. RTTI killer pattern.[ Go to top ]

    This pattern uses RTTI. I don't know why the author describes it as eliminating the use of it. The instanceof operator is not worse, in terms of design and performance, than Reflection. I think this is an anti-pattern, because it promotes bad OO design and incorrect use of polymorphism. This design centralizes functionality to a single class instead of decentralizing it. As new types of orders are added, the bean allways needs to be changed.

    I'm not sure about whether or not Order is a value object, but I do think that according to the way it is used in this pattern, it shouldn't be. The Order objects do not represent data: they represent the type of action that the client wishes to perform. Different subclasses of Order may themselves contain data that is required for the execution of these actions, but as far as the bean is concerned they all represent actions to be taken. This seems to me like a classic usecase for the Command pattern, which truely eliminates RTTI and decentralizes functionality to appropriate subclasses.

    Gal
  6. RTTI killer pattern.[ Go to top ]

    Gal,

    Good points. It's not an RTTI killer, it's an instanceof killer ;-)

    But the goal is merely to prevent this:

    Bean:

    public void addOrder(Order ord)
    {
       if(ord instanceof MoveOrder)
       { addSpecificOrder((MoveOrder)ord) ;}
       else
       if(ord instanceof AddOrder)
       ... and so on ...
    }

    Of course, you could add an overloaded version of addOrder for each order type on the bean, but in this case we want a single method handling all cases.

    As for the Command pattern. Yes, I tend to employ it except in cases - like the above - where the EJB remote interface acts as an API for external systems. In an exposed API, the Command pattern is not very friendly.

    Users of the server-side functionality (people in other projects, customers, etc) typically prefer straightforward interfaces rather than more complex frameworks like the Command, MVC, etc.
  7. RTTI killer pattern.[ Go to top ]

    Why do you think the Command pattern is less user friendly? In my view, as far as the client is concerned, this *is* a command pattern. The client wishes to perform a certain command (AddOrder, MoveOrder, etc) and in order to do so it calls addOrder(Order order). Order is, for all intents and purposes, a Command object: it specifies functionality. How you actually implement the mechanism of running these commands doesn't seem that important for the client: if you don't want to put server side code in the client side you can make the command object expose a way to get a handler for the command, or even maintain a mapping between command objects and handlers in some seperate class. IMO this will still isolate the functionality of specific commands, and will require less changes to the central bean code.

    Gal
  8. RTTI killer pattern.[ Go to top ]

    Gal.

    No, this is not the Comman pattern. Look it up in GoF or whatever. It is more like a facade.
  9. RTTI killer pattern.[ Go to top ]

    I disagree, and I do have GoF's book right in front of me. Would you care to elaborate about why you think this is like a facade?

    Gal
  10. RTTI killer pattern.[ Go to top ]

    Facades hides the complexity of one or more subsystems, subcomponents/interfaces and provides to a (logical) client a simpler view of the world. A session facade, as defined by the J2EE blueprint catalogue, combines this with value objects to increase calls on the server.

    So this is much more like a facade than the Command pattern which is about decoupling BOTH clients and suppliers completely.

    Makes sense?
  11. RTTI killer pattern.[ Go to top ]

    No. A facade pattern provides a unified interface to a set of distinct systems. This has nothing to do with this pattern. The bean where you have the addOrder method may itself be a facade, but that is not what this pattern is about. IMO it's like saying the steering-wheel is what makes your car go: yes, there is a steering-wheel in your car, but no, it's not what makes it go.
    I also don't think that an object such as "AddOrder" can be considered a value object. It does not speficy value: it specifies functionality. It specifies what should happen: in particular, an order should be added. This is GoF's definition of a Command object, and I think it makes a lot of sense.

    Gal
  12. RTTI killer pattern.[ Go to top ]

    Gal, I think you misunderstand. AddOrder is a kind of order, it does not specifiy functionality. It's a kind of order in a telco, just like a MoveOrder is (an order to move, say, a subscriber from one central to another.)

    My choice of example was terribly bad. Sorry about that.

    I didn't say it was a facade, I said it was more like a facade than a command pattern. I know see that you interpreted AddOrder to be a Command due to its name when it actually is a value object.

    No?
  13. RTTI killer pattern.[ Go to top ]

    I understand. My comments about the Command pattern above were based on my understanding of your example, which were obviously wrong. I think now we both agree that this is neither a Command nor a Facade pattern. Right?

    Gal
  14. RTTI killer pattern.[ Go to top ]

    Right.
  15. One confusion Han[ Go to top ]

    In your example you said :

    public void addOrder(Order order) throws OrderAddException
    {
       order.add();//override this mth for each order type
    }

    Please tell me that the 'order' instance of the value object does not make use of any EJBs period. I ask because I'm trying to understand what "adding the order" means regardless of whether it is a "AddOrder" or "MoveOrder".

    Sorry for the late question.

    Thanks
  16. Use the command pattern[ Go to top ]

    The point of this discussion is to find a way to move an invocation from the client side (where you can't invoke the code because you need server side resources) to the server side, in a way which doesn't mean changing the client/server interface every time you find a new bit of code to invoke.

    The code below works.

    The constructor takes the parameters of the operation (which must be serializable) and the execute method performs it on the server.

    Simple.

    Tom

    interface Order implemets Serializable
    {
      void execute();
    }

    class AddOrder implements Order
    {
      public AddOrder(... information needed to execute...);
      public void execute()
      {
         ... put order in DB or whatever...
      }
    }

    class XOrder ...
    {
      ...
    }

    Client:

    Order o = ... create some type of order ...
    bean.do(o);

    Server:

    class xxxEJB {
      public void do(Order o)
      {
        o.execute();
      }
    }
  17. Use the command pattern[ Go to top ]

    The command pattern has been mentioned before, but it's actually not solving the problem.

    The problem is to present a method to the client taking as a parameter the base class (or interface) of a hierarchy. What actions to take on the EJB-side should be based on the actual parameter (typically a subclass.)

    What the command pattern does is to move the invocation on the actual parameter - actions inside the execute method of the value object. Which is NOT what we want.
  18. Use the command pattern[ Go to top ]

    I was just wondering if you tried simply overloading the addOrder method in another EJB? Did you try it and it did not work ? I mean you have one EJB to be called from the client, with only one
    void addOrder(Order order)...;
    method and another EJB with overloaded addOrder(...) methods for each subclass of the Order value object. Your client-facing EJB would only have one interface, and the other EJB (only invoked from the server) would have to be changed when adding new order types. The first one would just delegate the call to the other one.

    Did you try this and it did not work because of serialisation or other problems? It is essentially what you are doing, just that the runtime could optimise it and you don't need to use reflection.

    Tibi
  19. Use the command pattern[ Go to top ]

    What the command pattern does is to move the invocation on the

    >actual parameter - actions inside the execute method of the
    >value object. Which is NOT what we want.

    Can you explain why you don't want this?

    If each type of order has some unique behaviour associated with it, the concrete Order subclass seems like a good place to have that behaviour.

    Tom
  20. RTTI killer pattern.[ Go to top ]

    Well, while the Order might be a pure value Object, for your code to work your concrete orders can't - at least they have to implement the method you are trying to call.
    So what's wrong with having this method on order (say as an abstract method), and override them in a subclass?
    In fact, your code does more or less what Java's polymorphism would (more efficiently) do. Except for type safety, because if your Order class does not declare your method, your code could, if extended, throw an exception when the subclass would not implement the method.
    From maintenace point of view, it's also quite ugly - someone comming in in two years might be quite confused.
    Regards,
    Vlad
  21. RTTI killer pattern.[ Go to top ]

    Oops - I've noticed only now that the methods handling the objects are on the bean - sorry about that & I take some of the points back.
    You still can just call your addOrder method (as you have both OrderX and OrderY param ones) and the correct one will be called. So you still have a language feature you can use.
  22. RTTI killer pattern.[ Go to top ]

    Vlad,

    The entire idea is to present to the EJB client a simpler interface than overloading will present. The *entire* objective is to present a function taking a base class or interface (such as IOrderType), but the functionality is based on the actual parameter.

    Facade nor the Command pattern nor overloading achieves this, but the code in the original posting actually achives this.

    Your point about lower type safety is valid (potential error when the actual-parameter-hierarchy is extended), but this is one of those trade-offs...

    I would normally not do it, but in this case "third-party people" will be using the bean and they want it as simple as possible.
  23. RTTI killer pattern.[ Go to top ]

    Well, you don't have to overload the public bean method. In fact, you already have two overloaded private methods
    "
    private boolean addConcreteOrder(AddOrder order)
    {...}

    private boolean addConcreteOrder(MoveOrder order)
    {...}
    "
    What I think you should do then have your add order as:

    public boolean addOrder(Order ord)
    {
      // this calls the appropriate private method
      // depending on the actual class of ord
      return addConcreteOrder(ord);
    }

    to catch extending w/o adding methods, you could have also

    private boolean addConcreteOrder(Order order) {
      throw IllegalArgumentException("Order class " + order.class + " not supported.");
    }

    which would be called if the JRE would fail to find an overloaded method.

    An entirely different way of doing this would be to have a factory that for each class of orders (as value objects) creates the appropriate business object that can validate it etc.. If you have more than a couple of orders and/or will extend a lot, I would think this to be more appropriate solution as it would decouple the logic of each order to its own class -> better maintenability and could have easier extensibility (if the factory is externaly configurable).
    Regards,
    Vlad
  24. Strategy, Not Visitor[ Go to top ]

    Sakesun: You would use visitor when you want to be able to modify the operation, or add new operations. In this case, he wants to be able to perform the same operation on multiple objects. The strategy pattern is the appropriate pattern.

    Definition: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independantly from clients thgat use it.


    interface OrderProcessor{
    void process (Order o);
    }

    class AddOrderProcessor{
    void process (Order o){
    }


    }

    class MoveOrderProcessor{
    void process (Order o){
    }

    etc.


    Simplest implementation is to create a Map

    Map dispatchMap = new HashMap();
    dispatchMap.put(MoveOrder.class,new MoveOrderProcessor());
    dispatchMap.put(AddOrder.class,new AddOrderProcessor());
    etc


    and to call from EJB

    OrderProcessor op = (OrderProcessor)dispatchMap.get(order.class);

    op.processOrder(order);

    A little more elegant, and enforces programming with interfaces. Should be significantly more effecient as well.

    However, if all orders have basically the same information in them, they can contain the name of the Strategy implementation to use themselves:

    order.getProcessorName("com.theserverside.AddOrderProcessor");


    In this case, I agree with Sakesun. Have a generic order object, which accepts a visitor. Now the visitor will implement whether it is an Add, Move, Connect, and, once you decide you need it, disconnect. But I am assuming the orders are fundamentally different.




  25. Strategy, Not Visitor[ Go to top ]

    I'm not very good in English. But, after I've reread the topics, I still believe visitor is appropriate for this situation. The author want to route from generic "addOrder(Order o)" to specific "addConcreteOrder1,2,3,...". The Visitor pattern can avoid rtti(instanceof) usage by providing a method <accept()> for client to ask for the object type at the base-class. The Visitor comsume this type-information and act upon. Any "Processor" for this object family can perform as a Visitor by extending Visitor class either directly or using anonymous adapter as being used in my example.
  26. I agree with Sakesun. Visitor is just fine to solve RTTI issue. Example :

    public abstract Order {
       public void abstract acceptVisitor(Visitor visitor);
    }

    public MoveOrder extends Order {
       public void abstract acceptVisitor(Visitor visitor) {
         visitor.visitMoveOrder(this);
       }
    }

    public interface Visitor {
       public void visitAddOrder(AddOrder order);
       public void visitMoveOrder(MoveOrder order);
       ...
    }

    public class MyStatelessBean implements OrderVisitor {

       public boolean add(Order order) {
          order.acceptVisitor(this);
       }

       public void visitAddOrder(AddOrder order) {
         // code specific to AddOrder
       }

       public void visitMoveOrder(MoveOrder order) {
         // code specific to MoveOrder
       }

       ...
    }


    The Visitor interface could be implemented in another class or private inner class if you don't want those public methods in your remote bean.

    Note that the goal was to solve "instanceof" issue. The Visitor pattern does it nicely and simply, without external configuration.

    If you expect more and more Order types to be defined in the future, Visitor may not be appropriate for maintenance reasons (especially in a J2EE environment) but this is another issue, solved by another pattern. In this case, a configurable map associating "order type" to "order processor" looks like a good choice.


    JCG
  27. Visitor solves RTTI[ Go to top ]

    I agree that Visitor is the solution of choice here. It simply and cleanly resolves the type without RTTI, which was the original problem. By delegating the type resolution to the visited object and keeping the type-specific functionality in the Visitor, it also retains the value-only nature of the visited object.

    It does have disadvantages where new types are regularly being added to the system, but that doesn't seem to be the case here.

    Dave
  28. Visitor solves RTTI[ Go to top ]

    I think adding new order-type to the system show another advantage of Visitor pattern. If the Visitor is interface or pure abstract class, whenever a new order-type is added the compiler can point out all the effected class at compile time. That is my favorite feature of Visitor.
  29. Visitor solves RTTI[ Go to top ]

    I have implemented a reflective visitor that works quite nicely, especially if you don't have control over the implementation of the classes you are visiting. It also makes maintenance a little easier.

    Taking from previous examples, you would implement something like this:

    class OrderVisitor extends ReflectiveVisitor {

      public void visit(AddOrder order) {...}

      public void visit(MoveOrder order) {...}

      public void visit(DeleteOrder order) {...}

      ...

    }

    Clients can invoke visit(Object) (implemented by ReflectiveVisitor), and the invocation will automatically delegate to the proper method.

    This is also *very* useful if you have no way of knowing what type of object you are working with. You can use ReflectiveVisitor to automatically upcast the object and delegate to the proper implementation.

    The code is GPLed, you can get it @ http://crazybob.org/visitor.zip.

    Thanks,
    Bob
  30. Acyclic Visitor[ Go to top ]

    If you expect more and more Order types to

    > be defined in the future, Visitor may not
    > be appropriate for maintenance reasons

    You can use Acyclic Visitor to avoid the maintenance problems. See http://www.objectmentor.com/resources/articles/acv.pdf. It actually uses instanceof, but in a clever manner that avoids the typical problems associated with runtime type checking.
  31. Hi,

    IMHO the solution involves basicly two patterns:

    a) Command Patter, yes, it is a command :-) but the Command Pattern does not solve the problem the requester has.

    b) Visitor Pattern, yes, its also the Visitor Pattern, however if we hear "visitor" we think about a set of polymorphic data, an iterator over that data and a "manipulation object" visiting each data item.

    The Command Pattern is allready (incompletly)applied. By making the Order class a value Object or Data Transfer Object, it is basicly a Command.

    However the Command is interpreted externaly via RTTI or instance_of, both should be avoided.

    There is a method public boolean addOrder(Order ord); desigend to interprete the Command. In a pure Command Pattern the addOrder(Order ord) method would call a method: "execute()" of the Command.

    Indeed that execute method is the accept method of the visitor!

    What is needed?
    At first I give the class with the addOrder(Order ord) method a name. OrderManager sounds good to me.

    Now below you see the original handling code, I jsut add a class name to it:

    class OrderManager {
    private boolean addConcreteOrder(AddOrder order)
          {...}

    private boolean addConcreteOrder(MoveOrder order)
          {...}

    public boolean addOrder(Order ord) {
          Class paramTypes[] = {ord.getClass()};
          Object params[] = {ord};

          Method m = this.getClass().getDeclaredMethod("addConcreteOrder", paramTypes);

    // invoke the appropriate addOrder version
          boolean isOK = (boolean)m.invoke((Object)this, params);

          return isOK;
    }
    } // class

    Now we can add a method to the class Order! If we would insist on the namings of the Command Pattern that method would be called execute. If we would insist on the naming of the Visitor Pattern we would call that method accept. In this case I like to use a different name to reflect that we have not a "pure" pattern here. So I call it perform.

    class Order {
       abstract boolen perform(OrderManager mg);

       // ... your stuff here
    }

    For a concrete Order like AddOrder, the implementation would look like this:

    class AddOrder {
       boolen perform(OrderManager mg) {

    }
  32. Hi,

    IMHO the solution involves basicly two patterns:

    a) Command Pattern, yes, it is a command :-) but the Command Pattern does not solve the problem the requester has.

    b) Visitor Pattern, yes, its also the Visitor Pattern, however if we hear "visitor" we think about a set of polymorphic data, an iterator over that set/graph and a "manipulation object" visiting each data item. This is not the case in this problem! But still applies to the solution!

    The Command Pattern is allready (incompletly)applied. By making the Order class a value Object or Data Transfer Object, it is basicly a Command.

    However the Command is interpreted externaly via RTTI( instance_of or reflection), that should be avoided.

    There is a method public boolean addOrder(Order ord); desigend to interprete the Command. In a pure Command Pattern the addOrder(Order ord) method would call a method: "execute()" of the Command.

    Indeed that execute method is the accept method of the visitor!

    What is needed?
    At first I give the class with the addOrder(Order ord) method a name. OrderManager sounds good to me.

    Below you see the original handling code, I just add a class name to it:

    class OrderManager {
    private boolean addConcreteOrder(AddOrder order)
          {...}

    private boolean addConcreteOrder(MoveOrder order)
          {...}

    public boolean addOrder(Order ord) {
          Class paramTypes[] = {ord.getClass()};
          Object params[] = {ord};

          Method m = this.getClass().getDeclaredMethod("addConcreteOrder", paramTypes);

    // invoke the appropriate addOrder version
          boolean isOK = (boolean)m.invoke((Object)this, params);

          return isOK;
    }
    } // class

    Now we can add a method to the class Order! If we would insist on the namings of the Command Pattern that method would be called execute. If we would insist on the naming of the Visitor Pattern we would call that method accept. In this case I like to use a different name to reflect that we have not a "pure" pattern here. So I call it perform.

    class Order {
       abstract boolen perform(OrderManager mg);

       // ... your stuff here
    }

    For a concrete Order like AddOrder, the implementation would look like this:

    class AddOrder {
       boolen perform(OrderManager mg) {
          mg.addConcreteOrder(this);
       }
    }

    The above OrderManager would be changed like this:

    class OrderManager {
    private boolean addConcreteOrder(AddOrder order)
          {...}

    private boolean addConcreteOrder(MoveOrder order)
          {...}

    public boolean addOrder(Order ord) {
        return order.perform(this);
    }
    } // class

    Conclusion:
    We use a Command to be sent from the client to the server.
    The server likes to interprete the command basing on the concrete type of the command. The pure Command pattern would isolate the "action" into the command, but we have the action on the server side.
    Solution:
    The reciever of the Commands is a Visitor!!! Yes, the visitor is passivly iterating over the incomming Commands. So lets use double dispatch from the CommandManager(the Visitor) via the Order(The Command) back to the CommandManager. The addConcreteOrder(XYZOrder ord) method is the visit method of the Visitor Pattern.

    Drawbacks:
    In the sketched solution all Commands need to implement the same Order interface or inherit from an abstract Order base class.

    The use of 'this' may not work under all conditions in an EJB environment.

    Regards,
        angel'o'sphere
  33. See

    http://www.theserverside.com/resources/article.jsp?l=ClassLoading

    Especially note the statements :
    <br>
    >Note that a class loaded at a given level in the hierarchy
    >may not reference any classes loaded at a lower level in
    >the hierarchy. Stated another way, a class loader has no
    >visibility into classes loaded by its descendants.
    <br>


    >In figure 1, if class Foo is loaded by class loader B, and
    >Foo depends on class Baz, then class Baz must be loadable
    >by either class loader A or B. If Baz is only visible to
    >class loader C or D, then a ClassNotFoundException will
    >occur. If the class Bar is visible to two sibling class
    >loaders (e.g., C and D in Figure 1) but not to their
    >parent class loaders, and if a request for Bar is sent to
    >both sibling class loaders, then each class loader will
    >load its own version of the class. Instances of Bar based
    >on class loader C will not be type compatible with
    >instances based on class loader D.
    <br>
    <br>

    The Visitor pattern in the static case makes parameters like - (Addorder order) - dependent on a class like the Handlers.
    <br>
    The parameters are value objects and could potentially be passed from a web container within the same JVM (in many App servers).
    <br>
    If the parameter classes are to be visible to both EJBs and Servlets, they need to be loaded by a parent ClassLoader to both of these or by a ClassLoader visible to both.
    <br>
    In an EAR deployment as explained in the above link, this is automatically taken care in the case where EJBS are deployed in the same ear as the dependent Servlets and Jsps.
    <br>
    If Servlets and JSPs are in different JVMS and use RMI/CORBA to talk to EJB, I expect this to be not an issue.
    <br>
    But in cases where this is not true , shared objects DTO value objects will need to be deployed in a System or a library class loader path that is a parent all ear class loaders. Then all the EJBs in various ears and Servlets in various wars will use these DTO objects from a single ClassLoader and it will be type compatible. Otherwise if there are multiple deployments of DTO objects one in an ear and one in war, the Servlets/JSPs won't be able to cast the Value Objects returned by EJBs and EJBs won't be able to cast the Value Objects passed by Servlets.

    <br>
    BUT,
         This causes a problem, if visitor handler classes are deployed within an ear. DTO value objects deployed in a parent class Loader path CANNOT refer to them.
    <br>
    How dow we get around this without the ear file restriction , i.e all dependent Servlets need to be in the same ear. We are having Enterprise level EJBS
    to be shared by many clients who may be deployed in the same JVM.
  34. Visotor[ Go to top ]

    A Visitor is a single method applied to multiple data objects.

    Multiple Commands applied to the same controller is a command pattern.
  35. RTTI killer pattern.[ Go to top ]

    "Well, you don't have to overload the public bean method. In fact, you already have two overloaded private methods
    [snip]"

    That doesn't work.
  36. RTTI killer pattern.[ Go to top ]

    yep, you're right - I forgot that Java does all the bindings at the compile time :( (shouldn't be getting spoiled). Sorry about that.
    Vlad
  37. RTTI killer pattern.[ Go to top ]

    The "overwrite only private method" approach won't work.
    The public method which takes an BaseClass object as argument sets the compiletime-type to BaseClass, so allways the the wrong method is going to be called
  38. RTTI killer pattern.[ Go to top ]

    I would recommend another approach based on the broker pattern or COR pattern.
     
    In the manager constructor, it will create the order handler queue. When the add order request comes, it will iterate through the queue to look up an appropriate handler for the order. We can build the handler queue dynamiclly based on a small configuration file.
     
    Interface Handler {
     
      public boolean add(order);
    }
     
     
    Mgr {
     
     public Mgr() {
     
       //Step 1. create the instance of the handlers
       //Step 2. Place the instance in the handling queue.
     
     }
     
     public boolean addOrder(Order ord) {
     
       while(it.hasNext()) {
     
           Handler handler = (Handler)it.next();
           if (handler.add(order))
              break;
       }//while
     }
    }//Mgr

    public class XXXHandler implements Handler {
     
      public boolean add(order) {
     
        if (order instanceof XXX)
           //do operation.
           return true;
        else
           return false;
      }
     
    }//XXXHandler
     
    If we want multiple handling for the order, simply remove the break statement.
     
    The major benefit of this approach is that it can expend easily.
  39. RTTI killer pattern.[ Go to top ]

    What's wrong with "visitor" or "multiple dispatching" ? Those patterns was supposed to solve this problem.
  40. RTTI killer pattern.[ Go to top ]

    Could you elaborate, Sakesun ?
  41. RTTI killer pattern.[ Go to top ]

    Something like this :-

    public class OrderSystem {
        public static void main(String[] args) {
    OrderProcessor processor = new OrderProcessor();
    processor.saveOrder(new FirstKindOrder());
    processor.saveOrder(new SecondKindOrder());
    processor.saveOrder(new ThirdKindOrder());
    processor.deleteOrder(new FirstKindOrder());
    processor.deleteOrder(new SecondKindOrder());
    processor.deleteOrder(new ThirdKindOrder());
        }
        static abstract class Order {
    abstract void accept(Visitor visitor);
    static abstract class Visitor {
    abstract void visit(FirstKindOrder order);
    abstract void visit(SecondKindOrder order);
    abstract void visit(ThirdKindOrder order);
    }
        }
        static class FirstKindOrder extends Order {
    void accept(Visitor visitor) {visitor.visit(this);}
    public String toString() {return "<FirstKind>";}
        }
        static class SecondKindOrder extends Order {
    void accept(Visitor visitor) {visitor.visit(this);}
    public String toString() {return "<SecondKind>";}
        }
        static class ThirdKindOrder extends Order {
    void accept(Visitor visitor) {visitor.visit(this);}
    public String toString() {return "<ThirdKind>";}
        }
        static class OrderProcessor {
    public void saveOrder(Order order) {
    order.accept(new Order.Visitor() {
    void visit(FirstKindOrder order)
    { System.out.println("Save FirstKind : " + order); }
    void visit(SecondKindOrder order)
    { System.out.println("Save SecondKind : " + order); }
    void visit(ThirdKindOrder order)
    { System.out.println("Save ThirdKind : " + order); }
    });
    }
    public void deleteOrder(Order order) {
    order.accept(new Order.Visitor() {
    void visit(FirstKindOrder order)
    { System.out.println("Delete FirstKind : " + order); }
    void visit(SecondKindOrder order)
    { System.out.println("Delete SecondKind : " + order); }
    void visit(ThirdKindOrder order)
    { System.out.println("Delete ThirdKind : " + order); }
    });
    }
        }
    }
  42. RTTI killer pattern.[ Go to top ]

    So what we wanted the client code to look like was this:

    >public boolean addOrder(Order ord);
    >The above allows you to add all kinds of orders through a
    >single ejb method.
    >In the ejb, we would like the call to be forwarded to a method
    >handling a specific type of order.
    >private boolean addConcreteOrder(AddOrder order)
    >private boolean addConcreteOrder(MoveOrder order)
    >{...}

    Is everybody missing the point here, or it's just me?
    You have to overload your method addOrder like this:
    public boolean addOrder (ConcreteOrderA order);
    public boolean addOrder (ConcreteOrderB order);

    You client just calls:
    bean.addOrder(new ConcreteOrderA());

    The rest is basic Java polymorphism. You need to add a new order type, add a new addOrder() method overload. No instanceOf, no RTTI.

    The only problem I see with this is that if you change your remote interface, you have to redeploy the client code as well. But again, if you add a new order type, don't you have to update both the client and the server? Alternatively, you could forward the call to a second EJB, which implements the polymorphic interface, so that the dispatch takes place only on the server, so you don't need to redeploy everything to the client when you add a new type of Order.

    Cheers,
    Tibi
  43. RTTI killer pattern.[ Go to top ]

    What about loading handler's reflectively?

    public interface OrderHandler {
      public boolean add(Order order);
    }

    public class Bean {

    }
  44. RTTI killer pattern.[ Go to top ]

    What about loading handler's reflectively?

    public interface OrderHandler {
      public boolean add(Order order);
    }

    public interface Order {
    }

    public class Bean {
    Map handlers = new HashMap();

    public void addOrder(Order order) {
    Class orderClazz = order.getClass();
    if(Order.isAssignableFrom(orderClazz) && !Order.class.equals(orderClazz)) {
    OrderHandler handler = getHandler(orderClazz);
    if(handler != null) {
    handler.add(order);
    } else {
    // Error!
    }
    } else {
    // Error!
    }
    }

    protected OrderHandler getHandler(Class clazz) {
    OrderHandler handler = (OrderHandler)handlers.get(clazz);
    if(handler == null) {
    handler = getHandlerReflectively(clazz);
    if(handler == null) {
    Class superClazz = clazz.getSuperclass();
    if(Order.isAssignableFrom(superClazz) && !Order.class.equals(superClazz)) {
    handler = getHandler(superClazz);
    }
    }
    }

    if(handler != null) {
    handlers.put(clazz, handler);
    }

    return handler;
    }

    protected OrderHandler getHandlerReflectively(Clazz clazz) {
    String handlerClassName = clazz.getName() + "Handler";
    Handler handler = null;
    try {
    Class handlerClazz = Class.forName(handlerClassName);
    if(OrderHandler.isAssignableFrom(handlerClazz) && !handlerClazz.isInterface()) {
    handler = (OrderHandler)handlerClazz.newInstance();
    }
    } catch(Exception e) {
    }
    return hadler;
    }
    }
  45. RTTI killer pattern.[ Go to top ]

    You've avoided a hard to maintain chain of instanceof with a hard to maintain group of methods in the one class?

    As someone mentioned you should have each ordertype handled by its own class and use something dynamic ( like a properties file ) to associate AddOrder->AddOrderProcessor.class etc.

    String proc = p.getProperty(order.getClass().getName()+".processor");
    Class pc = Class.forName(proc);
    OrderProcessor op = (OrderProcessor)(pc.newInstance());
    op.invoke(Order);
  46. RTTI killer pattern.[ Go to top ]

    I'm inclined to agree with Lyndon's approach of dynamically associating a handler/processor class with each concrete subclass/implementor or Order.

    Perhaps the design pattern we're talking about applying is Strategy? You have a number of related 'algorithms' that can be selected and interchanged as appropriate. As a starting point, your EJB could be the 'Context' which chooses the appropriate strategy. 'Strategy' itself is the interface; something like 'OrderHandler' maybe. Finally, the 'ConcreteStrategy' implementations perform the real work -- AddOrderHandler, MoveOrderHandler, etc. If the handlers need access to EJB resources, the EJB could pass an instance of itself or EJBContext or whatever is appropriate. I think it would be ok for the handlers to be dependent on the EJB environment.

    Using this design, the EJB could lookup the name of the ConcreteStrategy class to be used given the class name of the Order instance supplied. An instance could be instantiated and then the handler method invoked. I think this provides for 'true' polymorphism. It should be easier to extend for new Order subclasses because it _only_ involves writing new code -- a ConcreteStrategy for the new Order implementation -- and modification of deployment options. No existing EJB code needs to change.

    A refinement to using property files would be to use the EJB environment-naming context (for EJB 1.1) or the EJBContext (EJB 1.0) to find this mapping. This is a 'better' deployment option than using property files.

    Also, instead of using the simple Class.forName(classname) method, my understanding is that the Class.forName(classname, initialize, classloader) method should be used with classloader being Thread.currentThread().getContextClassLoader().

    Best regards,
    Jim Cakalic
  47. I was faced recently with the same problem as yours.

    I needed to:

       - process a collection of subclasses
         using a common interface avoiding
         overloading
       - the action code should be in the server-side
         classes not in the client-side value object subclasses


    The solution turned out to be rather cumbersome (but it works!):



    CLIENT-SIDE VALUE OBJECTS:

    These classes follow the Command pattern but delegating
    the action to a server-side object.

    public abstract class Order
    {
        ....
        abstract void processOrder(OrderProcessor op);
    }


    public final class AddOrder extends Order
    {
       ....
       void processOrder(OrderProcessor op)
       {
          op.processOrder(this);
       }

    }

    public final class MoveOrder extends Order
    {
       ....
       void processOrder(OrderProcessor op)
       {
          op.processOrder(this);
       }

    }



    SERVER SIDE CLASSES:

    The server side classes consiste of a package-scope interface
    that declares de OrderProcessor interface.

    The OrderProcessor implementation is a private object
    inside the OrderBroker (maybe an EJB).
    The OrderBroker presents an "immutable" interface out to the client.

    (package-scope)

    interface OrderProcessor
    {
       void processOrder(AddOrder o);
       
       void processOrder(MoveOrder o);
       
    }


    public final class OrderBroker
    {
       private OrderProcessor op = new OrderProcessor()
       {
          public void processOrder(AddOrder o)
          {
             System.out.println("Processing "+o);
          }

          public void processOrder(MoveOrder o)
          {
             System.out.println("Processing "+o);
          }
       };
        
        
       // IMMUTABLE INTERFACE METHOD
       
       public void processOrders(Order[] o)
       {
          for (int i = 0; i < o.length; i++)
        {
           o[i].processOrder(op);
        }
       }


    }



    CLIENT CODE:

    public class Client
    {

        public static void main(String[] args)
        {
           Order o1 = new AddOrder();
           Order o2 = new MoveOrder();
           
           OrderBroker broker = new OrderBroker();
           
           broker.processOrders(new Order[]{o1, o2});
        }
    }