Entity Strategy

Discussions

J2EE patterns: Entity Strategy

  1. Entity Strategy (5 messages)

    This pattern allows an entity bean to perform methods provided by a data transfer object(DTO). This decouples the entity from the behavior. The persistent data is provided by an entity bean and the behavior by a DTO. I'd like to propose here that DTO can be handled in an object-oriented manner.

    With this pattern an entity bean keeps a data transfer object in it and delegates method calls to the DTO. When a client passes an instance of the DTO's subclass to create() method, the client has different behavior dependent on an actual DTO class. Thus this pattern implements inheritance on behavior.

    A benefit of this pattern is easy to implement and maintain. Subclassing an existing DTO class, we could make use of polymorphism for entities even though we don't touch the bean sources and deployment descriptors at all. Because the entity class is stable in this pattern, we can focus on business logic implementation in DTOs that are simple JavaBeans.

    Besides, we can apply this pattern to container-managed relationship fields. In ejb-jar.xml bean names in relationships are fixed, so subtypes of entity beans, mapped to different tables, shouldn't be set to the relationship fields. But we sometimes have cases to change the behavior based on the entity subtype(eg. teacher or student). This pattern solves this problem without switch statements in the bean class.

    Assuming we have a class CustomerBean and have to take special care for gold and platinum customers, we simply implements two more DTO classes, GoldCustomerDTO and PlatinumCustomerDTO that extend CustomerDTO class, instead of extend the CustomerBean class. when ejbLoad() is called in the entity, a Customer DTO factory could create an appropriate type of DTO, with a given customer type as a persistent field.

    Next example shows how to override the getDiscountRate() method in the DTO classes for the Customer entity:


    //***************************************************
    // Customer entity class
    //***************************************************

    public abstract class Customer implements EntityBean {

      private transient CustomerDTO delegate;

      public abstract Long getCustomerId();
      public abstract void setCustomerId(Long id);
      public abstract int getCustomerType();
      public abstract void setCustomerType(int type);
      public abstract String getName();
      public abstract void setName(String name);

      public double getDiscountRate() {
        return delegate.getDiscountRate();
      }

      public Long ejbCreate(CustomerDTO delegate)
        throws CreateException {

        setCustomerId(delegate.getCustomerId());
        setCustomerType(delegate.getCustomerType());
        setName(delegate.getName());

        this.delegate = delegate;

        return null;
      }

      public void ejbPostCreate(CustomerDTO delegate) {
      }

      public void ejbLoad() {
        delegate = CustomerDTOFactory.create(getCustomerId(), getCustomerType(), getName());
      }

      public void ejbStore() {
        delegate = null;
      }

      //...
    }

    //***************************************************
    // Data Transfer Object classes
    //***************************************************

    public abstract class CustomerDTO implements java.io.Serializable {
      // ...
      public abstract double getDiscountRate();
    }

    public final class BasicCustomerDTO extends CustomerDTO {
      // ...
      public double getDiscountRate() {
        return 0.05;
      }
    }

    public final class PlatinumCustomerDTO extends CustomerDTO {
      //...
      public double getDiscountRate() {
        return 0.1;
      }
    }

    public final class GoldCustomerDTO extends CustomerDTO {
      //...
      public double getDiscountRate() {
        return 0.2;
      }
    }

    //***************************************************
    // Sample client code
    //***************************************************

    CustomerLocalHome home;
    OrderLocal order1,order2;
    // ...
    CustomerDTO gold = CustomerDTOFactory.createGoldCustomer(1, "foo");
    CustomerDTO plat = CustomerDTOFactory.createPlatinumCustomer(2, "bar");

    CustomerLocal goldCustomer = home.create(gold);
    CustomerLocal platCustomer = home.create(plat);

    // an order has a relationship to a customer.
    // in each order bean, getCustomer().getDiscountRate()
    // returns a different value.

    order1.setCustomer(goldCustomer);
    order2.setCustomer(platCustomer);


    Related Patters:
      Strategy
      
    References:
    [1] Emmanuel Proulx, EJB Inheritance
        http://www.onjava.com/pub/a/onjava/2002/09/04/ejbinherit.html
        http://www.onjava.com/pub/a/onjava/2002/09/25/ejbinherit2.html

    I've been thought simple entity polymorphism.
    I'd appreciate feedback.

    Threaded Messages (5)

  2. Entity Strategy[ Go to top ]

    Howdy Fusayuki;
    I like the DTO design pattern! But using polymorphism might slow down the program when the inheritance becomes very complex? Abstracting classes allows single inheritance, why can't you use interfaces?
  3. Entity Strategy[ Go to top ]

    Hi, Alex

    I'm glad to have your reply.
    The message for this pattern was my first post to TSS.

    >But using polymorphism might slow down the program
    > when the inheritance becomes very complex?

    I don't think polymorphism is costly in comparison with db access, but I agree the inheritance should be simpler for maintenance, not for speed.

    >Abstracting classes allows single inheritance,
    >why can't you use interfaces?

    When we define a DTO factory, we surely can use interfaces for the methods.

    Thank you for your comment,

    Miki
  4. Questionable[ Go to top ]

    Hi Fusayuki,

    two questions:

    * The DTO should get the entity bean object as a parameter in its methods because otherwise the strategy won't know about the attribute values of the instance it is working on. However, this will make the DTO depend on the bean class, and: because the client also loads the DTO, the client will also depend on the bean class which is impractical. How do you solve this?

    * In which jar file do you deploy the strategy DTO and its factory? Do you deploy it in a different jar than the entity bean? (This would be the goal - otherwise you would have to redeploy the entity bean and gain nothing.) However, don't you think, this other jar will make hot deployment difficult because the entity bean's ClassLoader won't know about the freshly deployed DTO class?

    My impression is that this pattern uses DTOs for a combination of two different purposes:
    * inter-tier data transfer
    * server-side logic

    I think, these two purposes should not be combined in a single object that the client uses. So I think, this is not a pattern but almost an anti-pattern.

    Thoughts and Ideas?

    Matthias Bohlen
    http://www.mbohlen.de/
  5. Questionable[ Go to top ]

    Hi Matthias,

    Thank you for your comments.

    <quote>
    * The DTO should get the entity bean object as a parameter in its methods because otherwise the strategy won't know about the attribute values of the instance it is working on. However, this will make the DTO depend on the bean class, and: because the client also loads the DTO, the client will also depend on the bean class which is impractical. How do you solve this?
    </quote>
    The client depends on the base type of the DTO, not on the concrete DTO classes. To handle this problem I need a DTO factory which creates a DTO for a given type value.

    <quote>
    * In which jar file do you deploy the strategy DTO and its factory? Do you deploy it in a different jar than the entity bean? (This would be the goal - otherwise you would have to redeploy the entity bean and gain nothing.) However, don't you think, this other jar will make hot deployment difficult because the entity bean's ClassLoader won't know about the freshly deployed DTO class?
    </quote>
    Yes, this has a packaging issue like the EJB Command pattern.
    But I think hard coded switch statements in the bean class implementation are worse than this issue.

    This pattern can extend the behavior of the entity without change of the entity code.
    Therefore the modification is localized on the new DTO class and the DTO factory.
    The merit is that we don't have to test entity bean every time when adding a new type to the entity.
    I believe the testing issue is more important than repackaging.

    <quote>
    My impression is that this pattern uses DTOs for a combination of two different purposes:
    * inter-tier data transfer
    * server-side logic
    </quote>
    Maybe I shouldn't have used the term DTO.
    But I didn't want to make a new word such as 'behavior object' just for this small pattern.

    The DTO, which I used in this pattern, should be used with the Session Facard pattern.
    Thus the target clients are session bean and remote clients never touch the DTOs.

    My point is to externalize the server-side logic from the entity but inter-tier data transfer.
    You know it isn't easy to implement EJB inheritance and entities are not polymorphic even though they say entity beans are object-oriented.

    Because the DTO and entity should be symmetric in my pattern, I'd need a tool support to ease the implementation.
    For example, XDoclet generates a value object class for an entity bean class.
    With the generated value object class, I can easily define the subclasses for the new behavior.

    <quote>
    I think, these two purposes should not be combined in a single object that the client uses.
    So I think, this is not a pattern but almost an anti-pattern.
    </quote>
    Yes, I know this pattern is a starting point.
    I'd like to hear better ideas to make entities polymorphic.

    Regards,
    Miki
  6. Why DTO?[ Go to top ]

    I like this pattern because it makes polymorphism with entity beans possible. In this sense it is much better than anything that has been published on the topic "entity beans and inheritance".
    But I don't understand why your behaviour classes (CustomerDTO) should be DTO's.
    Usually entity beans aren't called from a client, but from a SessionFacade on the server. So in my opinion the behaviour classes should be ordinary Java classes that aren't transported between client and server.

    Regards

    Rudi