In Practice
The ChalkTalk application needs the capability to read and save data to the database structure. We have read and written data to the database using JDBC; now it is time to accomplish the same task using entity beans. The process of building the beans is rather simple; most of our work will be executed in the session facade.
Building the Persistence Layer
The creation of the persistence layer using JBuilder depends on the appropriate data structure being completed. In Chapter 15, "Database Connectivity," we created the necessary data store for our application. We will now create the entity beans to manage this persistence. The following steps are used to build the necessary entity beans:The creation of the persistence layer using JBuilder depends on the appropriate data structure being completed. In Chapter 15, "Database Connectivity," we created the necessary data store for our application. We will now create the entity beans to manage this persistence. The following steps are used to build the necessary entity beans:
-
Import a schema from our data source in the EJB module containing our session beans. This is accomplished by right-clicking on the data source node when we are in the EJB Designer and selecting Import Schema from Datasource.
-
Set the following database parameters:
-
Driver: com.borland.datastore.jdbc.DataStoreDriver
-
URL: jdbc:borland:dslocal:C:\JBDG\db\ChalkTalk.jds
-
Username: leave blank
-
Password: leave blank
-
Right-click on each table and create a CMP 2.0 entity bean for each table. For example, right click on the table Room and create a CMP 2.0 bean.
-
Define relationships.
Configuring an Entity Bean
Typically each entity bean that has been created requires more finder methods than just a findByPrimaryKey. Our Room entity bean is a perfect example.
-
Right-click on our Room entity bean. Add a finder method.
-
Configure the following properties for the finder method:
-
Name: findAll
-
Return type: java.util.Collection
-
Input parameters: leave empty
-
Home interfaces: Local Home
-
Query: SELECT OBJECT(o) FROM RoomSchema AS o
-
Compile and save.
Creating an EJB Connection Factory
This factory supplies caching to both local and remote interfaces. Although this connection factory differentiates between local and remote interfaces, you have the capability to make this interface ubiquitous. The following steps build your EJB connection factory:
-
Create a new class within your project, calling it EJBConnectionFactory.
-
Move the newly created class to the package com.sams.chalktalk.beans.
-
Add the following code to implement the connection to both local and remote beans in addition to placing them into a cache when the connection has been established:
-
Compile and save your project.
package com.sams.chalktalk.beans; import javax.naming.*; import java.util.*; import javax.ejb.*; class EJBHomeFactory { private static EJBHomeFactory instance = null; private Context initialContext; private Map ejbHomes; private EJBHomeFactory() throws NamingException { initialContext = new InitialContext(); ejbHomes = Collections.synchronizedMap(new HashMap()); } public static EJBHomeFactory getInstance() throws NamingException { if(instance == null) { instance = new EJBHomeFactory(); } return instance; } public EJBLocalHome lookupByLocalEJBReference(String ejbReferenceComponent) throws NamingException { java.lang.Object home = ejbHomes.get(ejbReferenceComponent); if(home == null) { home = initialContext.lookup("java:comp/env/ejb/" + ejbReferenceComponent); ejbHomes.put(ejbReferenceComponent, home); } return (EJBLocalHome) home; } public EJBHome lookupByRemoteEJBReference(String ejbReferenceComponent, Class homeClass) throws NamingException { java.lang.Object home = ejbHomes.get(ejbReferenceComponent); if(home == null) { java.lang.Object obj = initialContext.lookup("java:comp/env/ejb/" + ejbReferenceComponent); home = javax.rmi.PortableRemoteObject.narrow(obj, homeClass); ejbHomes.put(ejbReferenceComponent, home); } return (EJBHome) home; } }
Creating a Manager Bean
A manager bean surfaces the business logic and ultimately interfaces to the persistence utilizing the entity beans. These manager beans will then be attached to the session facade to consolidate the middle-tier access. The following steps are required to create one of the manager beans:
-
Create a new class, naming the class RoomManager and placing the new class in the package com.sams.chalktalk.beans.
-
The following code surfaces the required business logic. The requirements of the manager class are used to implement all the appropriate business logic, such as checking to make sure that a room has a capacity.
package com.sams.chalktalk.beans; import javax.naming.*; import javax.ejb.*; import java.util.*; class RoomManager { //Add a home factory for caching the home interfaces private EJBHomeFactory homeFactory; private static RoomManager instance = null; //Use the RoomValueFactory to create private RoomValueFactory roomValueFactory; private RoomManager() throws NamingException { homeFactory = EJBHomeFactory.getInstance(); } public static RoomManager getInstance() throws NamingException { if(instance == null) { instance = new RoomManager(); } return instance; } public String createRoom(RoomValue roomValue) throws FinderException, NamingException { try { RoomHome roomHome = (RoomHome) homeFactory.lookupByLocalEJBReference("Room"); Room room = roomHome.create(roomValue.getLocation(),roomValue. getCapacity() ,roomValue.getName(),roomValue.getKey()); return room.getName(); } catch(Exception e) { throw new EJBException(e); } } public void updateRoom(RoomValue roomValue) throws FinderException, NamingException { try { Room room = roomValueFactory.findRoom(roomValue.getKey()); room.setCapacity(roomValue.getCapacity()); } catch(Exception e) { throw new EJBException(e); } } public void removeRoom(Short key) throws FinderException, NamingException { try { Room room = roomValueFactory.findRoom(key); room.remove(); } catch(Exception e) { throw new EJBException(e); } } public void removeAllRooms() throws FinderException, NamingException { try { Collection rooms = roomValueFactory.findAllRooms(); Iterator iterator = rooms.iterator(); Room room = null; while(iterator.hasNext()) { room = (Room) iterator.next(); room.remove(); } } catch(Exception e) { throw new EJBException(e); } } }
Attaching the Session Facade
Our session facade wraps multiple manager beans together into one session bean. In other words, we will access all functionality for our ChalkTalk system utilizing this one session bean. The following steps are required to attach the facade to our manager bean:
-
Define a private member for each type of bean manager you want to use. For example, the following code defines one for our RoomManager:
-
Create an instance of our manager bean within ejbCreate(). The following demonstrates the implementation using our RoomManager:
-
Attach the manager bean call to be called from the corresponding session bean method. If the client calls the createRoom method of the session bean, it then needs to pass the information to the manager class. The following code demonstrates such an implementation:
-
Compile and save your project.
private RoomManager roomManager;
public void ejbCreate() throws CreateException { try { roomManager = RoomManager.getInstance(); } catch (NamingException ex) { //pass exception to the container throw new EJBException(ex); }
public void createRoom(RoomValue room) { try { roomManager.createRoom(room); } catch (Exception ex) { throw new EJBException(ex); } }
Testing the Implementation
It is time to test the client we created. The easiest way to test the session facade is to build a client dedicated to testing the interface. The following steps build a test client to exercise this facade:
-
Select File, New from the JBuilder menu.
-
Within the Object Gallery, under the Enterprise tab, select the EJB Test Client.
-
Specify the following parameters to build our test client:
-
EJB name: ChalkTalkFacade
-
Package: com.sams.chalktalk.client
-
Class name: ChalkTalkFacadeTestClient
-
Generate Method for Testing Remote Interface Calls with Arguments: Checked
-
Generate Logging Messages: Checked
-
Generate Main Functions: Checked
-
Generate Header Comments: Checked
-
Add the following code to the main method to test your session bean interface:
-
Save, compile, and run your test application.
//create a Remote interface client.create(); //Add a room client.addRoom(new RoomData(5,"Small Room",5,"2nd Floor")); //Add with invalid capacity client.addRoom(new RoomData(3,"Error Room",0,"3rd Floor"));