1 Reply Latest reply on Sep 23, 2008 2:48 AM by eprst

    read-only cmp bean

    eprst

      Hi

      I'm trying to figure out how to implement read-only CMP 2.0 bean in JBoss 4.x

      My current attempt to define it like this doesn't work:

      /**
       * ...
       * @jboss.read-only "true"
       */
      public abstract class MyBean implements EntityBean {
      //....
       /**
       * @ejb.pk-field
       * @ejb.persistence
       * @ejb.interface-method view-type="local"
       * @jboss.column-name "foo"
       */
       public abstract Long getFoo();
      
       public abstract void setFoo(Long newValue);
      //...
      
       /**
       * @ejb:create-method
       * @ejb:transaction type="Required"
       */
       public MyPK ejbCreate(Long foo)
       throws CreateException {
       setFoo(foo); //throws exception
      
       return null;
       }
      //...
      }
      


      This essentially results in this code in jbosscmp-jdbc.xml:

       <entity>
       <ejb-name>My</ejb-name>
       <read-only>true</read-only>
       <table-name>xxx</table-name>
      
       <cmp-field>
       <field-name>foo</field-name>
       <column-name>foo</column-name>
       </cmp-field>
      etc
      


      However, an attempt to create such beans leads to exception in JBoss 4.x:

      Caused by: javax.ejb.EJBException: Field is read-only: fieldName=foo
       at org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCAbstractCMPFieldBridge.setValue(JDBCAbstractCMPFieldBridge.java:232)
       at org.jboss.ejb.plugins.cmp.bridge.EntityBridgeInvocationHandler$FieldSetInvoker.invoke(EntityBridgeInvocationHandler.java:170)
       at org.jboss.ejb.plugins.cmp.bridge.EntityBridgeInvocationHandler.invoke(EntityBridgeInvocationHandler.java:105)
       at org.jboss.proxy.compiler.Runtime.invoke(Runtime.java:76)
       at xxx.MyCMP$Proxy.setFoo(<generated>)
       at xxx.MyBean.ejbCreate(MyBean.java:114)
      


      How am I supposed to create instances without calling set* methods from ejbCreate?

      May be I'm wrong, but this piece in JDBCAbstractCMPFieldBridge.java looks suspicious:

       public void setValue(EntityEnterpriseContext ctx, Object value)
       {
       if(isReadOnly())
       {
       throw new EJBException("Field is read-only: fieldName=" + fieldName);
       }
       if(primaryKeyMember && JDBCEntityBridge.isEjbCreateDone(ctx))
       {
       throw new IllegalStateException("A CMP field that is a member " +
       "of the primary key can only be set in ejbCreate " +
       "[EJB 2.0 Spec. 10.3.5].");
       }
      


      I'd expect it to be something along "if(isReadOnly() && !JDBCEntityBridge.isEjbCreateDone(ctx))". This souldn't mark an instance as dirty one of course.