Creating a new entity bean

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

  1. Start or restart the WebSphere Commerce test server.
  2. In a Web browser, enter the following URL: http://localhost/webapp/wcs/admin/servlet/db.jsp
  3. In the input box, enter the following SQL statement:
    • Apache DerbyDB2
      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);
      
    • Oracle
      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);
      
  4. Click Submit Query.
  5. Create the BonusBean entity bean
    1. In the Enterprise Explorer view, expand WebSphereCommerceServerExtensionsData.
    2. Right-click Deployment Descriptor: WebSphereCommerceServerExtensionsData; select New > Enterprise Bean
    3. In the Create and Enterprise Bean window:
      1. Select Entity bean with container-managed persistence (CMP) fields
      2. In the Bean name field, enter Bonus.
      3. In the Source folder field, leave the default value, ejbModule.
      4. In the Default package field, enter com.ibm.commerce.extension.objects.
      5. From the CMP Version list, select 1.x.
      6. Click Next.
    4. In the Enterprise Bean Details window, add new CMP attributes for the MEMBERID and BONUSPOINT columns in the BONUS table:
      1. Select the default CMP attribute id:java.lang.Integer and click Remove.
      2. Click Add.
      3. In the Name field, enter memberId.
      4. 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.

      5. Select the Key Field check box to indicate that this field is the primary key of the database table.
      6. Click Apply.
      7. In the Name field, enter bonusPoint.
      8. In the Type field, enter java.lang.Integer.

        You must use the java.lang.Integer data type, not the integer data type.

      9. 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.
      10. 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.
      11. Click Apply.
      12. Optional: In the Name field, enter optCounter.
      13. Optional: In the Type field, enter short.
      14. Clear the Access with getter and setter methods check box.
      15. Click Apply then Close to close this window.
      16. 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.
    5. In the EJB Java Class Details window, create the entity bean called Bonus:
      1. To select the bean's superclass, click Browse.
      2. In the Type Selection window, in the Select a class using: (any) field, enter ECEntityBean and click OK.
      3. Specify the interfaces that the remote interface should extend by clicking Add.
      4. 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.
      5. Click Next.
      6. Deselect Add bean to Class Diagram.
      7. Click Finish.
  6. Set the isolation level for the new bean:
    1. Expand WebSphereCommerceServerExtensionsData > Deployment Descriptor > Entity Beans
    2. Right-click the Bonus bean and open the bean in its deployment descriptor.
    3. Click the Access tab.
    4. Next to the Isolation Level text box, click Add.
    5. In the Add Isolation Level window, select Read committed, then click Next.
    6. From the Beans found list, select the Bonus bean, then click Next.
    7. From the Methods found list, select Bonus to select all of its methods, and click Finish.
    8. Save your changes and keep the editor open.
  7. Set the security identity of the bean:
    1. Select the Access tab selected.
    2. In the Security Identity (Method Level) section, click Add.
    3. 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.
    4. From the Beans found list, select the Bonus bean, then click Next.
    5. From the Methods found list, select Bonus to select all of its methods, and click Finish.

    6. Save your changes and keep the editor open.
  8. Set the security role for the methods in the bean:
    1. In the Deployment Descriptor editor, select the Assembly tab.
    2. In the Method Permissions section, click Add.
    3. Select Security Roles then WCSecurityRole and click Next. This is the default security role for all EJB beans in WebSphere Commerce.
    4. From the list of beans found, select Bonus and click Next.
    5. In the Method elements page, click Apply to All, then click Finish.
    6. Save your changes.
  9. Remove the unused generated fields and methods. The ECEntityBean base class provides its own implementation of these methods:
    1. In the Java EE view, expand WebSphereCommerceServerExtensionsData > Entity Beans > Bonus
    2. Open the BonusBean class for editing
    3. In the Outline view removed the unused fields:
      1. Select the myEntityCtx field and from its pop-up menu, select Delete.
      2. Select the getEntityContext() method and from its pop-up menu, select Delete.
      3. Select the setEntityContext(EntityContext) method and from its pop-up menu, select Delete.
      4. Select the unsetEntityContext() method and from its pop-up menu, select Delete.
    4. Save your changes. Keep the BonusBean class open.

  10. Add a new getMemberId method to the enterprise bean:
    1. Add the following method to the end of this class:
      public java.lang.Long getMemberId() {
         return memberId;
      }
      
    2. Add the new method to the remote interface. In the Outline view, right-click the getMemberId method and select Enterprise Bean > Promote to Remote Interface. Once this is complete, a small R icon displays next to the method, indicating that it has been promoted to the remote interface.
    3. Save your changes.
    4. Close the BonusBean class.
  11. 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.
    1. In the EJB Deployment Descriptor editor, click the Bean tab.
    2. In the Beans pane, select the Bonus bean.
    3. Click Add next to the Finders text box, as in the following screen capture:

      A screen capture displaying the Finders text box.
    4. In the Name field, enter findByMemberId.
    5. Click Add next to the Parameters text box.
      1. In the Name field, enter memberId.
      2. In the Type field enter java.lang.Long.
      3. Click OK.
    6. From the Return Type list, select com.ibm.commerce.extension.objects.Bonus, then click Next.
    7. 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.
    8. 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) .
    9. Save your changes.
  12. 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:
    1. In the Enterprise Explorer view, open the BonusBean and view its source code.
    2. 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;
      }
      
    3. 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.
    4. 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 Enterprise Bean > Promote to Home Interface.
    5. 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:
      1. 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
           {
           }
        
      2. Save the code changes. The warning about a missing matching ejbPostCreate method is resolved.
  13. 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.
    1. 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();
         }
      
    2. Save your work.
    3. 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;
         }
      
    4. Save the file.
  14. Creating a database and table definition
    1. Right-click WebSphereCommerceServerExtensionsData and select New > Other.
    2. From the wizard, select Data > Physical Data Model and enter MyDBSchema as the file name.
    3. Select the appropriate database type for your development environment:
      • Apache DerbyDB2DB2 for Linux, UNIX, and Windows
      • OracleOracle
    4. The destination folder should populate after selecting the database type.
    5. Select the appropriate database version:
      • Apache DerbyDB2Version 9.5
      • OracleVersion 11
    6. Click Finish.
    7. In the Enterprise Explorer view, navigate to WebSphereCommerceServerExtensionsData > Data Models > MyDBSchema.dbm.
    8. Right-click Database > Add Data Object > Schema. 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.
    9. Right-click NULLID > Add Data Object > Table. Enter XBONUS as the table name.
    10. Add columns to the table by clicking the Columns tab and clicking the New symbol, just above the name column:
      1. Create the following columns:
        MEMBERID column properties and values
        Property Value
        Name MEMBERID
        Primary key Selected
        Data type
        • Apache DerbyDB2BIGINT
          Note: If selected, the other properties cannot be modified by default.
        • OracleNumber
        Length

        Oracle38

        Scale

        Oracle0

        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:<Table> XBONUS screen capture

      2. Click Finish.
  15. 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.
    1. In the Java EE perspective, right-click the WebSphereCommerceServerExtensionsData EJB project and select Java EE > EJB to RDB Mapping (1.x - 2.x) > Generate Map.
    2. 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.
    3. Click Next
    4. Select Meet In The Middle and click Next.
    5. Select None and click Finish. The Map.mapxmi editor opens.
    6. In the Enterprise Beans pane, highlight the Bonus bean. In the Tables pane, highlight the XBONUS table.
    7. 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.
    8. Save the Map.mapxmi file and leave it open.
  16. Enable Optimistic Locking
    1. In the Enterprise Explorer view, navigate to WebSphereCommerceServerExtensionsData > Deployment Descriptor.
    2. Open the deployment descriptor for editing.
    3. In the Bean tab, select the Bonus bean.
    4. In the lower right pane, scroll down to the Concurrency Control section.
    5. Select Enable optimistic locking.
    6. Save your changes.

  17. Set the optimistic predicate value of the optcounter field
    1. In the Enterprise Explorer view, navigate to WebSphereCommerceServerExtensionsData > Deployment Descriptor > Maps > Derby 10.0 > mall.
    2. Double-click mall: DERBY_V100 to open the Mapping Editor.
    3. In the Overview section, in the Enterprise Beans pane, select optcounter : short.
    4. Select the Properties view, and select true from the OptimisticPredicate list. Your screen should resemble the following screen capture:

      Selecting Properties, true, from the OptimisticPredicate list.
  18. Edit methods to call optimistic locking classes. In the BonusBean class make the following changes:
    1. In the Outline view, select ejbLoad() and add the following code as the first line in the method: super.ejbLoad();
    2. In the Outline view, select ejbStore() and add the following code as the first line in the method: super.ejbStore();
    3. In the Outline view, select ejbCreate(Long, Integer) and add the following code:
      1. Add this.initializeFields(); as the first line in the method.
      2. 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;
         }
    4. Save your changes.
  19. Create an access bean
    1. Right click the WebSphereCommerceServerExtensionsData project and select New > Others... .
    2. From the New wizard, and select EJB > Access Bean and click Next.
    3. Select Copy helper and click Next.
    4. Select the Bonus bean and click Next.
    5. From the Constructor Method list, select findByPrimaryKey(com.ibm.commerce.extension.objects.BonusKey) and click Finish.
    6. 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:
      • Apache Derby jdbc/WebSphere Commerce Cloudscape DataSource demo
      • DB2 jdbc/WebSphere Commerce DB2 DataSource demo
      • For IBM i OS operating systemjdbc/WebSphere Commerce iSeries DataSource demo
      • Oraclejdbc/WebSphere Commerce Oracle DataSource demo
        The following screen capture is an example using a Cloudscape database:
        An example using a Cloudscape database

        Ensure there are no spaces appended to the JNDI name. Spaces at the end of the JNDI will cause errors when the binding is created.

    7. Save your changes
  20. 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.
    1. Navigate to WebSphereCommerceServerExtensionsData.
    2. Select the WebSphereCommerceServerExtensionsData project.
    3. From the project's pop-up menu, select Java EE > Prepare for Deployment.
    4. 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.
  21. To regenerate the BonusAccessBean:
    1. Navigate to WebSphereCommerceServerExtensionsData.
    2. From the deployment descriptor's pop-up menu, select Java EE > Access Beans > Regenerate Access Beans.
    3. On the Select access beans to regenerate window, click Deselect All.
    4. Select only BonusAccessBean.
    5. Click Finish.
    6. Save all files.

Results