In this lesson, you will create a new entity
bean. In this example scenario, you have a business requirement to
include a tally of bonus reward points for each registered user. The
WebSphere Commerce database schema does not contain a table to store
this information, so you need to create a new database table. In accordance
with the WebSphere Commerce programming model, once the database table
is created, you must create an entity bean to access the data.
About this task
Creating the XBONUS table
In preparation
for creating the entity bean, you must first create the new database
table named XBONUS. In this tutorial, you will create the table in
your development database. In a different environment such as a production
environment, the creation of a new table can be controlled by the
schema architect. Ensure you adhere to your company's conventions
before creating a new table.
Procedure
- Start
or restart the WebSphere Commerce test server.
- In a Web browser, enter the following URL:
http://localhost/webapp/wcs/admin/servlet/db.jsp
- In the input box, enter the following SQL statement:
create table XBONUS (MEMBERID BIGINT NOT NULL, BONUSPOINT INTEGER NOT NULL, OPTCOUNTER SMALLINT NOT NULL,
constraint p_xbonus primary key (MEMBERID), constraint f_xbonus foreign key (MEMBERID) references users (users_id) on delete cascade);
create table XBONUS (MEMBERID NUMBER NOT NULL,BONUSPOINT INTEGER NOT NULL, OPTCOUNTER SMALLINT NOT NULL,
constraint p_xbonus primary key (MEMBERID), constraint f_xbonus foreign key (MEMBERID references users (users_id) on delete cascade);
- Click Submit Query.
- Create the BonusBean entity bean
- In the Enterprise Explorer view,
expand .
- Right-click Deployment Descriptor: WebSphereCommerceServerExtensionsData;
select
- In the Create and Enterprise Bean window:
- Select Entity bean with container-managed persistence
(CMP) fields
- In the Bean name field, enter
Bonus
.
- In the Source folder field, leave the default
value, ejbModule.
- In the Default package field, enter
com.ibm.commerce.extension.objects
.
- From the CMP Version list, select 1.x.
- Click Next.
- In the Enterprise Bean Details window, add new CMP attributes
for the MEMBERID and BONUSPOINT columns in the BONUS table:
- Select the default CMP attribute id:java.lang.Integer and
click Remove.
- Click Add.
- In the Name field, enter
memberId
.
- In the Type field, enter
java.lang.Long
. You
must use the java.lang.Long
data type, not the long
data
type, since the column memberId that you are trying to map to is BIGINT
or NUMBER.
- Select the Key Field check box to indicate
that this field is the primary key of the database table.
- Click Apply.
- In the Name field, enter
bonusPoint
.
- In the Type field, enter
java.lang.Integer
. You
must use the java.lang.Integer
data type, not the integer
data
type.
- Ensure the Access with getter and setter methods check
box is selected. By selecting this option all getter and setter methods
will be automatically generated for all fields.
- Clear the Promote getter and setter methods to remote
interface check box. The Make getter read-only check
box will be made unavailable. Clearing the promote getter and setter
methods to remote interface causes less overhead and better performance.
Since the getter and setter methods are not promoted to the remote
interface, clients will not be able to access the methods. Instead
of using the remote interface, CopyHelper Access Beans exist that
contain getters and setters for CMP fields that do not exist on the
remote interface. The methods within the CopyHelper Access Beans write
data to a hash table that in turn updates the database when commitCopyHelper()
is called. The hash table can record multiple database changes then
update the database in one transaction, unlike the remote methods
which require one transaction per change. A method called refreshCopyHelper()
that does the reverse function of commitCopyHelper(). The method refreshCopyHelper()
writes to the hash table from the database. Deselecting the box ensures
that the hashtable is used, resulting in the performance increase.
- Click Apply.
- Optional: In the Name field, enter
optCounter
.
- Optional: In the Type field, enter
short
.
- Clear the Access with getter and setter methods check
box.
- Click Apply then Close to
close this window.
- Ensure the Use the single key attribute type for the
key class check box is not selected, then click Next.
Ensuring this check box is not selected ensures that a key class is
created, ensuring consistency with other beans.
- In the EJB Java Class Details window, create the entity
bean called Bonus:
- To select the bean's superclass, click Browse.
- In the Type Selection window, in the Select a class
using: (any) field, enter
ECEntityBean
and
click OK.
- Specify the interfaces that the remote interface should extend
by clicking Add.
- In the Type Selection window, in the Select an interface
using: (any) field, enter
Protectable
and
click OK to select com.ibm.commerce.security.Protectable.
This interface is required in order to protect the new resource under
access control.
- Click Next.
- Deselect Add bean to Class Diagram.
- Click Finish.
- Set the isolation level for the new bean:
- Expand
- Right-click the Bonus bean and
open the bean in its deployment descriptor.
- Click the Access tab.
- Next to the Isolation Level text box, click Add.
- In the Add Isolation Level window, select Read
committed, then click Next.
- From the Beans found list, select
the Bonus bean, then click Next.
- From the Methods found list,
select Bonus to select all of its methods,
and click Finish.
- Save your changes and keep the editor open.
- Set the security identity of the bean:
- Select the Access tab selected.
- In the Security Identity (Method Level) section,
click Add.
- Select Use identity of EJB server,
then click Next. The Use identity of EJB server
field ensures that all EJB beans run under the same identity for security.
- From the Beans found list, select
the Bonus bean, then click Next.
- From the Methods found list,
select Bonus to select all of its methods,
and click Finish.
- Save your changes and keep the editor open.
- Set the security role for the methods in the bean:
- In the Deployment Descriptor editor, select the Assembly tab.
- In the Method Permissions section,
click Add.
- Select Security Roles then WCSecurityRole and
click Next. This is the default security role
for all EJB beans in WebSphere Commerce.
- From the list of beans found, select Bonus and
click Next.
- In the Method elements page, click Apply
to All, then click Finish.
- Save your changes.
- Remove the unused generated fields and methods. The ECEntityBean
base class provides its own implementation of these methods:
- In the Java EE view, expand
- Open the BonusBean class for
editing
- In the Outline view removed the unused fields:
- Select the myEntityCtx field and from its
pop-up menu, select Delete.
- Select the getEntityContext() method and
from its pop-up menu, select Delete.
- Select the setEntityContext(EntityContext) method
and from its pop-up menu, select Delete.
- Select the unsetEntityContext() method
and from its pop-up menu, select Delete.
- Save your changes. Keep the BonusBean class open.
- Add a new getMemberId method to the enterprise bean:
- Add the following method to the end of this class:
public java.lang.Long getMemberId() {
return memberId;
}
- Add the new method to the remote interface. In the Outline
view, right-click the getMemberId method and
select . Once this is complete,
a small R icon displays next to the method, indicating that it has
been promoted to the remote interface.
- Save your changes.
- Close the BonusBean class.
- Add a FinderHelper method to the BonusHome interface. FinderHelper
methods allow you to write your own finders where you might not know
the primary key, but need to select on other columns. A FinderHelper
method contains the SQL statements used by your bean's finder methods.
A findByPrimaryKey() method is created for an EJB bean but is often
not sufficient because you might not know the primary key.
- In the EJB Deployment Descriptor editor, click the Bean tab.
- In the Beans pane, select the Bonus bean.
- Click Add next to the Finders text
box, as in the following screen capture:
- In the Name field, enter
findByMemberId
.
- Click Add next to the Parameters text
box.
- In the Name field, enter
memberId
.
- In the Type field enter
java.lang.Long
.
- Click OK.
- From the Return Type list, select com.ibm.commerce.extension.objects.Bonus,
then click Next.
- From the Finder type list, select WhereClauseFinderDescriptor.
In this field, you specify the
where
clause for a select
statement
in a finder. You must provide the where
clause of
a select statement in the EJB FinderHelper method. You do not need
to provide the full select
statement since the EJB
container manages the table.
- In the Finder statement field,
enter
T1.MEMBERID = ?
, then click Finish.
T1 is an alias to the XBONUS table. When the FinderHelper runs, the
SQL statement that will run is "select T1.MEMBERID, T1.BONUSPOINT
FROM XBONUS T1 WHERE T1.MEMBERID = ? ". The "?" is replaced with the
dynamic value of String provided to the findByMemberId(String) .
- Save your changes.
- Create new ejbCreate and ejbPostCreate methods. You use
the ejbCreate method to insert a row into the database table. Add
a new ejbCreate method to the Bonus bean:
- In the Enterprise Explorer view,
open the BonusBean and view its source code.
- Create a new ejbCreate(Long, Integer) method, by adding
the following code into the class:
public com.ibm.commerce.extension.objects.BonusKey ejbCreate(
java.lang.Long memberId,java.lang.Integer bonusPoint)
throws javax.ejb.CreateException {
_initLinks();
this.memberId=memberId;
this.bonusPoint=bonusPoint;
return null;
}
- Save the code changes. The following warning might display
in the task view:
This class should implement a matching ejbPostCreate
method for this method
. You create the ejbPostCreate method
later in this tutorial.
- You must add the new ejbCreate(Long, Integer) method
to the home interface. This makes the method available in the generated
access bean. In the Outline view, right-click the ejbCreate(Long,
Integer) method and select .
- create a new ejbPostCreate(Long, Integer) method so
that it has the same parameters as the ejbCreate(Long, Integer) method.
Every ejbCreate(arg1, arg2) method must have a corresponding ejbPostCreate(arg1,
arg2) method according to the EJB specification requirements. Create
a new ejbPostCreate(Long, Integer) method so that it has the same
parameters as the ejbCreate(Long, Integer) method:
- In the BonusBean class, create a new ejbPostCreate(Long,
Integer) method, by adding the following code into the class:
public void ejbPostCreate(java.lang.Long memberId,
java.lang.Integer bonusPoint)
throws javax.ejb.CreateException
{
}
- Save the code changes. The warning about a missing matching ejbPostCreate
method is resolved.
- Add getOwner and fulfills methods. The next section adds
new methods, getOwner and fulfills, to the Bonus bean so that the
bean can be protected by the WebSphere Commerce access control system.
Access beans and data beans that do not have getOwner and fulfills
methods and do not extend a protectable class are not protected under
access control. Only the commands that invoke the access beans and
data beans are protected.
- In the BonusBean class, add the
new getOwner method to the BonusBean class by adding the following
code into the end of the class:
public java.lang.Long getOwner()
throws java.lang.Exception {
return getMemberId();
}
- Save your work.
- Add the new fulfills method, by adding the following
code to the end of the class:
public boolean fulfills(Long member, String relationship)
throws java.lang.Exception {
if ("creator".equalsIgnoreCase(relationship))
{
return member.equals(getMemberId());
}
return false;
}
- Save the file.
- Creating a database and table definition
- Right-click WebSphereCommerceServerExtensionsData and
select .
- From the wizard, select and enter MyDBSchema as
the file name.
- Select the appropriate database type for your development
environment:
- DB2 for Linux, UNIX, and Windows
- Oracle
- The destination folder should populate after selecting
the database type.
- Select the appropriate database version:
- Click Finish.
- In the Enterprise Explorer view, navigate to .
- Right-click . In the properties panel, enter NULLID in the name
field. You use NULLID as the schema name because this allows flexibility
for EJB beans to work against any schema. If the schema name is filled
in with a specific value other than NULLID, the EJB bean would only
work for tables created using a specific schema.
- Right-click . Enter XBONUS as the table name.
- Add columns to the table by clicking the Columns tab
and clicking the New symbol, just above the name column:
- Create the following columns:
MEMBERID column properties
and values
Property |
Value |
Name |
MEMBERID |
Primary key |
Selected |
Data type |
|
Length |
38 |
Scale |
0 |
Not null |
Selected |
BONUSPOINTcolumn properties and values
Property |
Value |
Name |
BONUSPOINT |
Data type |
INTEGER |
Not null |
Selected |
OPTCOUNTER column properties and values
Property |
Value |
Name |
OPTCOUNTER |
Data type |
SMALLINT |
Not null |
Selected |
Your resulting tables should resemble the following structure:
- Click Finish.
- Map the XBONUS table to the entity bean. Since your Bonus
bean and the XBONUS table already exist, Meet-in-the-middle mapping
is used.
- In the Java EE perspective, right-click the WebSphereCommerceServerExtensionsData EJB
project and select .
- On the first page of the Mapping wizard you are asked
to Specify the backend folder that will contain generated
mapping file, database schema and other runtime information. Use
an existing backend folder should be selected by default.
- Click Next
- Select Meet In The Middle and
click Next.
- Select None and click Finish.
The Map.mapxmi editor opens.
- In the Enterprise Beans pane, highlight the Bonus bean.
In the Tables pane, highlight the XBONUS table.
- Map the fields in the Bonus bean to the columns in the
XBONUS table by right-clicking the Bonus bean and selecting Match
By Name from the bean's pop-up menu.
- Save the Map.mapxmi file and leave it open.
- Enable Optimistic Locking
- In the Enterprise Explorer view,
navigate to .
- Open the deployment descriptor for editing.
- In the Bean tab, select the Bonus bean.
- In the lower right pane, scroll down to the Concurrency
Control section.
- Select Enable optimistic locking.
- Save your changes.
- Set the optimistic predicate value of the optcounter field
- In the Enterprise Explorer view, navigate to .
- Double-click mall: DERBY_V100 to
open the Mapping Editor.
- In the Overview section, in the Enterprise
Beans pane, select optcounter : short.
- Select the Properties view, and
select true from the OptimisticPredicate list.
Your screen should resemble the following screen capture:
- Edit methods to call optimistic locking classes. In the BonusBean class
make the following changes:
- In the Outline view, select ejbLoad() and
add the following code as the first line in the method:
super.ejbLoad();
- In the Outline view, select ejbStore() and
add the following code as the first line in the method:
super.ejbStore();
- In the Outline view, select ejbCreate(Long,
Integer) and add the following code:
- Add
this.initializeFields();
as the first line
in the method.
- Add the following two lines to the method before the return statement
BonusKey myNewKey = new BonusKey(memberId);
this.initializeOptCounter(myNewKey);
The resulting method
should look like the following:
public com.ibm.commerce.extension.objects.BonusKey ejbCreate( java.lang.Long memberId,java.lang.Integer bonusPoint) throws javax.ejb.CreateException {
this.initializeFields();
_initLinks();
this.memberId=memberId;
this.bonusPoint=bonusPoint;
BonusKey myNewKey = new BonusKey(memberId);
this.initializeOptCounter(myNewKey);
return null;
}
- Save your changes.
- Create an access bean
- Right click the WebSphereCommerceServerExtensionsData project
and select .
- From the New wizard, and select and click Next.
- Select Copy helper and click Next.
- Select the Bonus bean and click Next.
- From the Constructor Method list,
select findByPrimaryKey(com.ibm.commerce.extension.objects.BonusKey) and
click Finish.
- In the EJB Deployment Descriptor Editor, in the Overview tab,
scroll down to the JNDI - CMP Connection Factory Binding section
and in the JNDI name field enter the value
that matches your database type:
- Save your changes
- Generate deploy code and regenerate the BonusAccessBean.
The code generation utility analyzes the beans to ensure that Sun
Microsystems' EJB specifications are met and it ensures that rules
specific to the EJB server are followed. In addition, for each selected
enterprise bean, the code-generation tool generates the home and EJBObject
(remote) implementations and implementation classes for the home and
remote interfaces, as well as the JDBC persister and finder classes
for CMP beans. It also generates the Java ORB, stubs, and tie classes
required for RMI access over IIOP, as well as stubs for the home and
remote interfaces.
- Navigate to .
- Select the WebSphereCommerceServerExtensionsData project.
- From the project's pop-up menu, select .
- After the deploy code is generated, Rational Application
Developer rebuilds the workspace. When the workspace building completes,
ensure you have no errors in the Problems view.
- To regenerate the BonusAccessBean:
- Navigate to .
- From the deployment descriptor's pop-up menu, select .
- On the Select access beans to regenerate window,
click Deselect All.
- Select only BonusAccessBean.
- Click Finish.
- Save all files.