2 Replies Latest reply on Jan 10, 2006 10:03 AM by Frank Griffin

    Persistence fails silently in 4.0.2

    Frank Griffin Novice

      This is a nasty one.

      If you define an entity bean field as a TreeMap and run a series of EJB accesses (under different transactions - I used individual MDB accesses), the accesses subsequent to one which modifies the field won't see the changes.

      I turned on DEBUG logging and found the problem. Although a print in the ejbStore() method shows the modifications correctly, the next ejbLoad() has lost them. The reason is that
      org.jboss.ejb.plugins.cmp/jdbc/JDBCTypeFactory.java
      has the following code:

      /**
      * Field state factory for java.util.Map implementations. The state is
      * a deep copy of the value.
      */
      private static final CMPFieldStateFactory MAP = new CMPFieldStateFactory()
      {
      public Object getFieldState(Object fieldValue)
      {
      return fieldValue == null ? null : new HashMap((Map)fieldValue);
      }

      public boolean isStateValid(Object state, Object fieldValue)
      {
      return (state == null ? fieldValue == null : state.equals(fieldValue));
      }
      };

      This maps all "Map" implementations to a HashMap as a state value. Later on, when "isStateValid" is called, the saved state is always a HashMap, while the fieldValue will be whatever Map implementation the implementor chose, e.g. TreeMap. This causes isStateValid() to return "false", which causes the following code in JDBCCMP2xFieldBridge to report that the field is *not* dirty, thus causing it *not* to be persisted:


      /**
      * @return true if the field is dirty.
      */
      public boolean isDirty()
      {
      return isLoaded() && !stateFactory.isStateValid(state, value);
      }

      I changed my app to use TreeMap from TreeSet before digging in to debug this, so I suspect that Sets are treated in the same way, since I saw the same problem with a TreeSet.

      I'm sure there is probably a good reason for the isStateValid() test, but the silent failure in this case can easily lead to data corruption.