2 Replies Latest reply on Sep 22, 2003 5:57 AM by jimbrady

    EJBStore and Entity Bean Updates

    chriskrn1

      Hi

      I have some audit fields (dateLastAmended and userLastAmended) on every entity bean. In my ejbStore method, I update these fields. However, what I experience is that at the end of a transaction, JBOSS (3.04), calls ejbStore, even if the bean has not been changed ie. all entity beans that have been accessed during the transaction have their ejbStore methods called. This results in the audit fields being updated of entity beans that have not changed as well.

      Is this behaviour of ejbStore correct, and if so, does anyone have any thoughts/ideas on how I can update the audit fields of only those beans that have changed? Is there a way (according to the EJB 2.0 spec, or specifically in JBOSS), of detecting if a entity bean has been modified?

      Regards
      Chris


        • 1. Re: EJBStore and Entity Bean Updates
          sathyakumar

          Behaviour of ejbStore is correct.

          In JBoss entity beans can be read-only in which case I suppose ejbStore will never be called. These type of beans should not have any setter methods for any of the CMP fields.(Calling create will throw CreateException)..

          But otherwise i dont think you can control the call to ejbStore.

          Regards
          Sathya


          • 2. Re: EJBStore and Entity Bean Updates
            jimbrady

            Hi,
            I am a bit confused by this topic. I have seen that one new feature in 3.2.2RC2 is Container Managed Audit fields - but I can't find any documentation as to what that means. Can any body help?
            I have developed a solution that works and would like to share it as I found it hard to find what to do. If this is now made redundant by the JBoss upgrade let me know.
            To get it to work with xdoclet I have to add the following custom xdt:
            <XDtEjbDataObj:ifIsWithDataContainer>
            <XDtEjbDataObj:ifIsWithDataMethod>

            //
            // Stub to allow abstract super class to call getData of unknown class.
            //

            public java.lang.Object getDataAdapter(){
            return (java.lang.Object) getData();
            }

            </XDtEjbDataObj:ifIsWithDataMethod>
            </XDtEjbDataObj:ifIsWithDataContainer>

            What I did was to add a class Audit Adapter and got my beans to extend that. The audit adapter has code for ejbLoad, ejbStore and isModified as follows:

            public abstract class AuditAdapter implements javax.ejb.EntityBean {

            java.lang.Object dataholder = null;

            protected boolean isDirty = false;

            protected EntityContext ejbContext;

            public void setEntityContext(EntityContext ctx) {
            ejbContext = ctx;
            }
            public abstract void setUpdateUser(java.lang.String updateUser);
            public abstract void setUpdateDate(java.sql.Date updateDate);

            public abstract java.lang.Object getDataAdapter();

            public void ejbLoad() {
            dataholder = (java.lang.Object) getDataAdapter();
            isDirty = false;
            }

            public void ejbStore() {
            if (isModified()) {

            setUpdateUser(ejbContext.getCallerPrincipal().getName());
            }
            setUpdateDate(
            new java.sql.Date((new java.util.Date()).getTime()));
            }
            isDirty = false;
            }

            //
            // Called from some containers to avoid unnecessary called of ejbStore so make public.
            // Avoid unnecessary processing by only calling when isDirty is false.
            //
            public boolean isModified() {
            if (!isDirty) {
            java.lang.Object datanow = (java.lang.Object) getDataAdapter();
            if ((dataholder != null) && (datanow.equals(dataholder))) {
            isDirty = false;
            return isDirty;
            }
            dataholder = datanow;
            isDirty = true;
            }
            return isDirty;
            }
            }