0 Replies Latest reply on Jul 30, 2004 2:48 PM by cgraham

    COOKBOOK Mysql xdoclet CMP key generator example

      I have found it very hard to find a fully documented example that will help newbies do the basic stuff, so every time I find the solution to a problem that I have experienced that has taken me some time to solve I create a COOKBOOK.

      This cookbook goes through the step by step process of creating a simple CMP using xdoclet for JBOSS and Mysql where the CMP will create a new primary key for every new entity.

      1. You will need to deploy your data source for the MySQL database you wish to use. This is configured in mysql-ds.xml in the deploy dir. If you can use the real machine name for the datasource even if it is on localhost I have seen problems. If you are smart enough to remove this problem then all power to you.

      <?xml version="1.0" encoding="UTF-8"?>
      <datasources>
       <local-tx-datasource>
       <jndi-name>noiDS</jndi-name>
       <connection-url>jdbc:mysql://corbu/noi</connection-url>
       <driver-class>com.mysql.jdbc.Driver</driver-class>
       <user-name>jboss</user-name>
       <password>password</password>
       <min-pool-size>0</min-pool-size>
       </local-tx-datasource>
      </datasources>
      


      2. You will need to configure the way JBOSS entity command for CMP creation to use the MySQL generator. To do this you will need to edit the standardjbosscmp-jdbc.xml in the conf dir. REMEMBER it is important to use the right DTD for the version of JBOSS you are using.

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE jbosscmp-jdbc PUBLIC
       "-//JBoss//DTD JBOSSCMP-JDBC 3.2//EN"
       "http://www.jboss.org/j2ee/dtd/jbosscmp-jdbc_3_2.dtd">
      
      <!-- ===================================================================== -->
      <!-- -->
      <!-- Standard JBossCMP-JDBC Configuration -->
      <!-- -->
      <!-- ===================================================================== -->
      
      <!-- $Id: standardjbosscmp-jdbc.xml,v 1.39.2.34 2003/11/25 01:48:16 ejort Exp $ -->
      
      <jbosscmp-jdbc>
      
       <defaults>
       <datasource>java:/noiDS</datasource>
       <datasource-mapping>mySQL</datasource-mapping>
      
       <create-table>true</create-table>
       <remove-table>false</remove-table>
       <read-only>false</read-only>
       <read-time-out>300000</read-time-out>
       <row-locking>false</row-locking>
       <pk-constraint>true</pk-constraint>
       <fk-constraint>false</fk-constraint>
       <preferred-relation-mapping>foreign-key</preferred-relation-mapping>
       <read-ahead>
       <strategy>on-load</strategy>
       <page-size>1000</page-size>
       <eager-load-group>*</eager-load-group>
       </read-ahead>
       <list-cache-max>1000</list-cache-max>
       <unknown-pk>
       <unknown-pk-class>java.lang.Integer</unknown-pk-class>
       <field-name>id</field-name>
       <column-name>id</column-name>
       <jdbc-type>INTEGER</jdbc-type>
       <sql-type>INT(11)</sql-type>
       <auto-increment/>
       </unknown-pk>
       <entity-command name="mysql-get-generated-keys"/>
      
       </defaults>
      
      


      3. Create the mySQL table that will map into your entity. It is important to note that the primary key field needs to be set to auto_increment. Commonly if you set xdoclet to create the table when the bean is deployed the auto increment *will not* be set so take care because the mysql-get-generated-keys command wont work unless this is set. (will always return 0).

      #
      # Table structure for table `Job`
      #
      
      CREATE TABLE Job (
       id int(11) NOT NULL auto_increment,
       name varchar(250) binary default NULL,
       description varchar(250) binary default NULL,
       creationDate datetime default NULL,
       PRIMARY KEY (id)
      ) TYPE=MyISAM;
      
      


      4. You will need to create a XDOCLET 1.2.1 bean that will ultimately be the CMP to deploy. I have a simple bean that does this called job bean. It really does just act as a stub to prove that it works. Make sure to set the create table to false because you have already created your table. NOTE: If you want to have the bean create teh table make sure to go back to the mysql admin and add the auto_increment option to the primary key.

      
      package com.noi.jbossmq.ejb.ds;
      
      
      import javax.ejb.*;
      import java.util.Date;
      import java.util.Calendar;
      import java.util.Collection;
      import javax.naming.*;
      import java.rmi.*;
      import javax.rmi.PortableRemoteObject;
      
      /**
      * This is a job bean. It created using XDoclet tags.
      *
      * @ejb.bean
      * type="CMP"
      * name="Job"
      * jndi-name="comp/ejb/Job"
      * description="The Job Entity EJB"
      * display-name="Job"
      * primkey-field="id"
      *
       * @ejb.pk generate="true"
       *
       * @ejb.value-object
       * match="*"
       * name="Job"
       *
       * @ejb.finder
       * signature="java.util.Collection findAll()"
       * query="SELECT OBJECT(c) FROM Job c WHERE c.id > 0"
       * transaction-type="Supports"
       *
       * @ejb.persistence
       * table-name="Job"
       *
       * @ejb.interface remote-class="com.noi.jbossmq.ejb.ds.Job"
       *
       * @ejb.transaction
       * type="Required"
       *
       *
       * @jboss.create-table "false"
       * @jboss.remove-table "false"
       *
       *
       * @jboss.finder-query
       * name="findAll"
       * signature="java.util.Collection findAll()"
       * query="SELECT OBJECT(c) FROM Job c WHERE c.id > 0"
       *
       * @jboss.entity-command
       * name="mysql-get-generated-keys"
       *
       *
       */
      public abstract class JobBean extends BaseEntityBean implements EntityBean {
       public EntityContext mContext;
      
      
      
       /**
       * Id of this job.
       *
       * This is not remote since the primary key can be extracted by other means.
       *
       * @ejb.pk-field
       * @ejb.persistent-field
       * @ejb.interface-method
       *
       * @ejb.persistence column-name="id"
       *
       * @jboss.auto-increment
       *
       *
       */
       public abstract Integer getId();
      
      
      
       /**
       * Id of this product.
       *
       */
       public abstract void setId(Integer id);
      
      
       /**
       * Name of the product.
       *
       * @ejb.interface-method
       * @ejb.persistent-field
       * @ejb.transaction type="Supports"
       * @jboss.column-name "name"
       *
       */
       public abstract String getName();
      
       /**
       * ejb:interface-method
       */
       public abstract void setName(String name);
      
      
       /**
       * Description of the product.
       *
       * @ejb.interface-method
       * @ejb.persistent-field
       * @ejb.transaction type="Supports"
       * @jboss.column-name "description"
       *
       */
       public abstract String getDescription();
      
       /**
       * ejb:interface-method
       */
       public abstract void setDescription(String description);
      
      
       /**
       * Generated bulk accessor. This is set as remote to allow clients to get all data in one call.
       *
       * @ejb.interface-method
       * @ejb.transaction
       * type="Supports"
       */
       public abstract JobData getData();
      
       /**
       * Generated bulk accessor. This is set as remote to allow clients to get all data in one call.
       *
       * @ejb.interface-method
       * @ejb.transaction
       * type="Supports"
       */
       public abstract void setData(JobData data);
      
      
       /**
       * @ejb.create-method
       */
       public Object ejbCreate( )
       throws CreateException
       {
       setCreationDate(new Date());
       return null;
       }
      
       /**
       * @ejb.create-method
       */
       public Object ejbCreate(
       JobData data
       )
       throws CreateException{
       try{
      
       setId(data.getId());
       setName(data.getName());
       setDescription(data.getDescription());
       setCreationDate(new Date());
       }
       catch(Exception e)
       {
      
       throw new CreateException(e.getMessage());
       }
       return null;
       }
      
      
       public void ejbPostCreate( )
       throws CreateException {}
      
       public void ejbPostCreate(
       JobData data
       )
       throws CreateException
       {
       }
      
      
       public void setEntityContext( EntityContext lContext ) {mContext = lContext;}
       public void unsetEntityContext(){ mContext = null; }
       public void ejbActivate(){}
       public void ejbPassivate(){}
       public void ejbLoad(){}
       public void ejbStore(){}
      
       // EntityBean implementation -------------------------------------
       /**
       * Remove
       *
       * @ejb.transaction type="Mandatory"
       */
       public void ejbRemove() throws RemoveException {}
      
      
      }
      
      *********************
      
      package com.noi.jbossmq.ejb.ds;
      
      import javax.ejb.*;
      
      /**
       * SuperClass for all entity beans, implementing common entity bean methods.
       *
       * @author <a href="mailto:youremail@yourdomain.com">youremail@yourdomain.com</a>
       * @version $Revision: 1.6 $
       */
      public abstract class BaseEntityBean {
       /** Reference to EntityContext. */
       protected EntityContext entityContext = null;
      
       /**
       * The creation-date of the entity. This field is purely to track when
       * this entity was created, and should be set in ejbCreate
       * (<code>setCreationDate(new Date());</code>.
       * It is not included in the value object.
       *
       * <p>We use the qualified name here because XDoclet doesn't copy imports from
       * base classes into the generated interfaces.</p>
       *
       * @ejb.persistence column-name="creationDate"
       * @ejb.interface-method
       *
       * @ejb.value-object exclude="true" match="*"
       *
       */
       public abstract java.util.Date getCreationDate();
      
       public abstract void setCreationDate(java.util.Date creationDate);
      
       /**
       * Gets the EntityContext. To be used by classes extending this.
       * @return the EntityContext of the EJB
       */
       protected EntityContext getEntityContext() {
       return entityContext;
       }
      
       /** Required to implement EntityBean. Sets the EntityContext. */
       public void setEntityContext(EntityContext entityContext) throws EJBException {
       this.entityContext = entityContext;
       }
      
       /** Required to implement EntityBean. Sets the EntityContext to null. */
       public void unsetEntityContext() throws EJBException {
       entityContext = null;
       }
      
       /** Required to implement EntityBean. Not implemented. */
       public void ejbActivate() throws EJBException { }
      
       /** Required to implement EntityBean. Not implemented. */
       public void ejbPassivate() throws EJBException { }
      
       /** Required to implement EntityBean. Not implemented. */
       public void ejbLoad() throws EJBException { }
      
       /** Required to implement EntityBean. Not implemented. */
       public void ejbStore() throws EJBException { }
      
       /** Required to implement EntityBean. Not implemented. */
       public void ejbRemove() throws RemoveException, EJBException { }
      }
      
      
      
      


      5. The client needs to create the ejb and then set the data. My client is a MDB that converts a JMS text message and then persists the Job entity.

       private void makeJob(Message message)
       {
       try{
       TextMessage textMessage = null;
       textMessage = (TextMessage)message;
       String queryObjName = "comp/ejb/Job";
      
       Context ctx = new InitialContext();
       Object objref = ctx.lookup(queryObjName);
       JobHome home = (JobHome)PortableRemoteObject.narrow(objref, JobHome.class);
       System.out.println("message bean attempts to create.");
       Job newjob = home.create();
       JobData data = newjob.getData();
       data.setName(textMessage.getText());
       data.setDescription("A JOB");
       newjob.setData(data);
      
       }
       catch(Exception e){
       String emessage = e.getMessage();
       String errorClass = e.getClass().getName();
       System.out.println("class: "+ errorClass+" exception:"+emessage);
       }
      
       }
      
      



      I *think* this pretty much covers it. I really hope I didn't leave anything out but if I did I am very sorry. Good luck because I know how hard it is to find answers to simple things sometimes.

      Clay