Discussions

J2EE patterns: Generic Entity Beans

  1. Generic Entity Beans (12 messages)

    The idea is to use a Generic Entity Value Object, that contains all logic to handle updates and concurrency for your entity beans.

    Follwing Class hierarchy is proposed:

    1. abstract EntityValueObject
    2. SpecificValueObject extends EntityValueObject
    3. SpecificEntityBean extends SpecificValueObject.

    The EntityValueObject is an abstract class that contains all logic for updates and concurrency, the SpecificValueObject is used to transfer data to and from clients of entity beans and the SpecificEntityBean represents the Bean implementation.

    As previously stated the EntityValueObject contains all logic for updates and concurrency, represented by following methods:
    - EntityValueObject genericCreate (EntityValueObject obj)
    - EntityValueObject update (EntityValueObject obj)
    - EntityValueObject forceUpdate (EntityValueObject obj)
    - int getVersion()
    - void setVersion(int version)

    The genericCreate method is used to construct a new entity from a Value Object, this method will be called by the ejbCreate method of the entity bean.
    The update method takes a Value Object as argument and returns a Value Object with an updated version number.
    The forceUpdate can be used to force an update if a user tries to update data that has already been modified by someone else. The getter and setter methods for the version are used for concurrency control.

    Reflection to the rescue

    You might wonder how this works. The secret is reflection. Whenever you update a bean by passing it a Value Object, it will inspect all attributes of the Value Object and update the corresponding bean attributes with their values. It will also check whether the version number of the value object is different from the bean's version number, if this is the case, it will throw an exception which indicates that the bean has been updated by another client.

    Here is a code snippet of the update method:


      //Allow the update of 'id' if 'this.id == null', because the
      //ejbcreate-methods use this update() method.
      if (!((this.id == null) || (this.id.equals(obj.id)))) {
        setRollbackOnly();
        throw new IllegalUpdateException("Changing the id of a bean is not allowed!");
      }

      //Test if the data is stale (obj.getVersion() != this.getVersion())
      if (obj.getVersion() != this.getVersion()) {
        setRollbackOnly();
        throw new ModifiedException("Data has been modified before your change has been commited!");
      }

      //update all fields.
      Class beanClass=this.getClass();
      Class voClass= obj.getClass();
      try {
        Field[] voFields = voClass.getFields();

        for (int i=0;i<voFields.length;i++) {
          if (!(voFields[i].getName().equals("id"))){
            beanClass.getField(voFields[i].getName()).set(this,voFields[i].get(obj));
          }
        }
        //update the version nbr
        int currentversion=this.getVersion();
        currentversion++;
        setVersion(currentversion);
        //return the object
        return this.asValueObject();
      }
      catch (Exception e) {
        ...
      }


    Let's consider the following example, imagine a business object called "Person" that you want to implement as an Entity Bean.
    The first thing you will do is create a PersonValueObject with the attributes that belong to a person, e.g. name, date of birth, address, gender, telephone, etc..
    All attributes that you want to persist should be declared public. This Value Object must extend EntityValueObject.

    Next thing will be creating the Entity Bean PersonEntityBean, which will extend the PersonValueObject. Basically, you don't have to implement much except for the ejbCreate method that will call the genericCreate method of the EntityValueObject. That's it, you don't need to implement any other methods. You can now deploy and start using your entity bean.


    Threaded Messages (12)

  2. Generic Entity Beans[ Go to top ]

    The problem of reflection is performance. But if performance isn't important then there is a strategy for Value Objects that enhance your pattern. The Value Object Factory Strategy uses reflection to create VO based on the class name. Then you only need to inform the Class of VO.
    This pattern is described in the book Core J2EE patterns.
  3. Generic Entity Beans[ Go to top ]

    And just how often are performance not important...
  4. Generic Entity Beans[ Go to top ]

    I think that the performance of reflection in Java must be improved. The version 1.4 improves it a little. The Pattern is valid. A pattern must not go to trash only by the fact that the actual programming languages don't perform well with it. The languages must be improved to support the patterns. Not vice-versa. If the pattern don't perform well then choose another pattern until the language be improved.
  5. Generic Entity Beans[ Go to top ]

    Well if you really cared about performance I don't think you'd be useing EJBs at all! But, that's another topic :) Given the huge overhead just to use EJBs (especially EJB 1.1) the overhead of reflection is fairly trivial.

    Anyway, that's all IMHO :)

    Kent
  6. Generic Entity Beans[ Go to top ]

    You are so right. That is why one use BMP with DAO and make use of the DAO for listing and the bean for updating. :)
  7. I have used similar approach for JavaBeans in the past. The performance for reflection-based solution was not that bad compared to the total round-trip time required to process an incoming HTTP-request. However the difference to compiled Java class doing the same thing was something like 100 times.

    Because of this difference I wondered if it would be possible to create an utility that generates the Java-code for bean/value object manupulation on run-time and compiles this code to be the class to use for manipulation? Since this needs to be done only once the time required for compiling is taken only once (like for JSPs that are not precompiled). After that the generated class can be reused until the JVM is shut down. Unfortunately there was no time to try this but has someone else tried this kind of approach?
  8. Reflection performance problems[ Go to top ]

    Doesnt JBoss do something like this to dynamically generate stubs and ties for it beans?
  9. Reflection performance problems[ Go to top ]

    The EJB spec forbids using reflection in EJBs (sec. 25.1.2)

    "The enterprise bean must not attempt to query a class to obtain information about the declared
    members that are not otherwise accessible to the enterprise bean because of the security rules
    of the Java language. The enterprise bean must not attempt to use the Reflection API to access
    information that the security rules of the Java programming language make unavailable."
  10. EJB fordibs using Reflection API?[ Go to top ]

    My English is limited since it is not my mother tonque but I understand that part so that using Reflection API as such is not forbidden but using it to bypass Java language security rules is forbidden. Getter/setter methods are (or should be) public and therefore I see no problem to use Reflection API to query them on EJBs.
  11. EJB fordibs using Reflection API?[ Go to top ]

    You are correct the wording there is left to some possible interpretation. I will post a question to EJB-INTEREST on this.
  12. EJB fordibs using Reflection API?[ Go to top ]

    Hi Guys,

    due to currently avaialbe implementation of Aspect Orient Programming (AOP) rely on Reflection API. It would be awfull to
    prohibit this by specfication.

    I agree in everything said about performance, but I guess throwing away Reflection API would be totaly stupid. You lose to much flexilbity.

    Sure XDoclet helps to avoid monton coding of getter/setter stuff, but Metaprogramming isn't so dynamic as sometimes necessary.

    They should worry more about the Classloader's. Are you really sure that a ContainerProvider implemenend it's Classloader safely?

    Cheers
    Toby
  13. Just read EJB Spec. It has been there since 1.1. The reason for banning reflection is also there.