Session Bean The session bean in the Lab1 uses JDBC connection to retrieve conference information from the backend database directly. The Lab2 extends the application in Lab1 and adds an new entity bean ConferenceBean to separate the data model from the front end input processing. The session bean is revised to access the entity bean and the entity bean is a container-managed persistence mapped to the database table Conference.
The EJB container handles data storage and retrieval on behalf of entity bean. The purpose of this lab is to demonstrate how session beans work together with entity beans and how to divide the responsibilities between session bean and entity beans. In most distributed applications the persistent data is handled by entity beans instead of session beans. The process logic is shown in the following diagram.
Step 1. Coding the Enterprise Bean The Conference entity bean component includes the following code: Local interface: LocalConference.java Local home interface: LocalConferenceHome.java Entity bean class: ConferenceBean.java The local interface LocalConference defines three get access methods for the persistent fields so a local client can invoke the methods to retrieve data from the entity bean. The local interface must be converted to a remote interface if the clients of the bean is remote.
package Data; import java.util.*; import javax.ejb.*; // Local interface of conference CMP entity bean public interface LocalConference extends EJBLocalObject { public String getconferenceid(); public String getconferencename(); public double getregistrationfee(); }
The LocalConferenceHome.java defines the home interface for the bean. The create() method in the conference entity bean home interface takes three parameters: conference id, conference name, and registration fee. When the session bean instantiates the home interface and calls its create() method the container creates a conference instance and calls the ejbcreate() method. The conferencehome.create() and the conferencebean.ejbcreate() methods must have the same signatures, so that the parameter values can be passed from the home interface to the entity bean via the entity bean s container
The findbyprimary() method, which takes the primary key conferenceid as a parameter, is handled by container. It must be specified in the entity bean home interface to locate the Conference entity bean instance. The findall() method is a customized finder method handled by container, but a developer must define the EJB-QL query at deployment time.
package data; import java.util.*; import javax.ejb.*; // Home interface of conference CMP entity bean public interface LocalConferenceHome extends EJBLocalHome { public LocalConference create (String confid, String confname, double registfee) throws CreateException; } public LocalConference findbyprimarykey (String id) throws FinderException; public Collection findall () throws FinderException;
The ConferenceBean.java defines the entity bean implementation. The ConferenceBean is a container-managed entity bean. The EJB container handles data persistence and transaction management automatically. The EJB developers don t need writing any code to transfer data between the entity bean and the database. The ConferenceBean class defines several get and set access methods for the persistent fields. The set methods are hidden from their bean s clients because they are not defined in the LocalConference interface. The EJB container implements all the getter and setter abstract methods.
import java.util.*; import javax.ejb.*; import javax.naming.*; public abstract class ConferenceBean implements EntityBean { private EntityContext context; // Access methods for persistent fields: conferenceid, // conference name, registration fee public abstract String getconferenceid(); public abstract void setconferenceid(string confid); public abstract String getconferencename(); public abstract void setconferencename( String confname); public abstract double getregistrationfee(); public abstract void setregistrationfee( double registfee);
// EntityBean container callback methods public String ejbcreate (String confid, String confname, double registfee) throws CreateException { setconferenceid(confid); setconferencename(confname); setregistrationfee(registfee); return null; } public void ejbpostcreate (String confid, String confname, double registfee) throws CreateException { }
public void setentitycontext(entitycontext ctx) { context = ctx; } public void unsetentitycontext() { context = null; } public void ejbremove() {} public void ejbload() {} public void ejbstore() {} public void ejbpassivate() { } public void ejbactivate() { } } // ConferenceBean class
Step 2. Modify Session Bean All detailed code of SQL database connection and processing are removed from the previous session bean in lab1 since the entity bean will provide the logics for accessing the database rather than session bean itself. The remote interface, home interface and helper class ConfDetails are still the same. The modified source code DiscountCalc.Java is shown below:
//DiscountCalcBean.java package discountcalc; import java.util.*; import javax.ejb.*; import javax.naming.*; import java.rmi.remoteexception; import java.math.*; import data.*; public class DiscountCalcBean implements SessionBean { private LocalConferenceHome conferencehome = null; public void ejbcreate () {
try { InitialContext ic = new InitialContext(); conferencehome = (LocalConferenceHome) ic.lookup("java:comp/env/ejb/simpleconference"); } catch (NamingException ex) { System.out.println("Naming Exceptions"); } } public ArrayList getallconferences() { Collection conferences = null; try { conferences = conferencehome.findall(); } catch (Exception ex) { throw new EJBException(ex.getMessage()); } return confdetaillist(conferences); } // getallconferences
private ArrayList confdetaillist(collection conferences) { ArrayList detailslist = new ArrayList(); Iterator i = conferences.iterator(); while (i.hasnext()) { LocalConference conference = (LocalConference) i.next(); ConfDetails details = new ConfDetails(conference.getConferenceId(), conference.getconferencename(), conference.getregistrationfee()); detailslist.add(details); } return detailslist; } // confdetaillist
public double getdiscountedfee (double registfee, String attendeetype) { int discountrate = 0; if ( attendeetype.equals ("Member") ) discountrate = 20; else if ( attendeetype.equals ("Student") ) discountrate = 50; else discountrate = 0; return (registfee * (1 -(double)discountrate/100 )); } public DiscountCalcBean() {} public void ejbactivate() {} public void ejbpassivate() {} public void ejbremove() {} public void setsessioncontext(sessioncontext sc) {} } // DiscountCalcBean
Step 3. Compiling the Source Files To compile the source files, open a terminal window, go to c:\ejb\lab2 directory and type the following command: > asant build A new directory build with all the class files will be created under c:\ejb\lab2.
Step 4. Create database schema file To map an entity bean to a database table, a schema file need to be created. Start up PointBase database Open a terminal window, go to c:\ejb\lab2 directory and type the following command: > asant capture-db-schema A database schema file named register.dbschema will be created under c:\ejb\lab2\build directory. The capture-db-schema is defined in the targets.xml file.
Step 5. Deployment 1. Start application server, PointBase database and deploytool. 2. Create a new application named DiscountCalcApp2.ear under c:\ejb\lab2 3. Create ConferenceBean Entity Bean Select File New Enterprise Bean to start the New Enterprise Bean wizard In the EJB JAR dialog box select the Create New JAR File in the Application radio button. In the combo box, select DiscountCalcApp2. In the JAR Name field, enter DataJar. Click Edit Contents
In the tree under Available Files, locate the c:\ejb\lab2\build directory, select contents under data folder and click Add. Select register.dbschema and click Add, then click OK In the EJB JAR General Settings dialog box, select data.conferencebean for the Enterprise Bean Class combo box. Verify that the Enterprise Bean name field is ConferenceBean. Select the Entity for the Bean Type In the Local Home Interface combo box, select data.localconferencehome. In the Local Interface combo box, select data.localconference. Click Next.
Selecting the Persistent Fields and Abstract SchemaName: In Entity Bean settings dialog box select the fields that will be saved in the database In the Fields To Be Persisted list, For Conference entity bean, select conferenceid, conferencename and registrationfee. Choose Select an existing field for the Primary Key Class. Select conferenceid from the combo box. In the Abstract Schema Name field, enter Conference. This name will be referenced in the EJB QL queries.
Defining EJB-QL Queries for Finder and Select Methods: Click the Finder/Select Queries button to start Finder/Select Methods for ConferenceBean dialog box. To display a set of finder or select methods, click one of the radio buttons under the Show label To specify an EJB-QL query, choose the name of the finder or select method from the Method list and then enter the query in the field labeled EJB QL Query. Select findall, type the following EJB-QL Query for findall select object(c) from Conference c Click OK. Click Next, and Finish. Save the application.
Specifying persistent field and database mappings In the tree select ConferenceBean and click Entity tab. Click CMP Database (Sun Specific) Enter jdbc/pointbase in the JNDI Name of CMP Resource field. Select ConferenceBean for the Enterprise Bean Click Create database Mapping Select Map to Tables in Database Schema File Choose register.dbschema for the Database Schema Files in Module Click OK. Verify the field mappings, and then click Close.
Specifying Transaction Settings Select ConferenceBean in the tree. Click Transactions tab Select Container-Managed. Verify the methods and their attributes for Local, LocalHome and Bean. After the packaging process, you can view the deployment descriptor by selecting Tools Descriptor Viewer.
<?xml version='1.0' encoding='utf-8'?> <ejb-jar version=" 2.1" xmlns=" http://java.sun.com/xml/ns/j2ee" xmlns:xsi= " http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation= " http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd "> <display-name> DataJar</display-name> <enterprise-beans> <entity> <display-name> ConferenceBean</display-name> <ejb-name> ConferenceBean</ejb-name> <local-home> data.localconferencehome </local-home>
<local> data.localconference</local> <ejb-class> data.conferencebean</ejb-class> <persistence-type> Container</persistence-type> <prim-key-class> java.lang.string</prim-key-class> <reentrant> false</reentrant> <cmp-version> 2.x</cmp-version> <abstract-schema-name> Conference </abstract-schema-name> <cmp-field> <description> no description</description> <field-name> registrationfee</field-name> </cmp-field> <cmp-field> <description> no description</description> <field-name> conferencename</field-name> </cmp-field>
<cmp-field> <description> no description</description> <field-name> conferenceid</field-name> </cmp-field> <primkey-field> conferenceid</primkey-field> <security-identity> <use-caller-identity> </use-caller-identity> </security-identity> <query> <query-method> <method-name> findall</method-name> <method-params> </method-params> </query-method> <ejb-ql> select object (c)<br> from Conference c </ejb-ql>
</query> </entity> </enterprise-beans> <assembly-descriptor> <container-transaction> <method> <ejb-name> ConferenceBean</ejb-name> <method-intf> Local</method-intf> <method-name> getconferenceid</method-name> </method> <trans-attribute> Required</trans-attribute> </container-transaction> <container-transaction> <method> <ejb-name> ConferenceBean</ejb-name> <method-intf> Local</method-intf>
<method-name> getconferencename</method-name> </method> <trans-attribute> Required</trans-attribute> </container-transaction> <container-transaction> <method> <ejb-name> ConferenceBean</ejb-name> <method-intf> Local</method-intf> <method-name> remove</method-name> </method> <trans-attribute> Required</trans-attribute> </container-transaction>
<container-transaction> <method> <ejb-name> ConferenceBean</ejb-name> <method-intf> Local</method-intf> <method-name> getregistrationfee</method-name> </method> <trans-attribute> Required</trans-attribute> </container-transaction> </assembly-descriptor> </ejb-jar>
Packaging the Session Bean DiscountCalcBean In this application the data transaction is handled by Container. The session bean access the database via the entity beans so that the Resource Ref s is not required. Follow the steps in the Lab1 to package the session bean with the setting below:
Session bean Settings: Setting JAR Name Value DiscountCalcJar Contents DiscountCalc.class,DiscountCalcHome.class, DiscountCalcBean.class, ConfDetails.class Enterprise Bean Class Enterprise Bean Name Bean Type Remote Home interface discountcalc.discountcalcbean DiscountCalcBean Stateless discountcalc.discountcalchome Remote Interface discountcalc.discountcalc
Specify the Session Bean Reference: The DiscountCalcBean session bean accesses the ConferenceBean entity bean. When it invokes the lookup method, the DiscountCalcBean refers to the home of the entity beans: conferencehome = (LocalConferenceHome.ic.lookup ("java:comp/env/ejb/simpleconference"); In the tree, select DiscountCalcBean. Select the EJB Refs tab and Click Add. The settings as below:
Setting Coded Name Type Interface Value ejb/simpleconference Entity Local Home Interface Local/Remote Interface Target EJB/Enterprise Bean Name data.localconferencehome data.localconference ejb-jar-ic.jar#conferencebean
Specifying Transaction Settings: Select DiscountCalcBean in the tree. Click Transactions tab Select Container-Managed Verify methods and their attributes for Remote, RemoteHome and Bean.
5. Implement web component The index.jsp file in the Lab1 will be used for this lab. Follow the steps in the Lab1 to package the Web component, specify the JNDI name and context root. 6. Deployment Save the application Select Tools Deploy, Click OK.
Step 6. Running the application You can follow the instruction in the step 4 of the lab1 to run the DiscountCalcApp application. The result is exactly the same as in the Lab1.