- Overview
- The javax.ejb Package for Entity Beans
- Entity Bean Types
- Remote Versus Local Interfaces
- BMP Entity Bean Lifecycle
- Specifying a BMP Entity Bean
- Implementing a BMP Entity Bean
- Configuring and Deploying a BMP Entity Bean
- Client's View
- Session Beans Revisited
- Patterns and Idioms
- Gotchas
- Summary
- Q&A
- Exercises
Session Beans Revisited
The case study for today has the same set of Session beans as yesterday, and their interfaces are the same. However, their implementation is quite different, because they delegate all database interactions to the Entity bean layer.
As an example, Listing 6.13 shows the updateDetails() method in the stateful AdvertiseJob bean. The AdvertiseJob bean provides services for managing jobs.
Listing 6.13AdvertiseJobBean.updateDetails() Without an Entity Bean Layer
1: package agency; 2: 3: import java.util.*; 4: import javax.ejb.*; 5: import java.sql.*; 6: // imports omitted 7: 8: public class AdvertiseJobBean extends SessionBean 9: { 10: public void updateDetails(String description, String location, String[] skills) { 11: if (skills == null) { 12: skills = new String[0]; 13: } 14: Connection con = null; 15: PreparedStatement stmt = null; 16: try { 17: con = dataSource.getConnection(); 18: stmt = con.prepareStatement( "UPDATE JOB SET description = ?, location = ? WHERE ref = ? AND customer = ?"); 19: stmt.setString(1, description); 20: stmt.setString(2, location); 21: stmt.setString(3, ref); 22: stmt.setString(4, customer); 23: stmt.executeUpdate(); 24: stmt = con.prepareStatement( "DELETE FROM JobSkill WHERE job = ? AND customer = ?"); 25: stmt.setString(1, ref); 26: stmt.setString(2, customer); 27: stmt.executeUpdate(); 28: stmt = con.prepareStatement( "INSERT INTO JobSkill (job, customer, skill) VALUES (?, ?, ?)"); 29: for (int i = 0; i < skills.length; i++) { 30: stmt.setString(1, ref); 31: stmt.setString(2, customer); 32: stmt.setString(3, skills[i]); 33: stmt.executeUpdate(); 34: } 35: this.description = description; 36: this.location = location; 37: this.skills.clear(); 38: for (int i = 0; i < skills.length; i++) 39: this.skills.add(skills[i]); 40: } 41: catch (SQLException e) { 42: error("Error updating job " + ref + " for " + customer, e); 43: } 44: finally { 45: closeConnection(con, stmt, null); 46: } 47: } 48: }
Listing 6.14 shows the updated version, delegating the hard work to the Job bean:
Listing 6.14AdvertiseJobBean.updateDetails() with an Entity Bean Layer
1: package agency; 2: 3: import java.util.*; 4: import javax.ejb.*; 5: import data.*; 6: // imports omitted 7: 8: public class AdvertiseJobBean extends SessionBean 9: { 10: private JobLocal job; 11: public void updateDetails(String description, String locationName, String[] skillNames) { 12: if (skillNames == null) { 13: skillNames = new String[0]; 14: } 15: List skillList; 16: try { 17: skillList = skillHome.lookup(Arrays.asList(skillNames)); 18: } catch (FinderException ex) { 19: error("Invalid skill", ex); // throws an exception 20: return; 21: } 22: LocationLocal location = null; 23: if (locationName != null) { 24: try { 25: location = locationHome.findByPrimaryKey(locationName); 26: } catch (FinderException ex) { 27: error("Invalid location", ex); // throws an exception 28: return; 29: } 30: } 31: job.setDescription(description); 32: job.setLocation(location); 33: job.setSkills(skillList); 34: } 35: // code omitted 36: }
The updated version is much more object-oriented; the knowledge of the database schema has been encapsulated where it rightfully belongsin the Entity bean layer.
All this means that the AdvertiseJob bean no longer has any dependencies on the jdbc/Agency DataSource. On the other hand, it does now have dependencies on several of the Entity beans. These are defined using ejb-local-ref elements in the deployment descriptor. The relevant portion of the AdvertiseJob deployment descriptor (agency_session_ejbs_ejb-jar.xml file in the dd directory) is shown in Listing 6.15:
Listing 6.15AdvertiseJob Bean's Reference to the Entity Beans
1: <ejb-local-ref> 2: <ejb-ref-name>ejb/SkillLocal</ejb-ref-name> 3: <ejb-ref-type>Entity</ejb-ref-type> 4: <local-home>data.SkillLocalHome</local-home> 5: <local>data.SkillLocal</local> 6: <ejb-link>data_entity_ejbs.jar#SkillBean</ejb-link> 7: </ejb-local-ref> 8: <ejb-local-ref> 9: <ejb-ref-name>ejb/LocationLocal</ejb-ref-name> 10: <ejb-ref-type>Entity</ejb-ref-type> 11: <local-home>data.LocationLocalHome</local-home> 12: <local>data.LocationLocal</local> 13: <ejb-link>data_entity_ejbs.jar#LocationBean</ejb-link> 14: </ejb-local-ref> 15: <ejb-local-ref> 16: <ejb-ref-name>ejb/JobLocal</ejb-ref-name> 17: <ejb-ref-type>Entity</ejb-ref-type> 18: <local-home>data.JobLocalHome</local-home> 19: <local>data.JobLocal</local> 20: <ejb-link>data_entity_ejbs.jar#JobBean</ejb-link> 21: </ejb-local-ref> 22: <ejb-local-ref> 23: <ejb-ref-name>ejb/CustomerLocal</ejb-ref-name> 24: <ejb-ref-type>Entity</ejb-ref-type> 25: <local-home>data.CustomerLocalHome</local-home> 26: <local>data.JobLocal</local> 27: <ejb-link>data_entity_ejbs.jar#CustomerBean</ejb-link> 28: </ejb-local-ref>
Note the ejb-link reference, which names the bean that implements the required interfaces. This notation is used rather than a JNDI name because JNDI can (potentially) refer to remote EJBs, whereas local EJBs mustby definitionbe deployed on the same server.