Introducing Container Managed Persistance (CMP) fundamental concepts.

If you are used to writing webapps based on JSP and Servlets, you know how tedious it can be to use JDBC whenever you need to update your database with new information. By creating EJB components with container managed persistence, you let Resin-CMP generate the tedious SQL to load, store, and cache entity beans from the database.

Overview

Each CMP bean needs at least three classes:

- The home interface (CourseHome.java) to find and create entities,
- The local interface (Course.java) to represent the actual entities,
- The implementation class (CourseBean.java) which contains the bean's business logic,

and one XML file,

- The deployment descriptor (cmp-basic.ejb).

The bean also needs a database table that it can use to permanently store its fields. Each entity will be stored in a row of this table. (One field must be designated as the primary key). The name of the table is specified in the deployment descriptor by the <abstract-schema-name> tag. Our CourseBean will use the following schema: ``

    CREATE TABLE basic_courses (
      course_id VARCHAR(250) NOT NULL,
      instructor VARCHAR(250),
      PRIMARY KEY(course_id)
    );

    # manually create two sample entities
    INSERT INTO basic_courses VALUES('Potions', 'Severus Snape');
    INSERT INTO basic_courses VALUES('Transfiguration', 'Minerva McGonagall');

The Deployment Descriptor

The deployment Descriptor for the Course Bean looks like this:

`<ejb-jar>
<enterprise-beans>
<entity>
<ejb-name>basic_CourseBean</ejb-name>
<local-home>example.cmp.basic.CourseHome</local-home>
<local>example.cmp.basic.Course</local>
<ejb-class>example.cmp.basic.CourseBean</ejb-class>
<persistence-type>Container</persistence-type>
<reentrant>True</reentrant>
<prim-key-class>java.lang.String</prim-key-class>
<primkey-field>courseId</primkey-field>
<abstract-schema-name>basic_courses</abstract-schema-name>
<cmp-field>
<field-name>instructor</field-name>
</cmp-field>
<cmp-field>
<field-name>courseId</field-name>
</cmp-field>
</entity>
</enterprise-beans>
</ejb-jar>
`

<ejb-name> denotes the name that this bean is to be referenced by. Resin-CMP also uses this name as the Bean's JNDI name (see below).

The database schema is defined in the deployment descriptor (cmp-basic.ejb) with <cmp-field> tags. Each <cmp-field> specifies the name of a field that is to be kept persistant by the container. For example, in this example there is a <cmp-field> 'instructor'. Therefore, we need an instructor field in our table, and in the implementation class we need to define two related methods: ``

        public abstract String getInstructor();
        public abstract void setInstructor(String val);

These will be implemented by the container, which fills in the actual JDBC code.

Using the CMP Bean

Before you can use the CMP bean, it needs to be deployed. Resin-CMP looks for *.ejb deployment descriptors in an application's WEB-INF directory. If a found deployment descriptor is valid, Resin-CMP will automatically deploy all beans that it references. This includes the automatic implementation and compilation of the Home and Local interfaces.

Once the CMP Bean is deployed, we use the home interface to obtain references to entities that are already stored in the database. First, we use JNDI to find the Home Interface. The deployment descriptor defines where the Home Interface is mapped into JNDI: ``

          Context ejb = (Context) new InitialContext().lookup("java:comp/env/cmp");

          home = (CourseHome) ejb.lookup("basic_CourseBean");

The Home Interface must always declare the method findByPrimaryKey(...) that will return the entity associated with a particular primary key. You declare this method abstract and let Resin-CMP implement it for you. Its return type needs to be that of the local interface - in our case, `Course`.
Since we have initialized the database with two sample records, we know that there is an entity with the primary key "Potions". We can use the findPrimaryKey(...) method to obtain a reference to the associated entity: ``

        try {
          Course course = home.findByPrimaryKey("Potions");
        }
        catch (FinderException e) {
          throw new ServletException(e);
        }

From here on the application developer starts to really benefit from CMP. If we were to change the instructor for the Potions course, we could call: ``

          course.setInstructor("Scott");

This call will automatically update the database to reflect the change in the instructor field. Resin-CMP has generated all neccessary SQL.