Beruflich Dokumente
Kultur Dokumente
Joaquin Picon, Patrizia Genchi, Maneesh Sahu, Martin Weiss, Alain Dessureault
SG24-5429-00
SG24-5429-00
International Technical Support Organization Developing Enterprise JavaBeans with VisualAge for Java May 1999
5429edno.fm
Take Note!
Before using this information and the product it supports, be sure to read the general information in Appendix E, Special Notices on page 379.
First Edition (May 1999) This edition applies to VisualAge for Java Enterprise Edition 2.0 with the Enterprise JavaBeans update for use with the Windows Operating System and WebSphere Advanced Edition 2.0. Comments may be addressed to: IBM Corporation, International Technical Support Organization Dept. QXXE Building 80-E2 650 Harry Road San Jose, California 95120-6099 When you send information to IBM, you grant IBM a non-exclusive right to use or distribute the information in any way it believes appropriate without incurring any obligation to you.
Copyright International Business Machines Corporation 1999. All rights reserved Note to U.S Government Users Documentation related to restricted rights Use, duplication or disclosure is subject to restrictions set forth in GSA ADP Schedule Contract with IBM Corp.
Contents
Figures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xv Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii The Team That Wrote This Redbook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xviii Comments Welcome . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .xix
iii
3.2
3.3
3.4
3.5
Session Bean Life Cycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Creation state . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Ready state . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Pooled state . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Removal state . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Developing Session Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 Writing the Enterprise Bean Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 Implementing the business methods . . . . . . . . . . . . . . . . . . . . . . . . . 25 Implementing the ejbCreate methods . . . . . . . . . . . . . . . . . . . . . . . . 27 Implementing the SessionBean interface . . . . . . . . . . . . . . . . . . . . . 29 Writing the Home Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 Writing the Remote Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Developing Session Bean inside VisualAge for Java . . . . . . . . . . . . . . . 34 Creating EJBs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 First step: adding EJB Groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Second step: adding EJB to EJB Groups . . . . . . . . . . . . . . . . . . . . . . 39 Generating Deployed Code. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 The deployment descriptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 The ejb-jar file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Deploying an enterprise Bean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Generate the Test Client. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 Testing EJBs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Setting Name Service and EJB Server Properties . . . . . . . . . . . . . . 68 Starting the Name Service and EJB Servers. . . . . . . . . . . . . . . . . . . 71 Restarting Servers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 Running the Generated Test Client . . . . . . . . . . . . . . . . . . . . . . . . . . 73 Writing Your Own Client Application . . . . . . . . . . . . . . . . . . . . . . . . . . 79 Importing required Java packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 Instantiating an EJB Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 Stopping the Name Service and EJB Servers . . . . . . . . . . . . . . . . . . . . . 85 Running the client outside VisualAge for Java . . . . . . . . . . . . . . . . . . . 85 Exporting EJB Groups and EJBs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Exporting EJBs to EJS or EJB Jar Files . . . . . . . . . . . . . . . . . . . . . . 85 Exporting EJBs to Client Jar files . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Running the client outside VisualAge for Java . . . . . . . . . . . . . . . . . . . 90 Deployment on WebSphere Advanced Edition 2.0. . . . . . . . . . . . . . . . . 91 Deployment for Other Enterprise JavaBeans Servers . . . . . . . . . . . . . 97 Deployment using WebSphere tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
Chapter 4. Developing a Container-managed persistence bean 107 4.1 Container-Managed Persistence basics . . . . . . . . . . . . . . . . . . . . . . . . 107 4.2 Developing a CMP Bean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Creating a Container-managed persistence bean. . . . . . . . . . . . . . . . . 109 Projects, packages and reserved package organization . . . . . . . . . . . . 118
iv
Understanding the generated types . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 Adding fields to the Bean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 Removing a field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 Regarding the other modifiers (final, transient, static) . . . . . . . . . 129 Working with the key Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 4.3 Understanding the generated methods . . . . . . . . . . . . . . . . . . . . . . . . 132 Life cycles of enterprise Bean instances . . . . . . . . . . . . . . . . . . . . . . . . 132 Creation State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 Pooled State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 Ready State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 Removal State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 The CustomerBeans generated methods . . . . . . . . . . . . . . . . . . . . . . . 134 The CustomerHome interfaces generated methods . . . . . . . . . . . . 136 The CustomerKeys generated methods. . . . . . . . . . . . . . . . . . . . . . 137 4.4 Adding remote interface methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 Methods inherited from javax.ejs.EJBObject . . . . . . . . . . . . . . . . . . . . 139 Using valid parameters and return values for Java RMI . . . . . . . . . . 140 4.5 Modifying, adding home methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 4.6 Generating Database Schema and mapping . . . . . . . . . . . . . . . . . . . . 141 The top-down approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 The bottom-up approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 The meet-in-middle approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 Creating the CMP sample database . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 Importing a database schema into VisualAge for Java . . . . . . . . . . . . 148 Defining a map between the EJBs and the database schema . . . . . . . 153 4.7 Adjusting the deployment descriptor attributes . . . . . . . . . . . . . . . . . 158 4.8 Generating your deployed code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 4.9 Adding Special Finder methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 Insert a finder method declaration in the CustomerHome interface . 161 Create a query string in the CustomerFinderHelper interface . . . . . . 161 4.10 Testing your Bean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 Chapter 5. Developing a Bean-managed persistence bean. . . . . 173 5.1 Bean-managed persistence Entity bean . . . . . . . . . . . . . . . . . . . . . . . . 173 5.2 The TransactionRecord Entity bean . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 Creating the Entity bean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 Adding and defining BMP fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 Understanding the Generated Methods . . . . . . . . . . . . . . . . . . . . . . . . 177 Modifying the Key Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 Adding Remote Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 Modifying and Adding Home Methods . . . . . . . . . . . . . . . . . . . . . . . . . 180 5.3 XML - The eXtensible Markup Language . . . . . . . . . . . . . . . . . . . . . . 182 Introduction to XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
The Document Object Model- DOM. . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 5.4 Persisting to an XML File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 Organizing the XML file. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 Accessing the DOM. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 Creating the Persister Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 5.5 Optimizing the Bean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190 5.6 Specifying Environment Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 5.7 Transaction Management of the XML BMP . . . . . . . . . . . . . . . . . . . . 192 Chapter 6. Naming Services. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 6.1 System view . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 6.2 Naming Service Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 Location Service Daemon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 Persistent Name Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 EJB Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 6.3 Using and Configuring Naming Service . . . . . . . . . . . . . . . . . . . . . . . . 199 Client looking for an object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 Changing host name to Persistent Name Server and EJB server. . . . 205 Chapter 7. Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 7.1 Enterprise JavaBeans & Transactions. . . . . . . . . . . . . . . . . . . . . . . . . 212 The Bean-managed demarcation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 The Container-managed demarcation . . . . . . . . . . . . . . . . . . . . . . . . . . 213 The Transaction attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 Transaction Isolation Levels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 7.2 EJB Transactions & CORBA OTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215 CORBA OTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215 Transactional vs Recoverable Objects . . . . . . . . . . . . . . . . . . . . . . . . . . 217 7.3 Implementing Session Synchronization . . . . . . . . . . . . . . . . . . . . . . . . 217 7.4 Scenarios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 Scenario Description. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 The implementation model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 myTransactionTest.test1() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 myTransaction.test2( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 myTransaction.test3( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 7.5 The test cases results. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 Result tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 Test scenarios results explanation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 Case 1: Effect of the TX_REQUIRED attribute. . . . . . . . . . . . . . . . 226 Case 2: Effect of the TX_MANDATORY attribute. . . . . . . . . . . . . . 227 Case 3: Effect of the TX_NOT_SUPPORTED attribute . . . . . . . . . 227 Case 4 and case 5: Effect of the TX_REQUIRES_NEW attribute . 228
vi
Case 6: Effect of the TX_SUPPORTS attribute . . . . . . . . . . . . . . . . 228 Concurrent access from multiple transactions. . . . . . . . . . . . . . . . . . . 228 Transactions and Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 Client-demarcated transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
Chapter 8. Security. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235 8.1 EJB Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235 8.2 Identifying and Authenticating the Caller . . . . . . . . . . . . . . . . . . . . . . 236 8.3 Application Server Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 Protecting resources by access control lists . . . . . . . . . . . . . . . . . . . . . 236 Users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 Groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 Permissions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238 Realms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238 Access control lists. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 Choosing authentication schemes and protocols . . . . . . . . . . . . . . . . . 240 About authentication protocols. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 About authentication schemes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 Combining authentication schemes and protocols . . . . . . . . . . . . . . . . 242
vii
Chapter 11. Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 11.1 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 11.2 Requirements for the Inheritance. . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 11.3 Programming Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 Remote Interface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 EJB Homes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 Primary Key Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 11.4 Mapping Schemes for Relational Databases . . . . . . . . . . . . . . . . . . . 268 11.5 Developing the BankAccount Hierarchy . . . . . . . . . . . . . . . . . . . . . . 270 Developing the Remote Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 The BankAccount Superclass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 Developing Subclass EJBs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 Proxy Superclass. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 Defining the Inheritance Mapping Scheme . . . . . . . . . . . . . . . . . . . . . 274 11.6 Accessing the BankAccount Hierarchy. . . . . . . . . . . . . . . . . . . . . . . . 275 The TypeConverter Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 11.7 Relationships and Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 SingleLink . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 public BankAccount getBankAccount() . . . . . . . . . . . . . . . . . . . . . . 278 ManyLink . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 public Enumeration getBankAccounts() . . . . . . . . . . . . . . . . . . . . . 279 public void addBankAccount(BankAccount acc) . . . . . . . . . . . . . . . 279 public void removeBankAccount(BankAccount acc) . . . . . . . . . . . . 279 public void removeAllMembers() . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 11.8 The Future of EJB Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 Chapter 12. Bank Implementation Entity Beans. . . . . . . . . . . . . . 281 12.1 Developing the BankAccount Hierarchy . . . . . . . . . . . . . . . . . . . . . . 282 Developing the BankAccount Bean . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 Add the CMP Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 Modify the Generated Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 Add the Remote Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 Specify the Relationships . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 Developing the Children EJBs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 12.2 Developing the Bank Entity Bean . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 Add Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284 Add new methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 Modify the Generated Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 Add Methods to the Remote Interface . . . . . . . . . . . . . . . . . . . . . . . 289 12.3 Developing the Customer Entity Bean . . . . . . . . . . . . . . . . . . . . . . . . 290 Add Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290 Add new methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
viii
Modify the Generated Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 Add Methods to the Remote Interface . . . . . . . . . . . . . . . . . . . . . . . 295 Adding Finder Methods to CustomerHome . . . . . . . . . . . . . . . . . . . . . 295 12.4 Developing the TransactionRecord Entity Bean . . . . . . . . . . . . . . . . 296 Add Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296 Add new methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298 Modify the Generated Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299 Add Methods to the Remote Interface . . . . . . . . . . . . . . . . . . . . . . . 301 Adding Finder Method to TransactionRecordHome . . . . . . . . . . . . . . . 301 12.5 Creating the Bank Schemas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301 12.6 Creating the Bank Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302 Chapter 13. Bank implementation UserSB . . . . . . . . . . . . . . . . . . . 305 13.1 The UserSB sequence diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306 UserSB Customer Authentication Sequence Diagram. . . . . . . . . . . . . 306 UserSB Customer GetAccounts Sequence Diagram. . . . . . . . . . . . . . . 308 UserSB Customer Deposit Sequence Diagram . . . . . . . . . . . . . . . . . . . 309 UserSB Customer Withdraw Sequence Diagram . . . . . . . . . . . . . . . . . 310 UserSB Customer GetBalance Sequence Diagram . . . . . . . . . . . . . . . 310 UserSB Customer GetHistory Sequence Diagram . . . . . . . . . . . . . . . . 311 UserSB Customer Transfer Sequence Diagram . . . . . . . . . . . . . . . . . . 312 UserSB Customer PayBill Sequence Diagram . . . . . . . . . . . . . . . . . . . 313 13.2 Creating the UserSB Session Bean . . . . . . . . . . . . . . . . . . . . . . . . . . 314 Add Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315 Add New Methods. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320 Modify the Generated Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326 Add Methods to the Remote Interface . . . . . . . . . . . . . . . . . . . . . . . . . . 328 Generate Deployed Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 Chapter 14. Bank Implementation AdminSB . . . . . . . . . . . . . . . . . 331 14.1 Developing the AdminSB Session Bean . . . . . . . . . . . . . . . . . . . . . . . 331 Add Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 Add new methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333 Modify the Generated Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338 Add Methods to the Remote Interface . . . . . . . . . . . . . . . . . . . . . . . . . . 339 Generate Deployed Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
ix
A.4 Starting and Stopping WebSphere Advanced Edition 2.0 . . . . . . . . . 351 Appendix B. Transaction Samples Appendix . . . . . . . . . . . . . . . . . 353 B.1 Installing and running the transaction samples . . . . . . . . . . . . . . . . . 353 Creating the DB2 database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 Importing the transaction.dat repository . . . . . . . . . . . . . . . . . . . . . . . 354 Adding the TransactionSamples project to the workspace . . . . . . . . . 354 Generating the deployed code and running the samples . . . . . . . . . . . 355 B.2 Output Samples. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356 Appendix C. ITSOBANK database . . . . . . . . . . . . . . . . . . . . . . . . . . . 365 C.1 database Definition DDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365 C.2 Sample Data of ITSOBANK Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . 369 Appendix D. Samples and BANK Application . . . . . . . . . . . . . . . . 373 Appendix E. Special Notices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379 Appendix F. Related Publications . . . . . . . . . . . . . . . . . . . . . . . . . . . 383 F.1 International Technical Support Organization Publications . . . . . . . 383 F.2 Redbooks on CD-ROMs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384 F.3 Other Publications. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384 How to Get ITSO Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385 How IBM Employees Can Get ITSO Redbooks. . . . . . . . . . . . . . . . . . . . . . 385 How Customers Can Get ITSO Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . 386 IBM Redbook Order Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 List of Abbreviations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401 ITSO Redbook Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
5429LOF.fm
Figures
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. SanFrancisco basic architecture. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 SanFrancico future model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Global Enterprise JavaBeans View from Client and Server . . . . . . . . 17 The TransferBean class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 The business methods of the TransferBean class . . . . . . . . . . . . . . . . . 27 The ejbCreate method of the TransferBean class . . . . . . . . . . . . . . . . . 29 Implementing the SessionBean interface in the TransferBean class . 31 The TransferHome home interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 The Transfer remote interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 VisualAge for Java main window. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 EJB Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Adding a new EJB Group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 EJB Page After the Creation of the New Group . . . . . . . . . . . . . . . . . . 39 Create EJB SmartGuide. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Create ReadCustomerInfo EJB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Adding Import Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 EJB Workspace after the Creation of the New EJB . . . . . . . . . . . . . . . 45 Create Field smartguide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 Create fileName Field. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 Create Method smartguide. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Create Method SmartGuide - First Page . . . . . . . . . . . . . . . . . . . . . . . . 51 Create Method SmartGuide - Second Page . . . . . . . . . . . . . . . . . . . . . . 52 RaedCustomerInfoBean in the EJB Workspace . . . . . . . . . . . . . . . . . . 55 Properties Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Environment Properties Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Environment Properties Page after Definition of a Property . . . . . . . . 60 Definition of the Properties Field. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Getting Properties from the Context . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Retrieve Environment Variable Value from Properties . . . . . . . . . . . . 61 Method properties Window. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 Method Selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Modify Method Control Descriptor Window . . . . . . . . . . . . . . . . . . . . . 63 EJB WorkSpace after the EJB Deployment Code Generation . . . . . . . 65 Generate Test Client. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 EJB Server Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Location Service Properties Dialog . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 Persitent Name Service Property Dialog. . . . . . . . . . . . . . . . . . . . . . . . 70 EJB Server Properties Dialog. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
xi
5429LOF.fm 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81.
Console After all Servers are Started. . . . . . . . . . . . . . . . . . . . . . . . . . . 72 Connect Window for the ReadCustomerInfo Session Bean . . . . . . . . . 75 Home Test Client Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Remote Test Client Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 Testing Remote Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 Inspector Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 Read Customer Client Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Exporting .jar Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 Export to an EJB jar File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 Export to an EJB Client jar File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 IBM WebSphere Application Server Administration Login . . . . . . . . . 92 Container Page inside WebSphere. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Deploy Jar File Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Redeployment Selection window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 EJB Jar Copy Window. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Exporting to EJB Jar files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Undeploy Jar file window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 EJB Jar Undeploy Result Window. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 WebSphere Navigation Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 The jet Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 jet Tool Message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 The jet Tool after Importing the ReadCustomerInfo Bean. . . . . . . . . 103 Using Jet Tool to Modify a Property Value . . . . . . . . . . . . . . . . . . . . . 104 The SmartGuide Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 Project not Found . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 Create EJB SmartGuide. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 EJB Class Attributes and Interfaces Definition . . . . . . . . . . . . . . . . . 115 Customer CMP Entity Bean Generated Classes. . . . . . . . . . . . . . . . . 117 Association between EJB Reserved Package and Project. . . . . . . . . . 119 Association between EJB Class package and Project . . . . . . . . . . . . . 120 CustomerCMP Entity Beans Fields . . . . . . . . . . . . . . . . . . . . . . . . . . 123 Create Field SmartGuide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 New Fields Created. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 CMP Fields Icon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 Dummy Member Field Declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 Workbench without Dummy Field . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 Transient Field Modifier Utilization Example . . . . . . . . . . . . . . . . . . 130 Methods added to the Remote Interface are identified by an Icon . . 139 Remote Interface generated Methods . . . . . . . . . . . . . . . . . . . . . . . . . 139 Association Between CMP Fields and Database Columns . . . . . . . . . 142 Selection with Schema Browser: Database, Tables, Converters . . . . 143 With Map Browser Associate Fields and Columns . . . . . . . . . . . . . . . 144 EJB Server Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
xii
5429LOF.fm
82. Characteristics of DB2 Table and Columns Created for CMP Fields 146 83. Schema Browser Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 84. Database Connection Info Window VisualAge for Java . . . . . . . . . . . 150 85. Select Tables Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 86. Schema Browser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 87. Column Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 88. CustomerSchema class Created After Saving the Schema. . . . . . . . . 153 89. Map Browser Window. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 90. New Datastore Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 91. Map Browser Window with Customer Table Map . . . . . . . . . . . . . . . 155 92. Property Map Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 93. Customer Property Map Editor Window. . . . . . . . . . . . . . . . . . . . . . . 157 94. CMPSMap class Created After Saving the Map . . . . . . . . . . . . . . . . . 157 95. Properties Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 96. Checking Your Server is Ready . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 97. Running the Test Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 98. Customer EJB Test Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 99. Customer Home Interface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 100. CustomerKey Creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 101. Customer Remote Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 102. Customer getName() Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 103. New CustomerKey Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 104. Retrieve Dessureault Customer instance Using FindByLastName. . 171 105. The Create EJB SmartGuide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 106. The Create Field SmartGuide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 107. The Generated Methods and Classes. . . . . . . . . . . . . . . . . . . . . . . . . . 178 108. Mapping Entity Beans to an XML File . . . . . . . . . . . . . . . . . . . . . . . . 184 109. Document Type Definition (DTD) for the TransactionRecord . . . . . . 185 110. The Document Object Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 111. Setting an Environment Property in the Deployment Descriptor . . . 192 112. JNDI Architecture. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196 113. WebSphere Advanced Edition 2.0: System View . . . . . . . . . . . . . . . . 197 114. Creating the InitialContext Object . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 115. Changing the Boot Port Value in WebSphere Advanced Edition 2.0. 201 116. Creating the EJBHome object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 117. Changing the JNDI Name under VisualAge for Java. . . . . . . . . . . . . 203 118. Changing the JNDI Name with Jet Tool . . . . . . . . . . . . . . . . . . . . . . . 204 119. Creating the EJB Object. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 120. Accessing an EJB from a Different Machine . . . . . . . . . . . . . . . . . . . . 206 121. Opening the EJB Server Configuration. . . . . . . . . . . . . . . . . . . . . . . . 206 122. EJB Server Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 123. Persistent Name Server Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 124. Location for Persistent Naming Information . . . . . . . . . . . . . . . . . . . 208
xiii
5429LOF.fm
125. EJB Server Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 126. OTS Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216 127. SimpleClient Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219 128. MyTransactionTest.test1() method . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 129. MyTransactionTest.test2() Method . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 130. MyTransactionTest.test3() Method . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 131. Access Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 132. System View of the Bank Application . . . . . . . . . . . . . . . . . . . . . . . . . 246 133. Bank Application Class Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 134. Single-table mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268 135. Root/leaf mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 136. Distinct-table mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 137. BankAccount Inheritance Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . 270 138. Simulating Inheritance by delegation . . . . . . . . . . . . . . . . . . . . . . . . . 272 139. Mapping the BankAccount Hierarchy to the Database . . . . . . . . . . . 274 140. UserSB Customer Authentication Sequence Diagram . . . . . . . . . . . . 307 141. UserSB GetAccounts Sequence Diagram . . . . . . . . . . . . . . . . . . . . . . 308 142. UserSB Deposit Sequence Diagram. . . . . . . . . . . . . . . . . . . . . . . . . . . 309 143. UserSB Withdraw Sequence Diagram. . . . . . . . . . . . . . . . . . . . . . . . . 310 144. UserSB getBalance Sequence Diagram . . . . . . . . . . . . . . . . . . . . . . . . 311 145. UserSB getHistory Sequence Diagram . . . . . . . . . . . . . . . . . . . . . . . . 312 146. UserSB transfer Sequence Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . 313 147. UserSB PayBill Sequence Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . 314 148. Properties for the UserSB. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315 149. UserSB generetaed code. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 150. Import from an EJB Jar File window . . . . . . . . . . . . . . . . . . . . . . . . . 346 151. Import from CreateCustomerInfo EJB Jar File . . . . . . . . . . . . . . . . . 347 152. EJB Workspace after Importing and EJB .jar . . . . . . . . . . . . . . . . . . 349 153. WebSphere Application Server Java Engine Setup . . . . . . . . . . . . . . 350 154. ITSOEJBSamples EJB Group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355 155. ITSOBANK Database Data Definition Language (Part1) . . . . . . . . . 366 156. ITSOBANK Database Data Definition Language (Part 2) . . . . . . . . . 367 157. ITSOBANK Database Data Definition Language (Part 3) . . . . . . . . . 368 158. ITSOBANK Data (Part 1). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369 159. ITSOBANK Data (Part 2). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370 160. ITSOBANK Data (Part 3). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371 161. ITSOBANK Data (Part 4). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372 162. SG24-5429 Directory Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373
xiv
5429LOT.fm
Tables
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. Container-Managed fields mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 Creating the Different DOM Nodes in the hierarchy. . . . . . . . . . . . . . 187 Accessing the Different DOM Nodes . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 Scenario 1 - TX_REQUIRED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 Scenario 2 - TX_MANDATORY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 Scenario 3 TX_NOT_SUPPORTED . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 Scenario 4 TX_REQUIRES_NEW . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 Scenario 5- TX_REQUIRED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 Create Field bankName . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284 Create Field customerLink . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 Create Field accountLink. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 Create Fields for the Customer Bean . . . . . . . . . . . . . . . . . . . . . . . . . . 291 Create Field bankAccountLink . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 Create Field bank . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292 Create Field accountId and traccId . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 Create Field transamt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 Create Field transamt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 Create Field accountLink. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298 Create Bank Schema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302 Create Bank Datastore Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302 Bank Table Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 Bank Property Map Relationship . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 Create Field bankAccountHome . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316 Create Field bankHome . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316 Create Field custKey . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317 Create Field customerHome . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317 Create Field customerRef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318 Create Field initialCtx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318 Create Field loginPassword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 Create Field loginStatus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 Create Field transactionRecordHome . . . . . . . . . . . . . . . . . . . . . . . . . . 319 Create Field for AdminSB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
xv
5429LOT.fm
xvi
5429pref.fm
Preface
With the introduction of the Enterprise JavaBeans specification, application developers can now focus on writing the business logic necessary to support their application without having to deal with the intricacies of the underlying middleware which still gives crucial services such as transactions, security, naming and persistency. IBM is exploiting this specification in a family of compatible Java application servers conforming to IBMs Enterprise Server for Java (EJS) specification. In addition, IBM has already introduced the support for EJB development into its awarded Java development tool: VisualAge for Java version 2.1. By Including in this new version the EJS runtime, VisualAge for Java provides a unique Rapid Application Development environment to develop, debug and test EJBs. In this book we explore in depth the EJB specification and apply this knowledge to develop an application including all different facets of EJB: Session bean, Bean-Managed, Container-Managed persistence entity beans, transaction (JTS), security, naming service (JNDI). We also address relationships and inheritance which are issues not yet addressed by Enterprise JavaBeans specification.
xvii
5429pref.fm
developing JAVA applications.She has worked as a SanFrancisco Technical consultant in the last 2 years. She holds a degree in Mathematics from the University of Bari. Martin Weiss is an Advisory IT Specialist in Switzerland. He has been with IBM since 1978, working in application development (IBM mainframe, AS/400, OS/2, Windows NT). Since 1993 he has focused on object technology, primary as a developer and mentor in VisualAge customer projects (Smalltalk, C++, Java). Maneesh Sahu is a software engineer in IBM, Bangalore. He has 2 years of experience in developing JavaBeans. He holds a degree in computer engineering from Karnataka Regional Engineering College (http://www.krec.ernet.in). His areas of expertise include developing visually wirable components, application development in VAJava and XML. He has written extensively on Developing Java and XML applications. Alain Dessureault is an IT Architect in IBM Canada. He has 7 years of experience in all phases of the software life cycle (analysis, requirements, architecture, design, construction, implementation and testing). He/she holds a degree in Computer Science from the Universite Laval. His/her areas of expertise include object-oriented tools processes and languages, distributed systems and client-server systems architecture, design and programming He has written extensively on Systems architecture and Distributed computing.
Acknowledgments
This book would not have been possible without the help of the following people who contributed to the content of the book: The editing team, and staff at the International Technical Support Organization, San Jose Center. Dave Ings, Howard Borenstein VisualAge for Java Development, IBM Toronto Lab, Toronto Graeme Dixon, Keith Uher WebSphere Advanced Edition 2.0 Development, IBM Transarc, Pittsburgh Elias Bayeh WebSphere Advanced Edition 2.0 Development, IBM Raleigh Lab, Raleigh Verlyn Johnson, San Francisco Marketing Support, IBM Rochester
xviii
5429pref.fm
David S. Linthicum, Chief Technology Officer, SAGA, http://www.sagus.com Chris Crenshaw, President, Nova Laboratories, http://www.nova-labs.com
Comments Welcome
Your comments are important to us! We want our redbooks to be as helpful as possible. Please send us your comments about this or other redbooks in one of the following ways:
u Fax the evaluation form found in ITSO Redbook Evaluation on page 403
xix
5429pref.fm
xx
Part 1
implement core business processes. The availability of object-oriented frameworks allows developers to rely on a base of existing business processes and business objects. SanFrancisco Application Business Components is the answer IBM gives to this requirement. It is a set of components that address commercial area such as General Ledger (GL),Account Payable/Account Receivable(AR/AP) Warehouse Management(WM), Order Management (OM). SanFrancisco has a strong technological infrastructure and has a layered architecture that shields developers from implementation details of function such as distributed computing and transaction management. The SanFrancisco architecture is made of three integrated layers:
Foundation Common Business Objects (CBOs) Core Business Processes(CBPs) The architecture is illustrated in figure 5
The Foundation layer is the core technological layer of SanFrancisco and provides the fundamental services such as distributed object creation,
synchronization, persistence, and a consistent application development model. It encapsulates the technological aspects of cross-platform distributed object management and provides an easy-to-use API. It also includes support for security, provides distributed transaction processing, and forms a middleware between a client application and server. The CBOs layer is built on top of the Foudation layer. It provides advanced components like Company,Address,BusinessPartner which are common across business domain. It provides generalized mechanisms to be used to solve business application problems Core Business Processes are the top layer of SanFrancisco. This layer provides the fundamental behavior and structure for particular domains. San Francisco provides the behaviors and structures needed to allow developers to customize the Core Business Processes for use in their applications. For example, SanFrancisco contains the General Ledger Core Business Process, which includes the architecture, design, and default logic to build a General Ledger application. The developer, instead of building it from scratch, needs only to enhance and extend this layer to build a customized General Ledger application. (For details you can refer to the following redbook SG242157-00 -San Francisco Concepts & Facilities ). Building application with SanFrancisco make the developer to be concentrated only on the business need without taking care of technological issue like distributing computing. Today the SanFrancisco Foundation overlaps the functions provided by EJB servers. It also provides a programming model which includes functions not yet addressed by EJB. On the other hand, EJB servers include some functions not provided by SanFrancisco. For example CORBA access is not delivered by SanFrancisco because SanFrancisco doesnt support IIOP access. You can integrate SanFrancisco business components with emerging technologies such as Websphere, but components built for one environment will not automatically run in the other. If you want to build a GL application which is CORBA compliant you may choose to build your own EJB components but it has to be clear that in this case you have to write 100% of your business code. You can not use the SanFrancisco business components as the starting point for a CORBA compliant application IBM has announced it plans to migrate the SanFrancisco business components to run on the Websphere family of servers. The SanFrancisco programming model will be migrated to the EBJ model. This will provide CORBA access to SanFrancisco components. The Websphere family of EJB
servers will be enhanced to provide the functions needed by the new version of the SanFrancisco components. With this new version you will be able to decide if you application is going to run in a EJB server or in a SanFrancisco server as depicted by Figure 2
Microsoft DCOM
The Distributed Component Object Model (DCOM) is Microsofts solution to distributed object architectures. It uses Object Remote Procedure Calls (ORPCs) to carry messages between components. Key features engineered into the DCOM architecture include language independence, transport
neutrality, and static and dynamic object method invocation. Because DCOM supports Windows platforms, DCOM-based applications can take full advantage of existing Microsoft services such as security and transactions. Some vendors are migrating DCOM to other platforms such as UNIX, and DCOM eventually will become truly cross-platform. One thing is clear, Enterprise JavaBeans have no place in this environment.
CORBA
In the recent years, several companies have put on the market products supporting the CORBA standard. There is no doubt that CORBA offers the most mature environment for distributed objects. Even though not a single vendor provides the entire set of object services, they still offer the largest set of services necessary to run such distributed object oriented applications. In addition, with a product like Component Broker, developers dont need to know how to program persistence, security, or transactional integrity, because the appropriate code is generated for them. IT organizations can, therefore, develop their business logic, then select the qualities of service necessary for the deployment of the business application. This idea of separating deployment concerns from actual business logic is built in Component Broker from the very beginning. However, the contract between Component Brokers business objects and the containers in which they are executed has not been standardized. Such a contract between business objects and their containers has been standardized in the form of the Enterprise JavaBeans specification. This specification opens a new world of opportunities for tool builders, ranging from those who build high-end enterprise-class tools to IDE tools vendors who simplify the creation, assembly and reuse of components during development and deployment.
1.5 Summary
The Enterprise JavaBeans specification help significantly in the separation of business logic from the middleware intricacies of dealing with major services like persistence, transaction, naming and security. If it is not yet the technology you can start using in any situation, this may change very quickly. As we have seen major commercial frameworks, CORBA
and high transaction volume environments have in their plan to support soon Enterprise JavaBeans. Developing business logic in the form of Enterprise JavaBeans may give a complete platform independence and for the first time a unique capability to move from workstation to more reliable, secure and scalable mainframe environments by the magic of a re-deployment. Before we start looking on how to develop Enterprise JavaBeans with VisualAge for Java, we propose to refresh your mind with a quick description of the major components and roles found in the Enterprise JavaBeans specification.
10
11
However, CORBA clients written in C++, as ActiveX, or in Java can be EJB clients as well. By using CORBA services, a CORBA client can have full access to EJBs.
2.1 Roles
The separation of the business logic from other tasks requires the definition of different roles.
Provider
The Enterprise JavaBeans provider is the developer who understands the business logic and knows how to translate it into Java code. The Enterprise JavaBeans provider needs to have an understanding of the interfaces and semantics of Enterprise JavaBeans. The Enterprise JavaBeans provider is responsible for deciding, among other issues, whether the enterprise Bean is persistent or not. If the enterprise Bean is persistent, the enterprise Beans provider must provide a list of fields with persistent state. The enterprise Bean provider also must decide whether he or she is going to manage the persistency, using such support as files, databases, or CICS transactions, or let the container manage the persistency. Another decision the enterprise Beans provider must make concerns the behavior of the enterprise Bean when it is involved in the scope of a transaction.The Enterprise JavaBeans providers responsibility ends with the packaging of the EJB and all associated files as a jar file, which is then given to the deployer.
Deployer
The deployer is responsible for installing the EJB classes in the EJB server. The deployer understands EJB and the runtime server environment and can map EJB developer requirements and configure them using EJB server tools. The deployer also must ensure that EJBs are accessible through JNDI.
Application Assembler
The application assembler writes applications that use EJBs. He or she has a client view of the EJB and can create new, composed EJBs and develop applets, servlets, or native CORBA applications that use EJBs.
12
Container Provider
The container provider focuses mainly on providing scalability, security, and transactional behavior for EJBs. The accompanying tools generate the "glue" code that creates the link between the business logic and the underlying services. The container intercepts client calls to the EJB and executes the appropriate services that ensure the transactional, persistent behavior expected for the EJB.
Server Provider
The server provider brings operating system and middleware services to the container. In most cases, the same vendor provides the server and container because there are as yet no specifications to define the interface between a container and a server.
System Administrator
The system administrator ensures that the system is working properly by using the monitoring and management tools provided by the server and container providers.
2.2 Components
In this section we present an overview of the major Enterprise JavaBeans components.
Container
A container is where an EJB lives. It can contain one or more EJB classes. These classes are identified by their home interface, which acts like a factory that allows clients to create, find, and remove instances of an EJB. By using the Deployment Descriptor during EJB development, or later on by using deployment tools, it is possible to give a meaningful name to the home interface. The container places this name in the naming space that is accessible from clients using JNDI.
13
Session Beans
The life time of a session bean is typically that of its client. A session bean contains conversational states that are not persistent and will not survive a server failure. However, a session bean must indicate to its container a state management mode: STATELESS STATEFUL In order for a container to manage efficiently a large number of bean instances, it can take an instance out of memory and store it in permanent storage. This is called passivation. When this bean is invoked again, the container creates a new instance and initializes it with the data saved during passivation. This is called activation. Therefore, if the session bean contains a conversational state that must be preserved between method invocations, the session bean indicates STATEFUL management mode. Otherwise the container considers the session bean STATELESS and never uses passivation but instead can destroy it in case of memory resource shortage. Because all instances of stateless session beans are the same, the container can decide to use any available instance to satisfy a client request.
Entity Beans
Entity beans are used to represent persistent data. In the most common case, their fields are mapped into a relational database. But in more complex situations, the persistent data can result from the invocation of an application or the execution of an existing CICS transaction. The persistent state of an entity bean is defined in two flavors: 1. Bean-managed persistence (BMP) With a BMP entity bean, the EJB provider manages the persistent state of the bean by coding database calls or any type of access to permanent storage. It is the provider responsibility to save and restore the state of the EJB when called by the container on such methods as: ejbFind, ejbLoad, and ejbStore. A BMP entity bean is inappropriate for large applications. This becomes obvious when you think about a large number of entity beans, each accessing a given database. For portability and scalability use a Container-managed persistence entity bean.
14
2. Container-managed persistence (CMP) With Container-managed persistence entity beans you do not have to know which source is used to provide the persistent state of the bean. You just have to specify which fields are persistent. Thus there is complete portability, and the EJB provider can focus on the business logic. The hard part is for the container. Each container provider also provides the tools to map EJB fields to databases or any existing application. In addition, it can efficiently manage database access by using a shared pool of connections and caching data. Vendors will differentiate their offerings by the number of containers they provide to access different sources, and the reliability and scalability of their implementation. When Container-managed persistence is used, an Enterprise JavaBeans can be transparently moved from one container to another regardless of whether it is provided by the same vendor. The business logic remains untouched! Every Enterprise JavaBeans entity bean has a unique identity within its home. Its identity is defined by a primary key. The primary key can be any class type. The only restriction is that the class must implement serializable, because it must be possible to pass the primary key between the client and the server. The primary key is used by the client to create or find an instance of an EJB.
15
implement it as a BMP. But dont forget that mixing persistency state management with business logic is not good for portability. For each bean, you have to provide an implementation, additional classes, and interfaces. Assuming that your bean name is EmployeeID, you have to: 1. Develop an EmployeeIDBean class 2. Develop an EmployeeID interface 3. Develop an EmployeeIDHome interface 4. If it is an entity bean, provide an EmployeeIDKey 5. Create a deployment descriptor file 6. Create a manifest file 7. Package all of these files inside a deployment jar that the container deployment tool uses to install and execute the EJBs. The information set in the deployment descriptor contains the beanHomeName. This is the JNDI name you give to the EmployeeIDHome. It can be any name that makes sense in your organization, such as applications/travelExpenses. At deployment time, the deployer can still change it. When the container instantiates the EJB home, it registers in the naming space this name bound to EmployeeIDHome (see Figure 3 on page 17). Later on, an EJB client uses the JNDI API to look up the home and then continues by creating, finding, or removing instances of the object managed by its home.
16
One of the major benefits of EJB comes from the separation of the business logic from the middleware supporting it. The specification also defines the contract with the container provider who provides such services as transactions, persistency, and security and the tools to generate the glue code that realizes the link between these services and the business logic. To make the EJB offering even more attractive, VisualAge for Java 2.1 comes with complete EJB development support, including WebSphere 2.0 runtime. You can now develop your EmployeeIDBean and let the tool generate every thing else including the container deployment classes. You can develop, debug, and test any type of EJBs: session beans, BMP entity beans, or CMP entity beans. VisualAge for Java also generates the jar file with all information required to deploy it in containers such as WebSphere, Component Broker, or any other vendor container. All these capabilities are detailed in this book.
17
18
This class encapsulates the data associated with the enterprise bean and contains the developer-implemented business methods that access this data. It also contains the methods used by the container to manage the life cycle of an enterprise bean instance. Clients (whether they are other
19
enterprise beans or user applications) never access objects of this class directly; instead, they use the container-generated classes associated with the home and remote interfaces to manipulate the enterprise bean.
u Home interface
This interface contains the methods used by the client to create and remove instances of the enterprise bean. This interface is implemented by the container during enterprise bean deployment in a class known generically as the EJB home class.
u Remote interface
Once the client has used the home interface to gain access to an enterprise bean, it uses this interface to invoke the business methods defined in the bean class. This interface is implemented by the container during enterprise bean deployment in a class known generically as the EJB object class. Unlike an entity bean, a session bean does not have a primary key class. A session bean does not require a primary key class because instances of session beans cannot be uniquely identified from each other.
referred to as a stateful session bean. When a session bean maintains data across methods, it is said to have a conversational state. A Web-based shopping cart applet is a classic example of a stateful session bean. As the shopping cart user adds (and subtracts) items to the shopping cart, the underlying enterprise bean must maintain a record of the content of the cart. Once a particular client begins using an instance of a stateful session bean, the client must continue to use that instance as long as the specific state of that instance is required. If the bean is lost before the contents of the shopping cart is committed to an order, the shopper must load up a new shopping cart.
20
u If a session bean does not need to maintain specific data across methods,
it is referred to as a stateless session bean. The example Transfer enterprise bean developed in The TransferBean class on page 25 provides an example of a stateless session bean. For stateless session beans, a client can use any instance to invoke any of the session beans methods.
Creation state
A session beans life cycle begins when a client invokes a create method defined in the beans home interface. In response to this method invocation, the container does the following: 1. Creates a new memory object for the session bean instance. 2. Invokes the session beans setSessionContext method. (This method passes the session bean instance a reference to a session context interface that can be used by the instance to obtain container services and get information about the caller of a client-invoked method.) 3. Invokes the session beans ejbCreate method corresponding to the create method called by the client.
Ready state
Once a session bean instance is created, it moves to the ready state of its life cycle. In this state, clients can invoke the beans business methods defined in the remote interface. The actions of the container at this state are determined by whether a method is invoked transactionally or nontransactionally:
u Transactional method invocations
When a client invokes a transactional business method, the session bean instance is associated with a transaction. Once a bean instance is associated with a transaction, it remains associated until that transaction completes. (Furthermore, an error results if a client attempts to invoke another method on the same bean instance if invoking that method causes the container to associate the bean instance with another transaction or with no transaction.) The container then invokes the following methods: 1. The afterBegin method, if that method is implemented by the bean class.
21
2. The business method in the bean class that corresponds to the business method defined in the beans remote interface and called by the client. 3. The bean instances beforeCompletion method, if that method is implemented by the bean class and if a commit is requested prior to the containers attempt to commit the transaction. The transaction service then attempts to commit the transaction, resulting either in a commit or a rollback. When the transaction completes, the container invokes the beans afterCompletion method, passing the completion status of the transaction (either commit or rollback). If a rollback occurs, a stateful session bean can roll back its conversational state to the values contained in the bean instance prior to beginning the transaction. Stateless session beans do not maintain conversational state, so they do not need to be concerned about rollbacks.
u Nontransactional method invocations
When a client invokes a nontransactional business method, the container simply invokes the corresponding method in the bean class.
Pooled state
The container has a sophisticated algorithm for managing which enterprise bean instances are retained in memory. When a container determines that a session bean instance is no longer required in memory, it invokes the bean instances ejbPassivate method and moves the bean instance into a reserve pool. When this method returns, the container saves the instances state to a data source. A session bean instance cannot be passivated when it is associated with a transaction. If a client invokes a method on a passivated session bean instance, the container activates the instance by restoring the instances state from the data source and then invoking the bean instances ejbActivate method. When this method returns, the bean instance is again in the ready state. Because every stateless session bean instance of a particular type is the same as every other instance of that type, stateless session bean instances are not passivated or activated. These instances exist in a ready state at all times until their removal.
Removal state
A session beans life cycle ends when a client or the container invokes a remove method defined in the beans home interface and remote interface. In response to this method invocation, the container calls the bean instances ejbRemove method.
22
If you attempt to remove a bean instance while it is associated with a transaction, the javax.ejb.RemoveException is thrown. Once a bean instance is removed, any attempt to invoke a method on that instance causes the java.rmi.NoSuchObjectException to be thrown. A container can implicitly call a remove method on an instance after the lifetime of the EJB object has expired. The lifetime of a session EJB object is set in the deployment descriptor with the timeout attribute.
23
By convention, the enterprise bean class is named NameBean, where Name is the name you assign to the enterprise bean. The enterprise bean class for the example Transfer enterprise bean is named TransferBean. Every session bean class must meet the following requirements:
u It must be public, it must not be abstract, and it must implement the
javax.ejb.SessionBean interface. For more information, Implementing the SessionBean interface on page 29.
see
u It must define and implement the business methods that execute the
tasks associated with the enterprise bean. For more information, see Implementing the business methods on page 25.
u It must define and implement an ejbCreate method for each way in which
you want it to be able to instantiate the enterprise bean class. For more information, see Implementing the ejbCreate methods on page 27. Stateful session beans may need to synchronize their conversational state with the transactional context in which they operate. For example, a stateful session bean may need to reset the value of some of its variables if a transaction is rolled back or it may need to change these variables if a transaction successfully completes. If a bean needs to synchronize its conversational state with the transactional context, the bean class must implement the javax.ejb.SessionSynchronization interface. This interface contains methods to notify the session bean when a transaction begins, when it is about to complete, and when it has completed. The enterprise bean developer can use these methods to synchronize the state of the session enterprise bean instance with ongoing transactions. Note: The enterprise bean class can implement the enterprise beans remote interface, but this is not recommended. If the enterprise bean class implements the remote interface, it is possible to inadvertently pass the this variable as a method argument. Figure 4 shows main parts of the enterprise bean class for the example Transfer bean. The sections that follow discuss these parts in greater detail. A session bean can be either stateful or stateless. In a stateless session bean, none of the methods depend on the values of variables set by any other method, except for the ejbCreate method that sets the initial (identical) state of each bean instance. In a stateful enterprise bean, one or more methods depend on the values of variables set by some other method. The Transfer bean is stateless. If the Transfer beans transferFunds method was dependent on the value of the balance variable returned by the getBalance method, the TransferBean would be stateful.
24
import java.rmi.RemoteException; import java.util.Properties; import javax.ejb.*; import java.lang.*; import javax.naming.*; import com.ibm.ejs.doc.account.*; public class TransferBean implements SessionBean { private SessionContext mySessionCtx = null; private InitialContext initialContext = null; private AccountHome accountHome = null; private Account fromAccount = null; private Account toAccount = null; ... public void ejbActivate() throws RemoteException { } ... public void ejbCreate() throws RemoteException { ... } ... public void ejbPassivate() throws RemoteException { } ... public void ejbRemove() throws RemoteException { } ... public float getBalance(long acctId) throws FinderException, RemoteException { ... } ... public void setSessionContext(javax.ejb.SessionContext ctx) throws java.rmi.RemoteException { ... } ... public void transferFunds(long fromAcctId, long toAcctId, float amount) throws java.rmi.RemoteException { ... } } Figure 4. The TransferBean class
25
The business methods implemented in the enterprise bean class cannot be directly invoked by a client. Instead, the client invokes the corresponding methods defined in the enterprise beans remote interface, by using an EJB object associated with an instance of the enterprise bean, and the container invokes the corresponding methods in the enterprise bean instance. Therefore, for every business method implemented in the enterprise bean class, a corresponding method must be defined in the enterprise beans remote interface. The enterprise beans remote interface is implemented by the container in the EJB object class when the enterprise bean is deployed. Figure 5 shows the business methods for the TransferBean class. The getBalance method is used to get the balance for an account. It first locates the appropriate Account EJB object and then calls that objects getBalance method. The transferFunds method is used to transfer a specified amount between two accounts (encapsulated in two Account entity EJB objects). After locating the appropriate Account EJB objects by using the findByPrimaryKey method, the transferFunds method calls the add method on one account and the subtract method on the other. Like all finder methods, findByPrimaryKey can throw both the FinderException and RemoteException exceptions. The try/catch blocks are set up around invocations of the findByPrimaryKey method to handle the entry of invalid account IDs by users. If the session bean user enters an invalid account ID, the findByPrimaryKey method cannot locate an EJB object, and the finder method throws the FinderException exception. This exception is caught and converted into a new RemoteException exception containing information on the invalid account ID. Obtaining the EJB home object is discussed in Implementing the ejbCreate methods on page 27.
26
public class TransferBean implements SessionBean { ... private Account fromAccount = null; private Account toAccount = null; ... public float getBalance(long acctId) throws FinderException, RemoteException { AccountKey key = new AccountKey(acctId); try{ fromAccount = accountHome.findByPrimaryKey(key); } catch(FinderException ex) { throw new FinderException("Account " + acctId + " does not exist."); } return fromAccount.getBalance(); } ... public void transferFunds(long fromAcctId, long toAcctId, float amount) throws RemoteException, InsufficientFundsException, FinderException { AccountKey fromKey = new AccountKey(fromAcctId); AccountKey toKey = new AccountKey(toAcctId); try { fromAccount = accountHome.findByPrimaryKey(fromKey); } catch(FinderException ex) { throw new FinderException("Account " + fromAcctId + " does not exist."); } try { toAccount = accountHome.findByPrimaryKey(toKey); } catch(FinderException ex) { throw new FinderException("Account " + toAcctId + " does not exist."); } try { toAccount.add(amount); fromAccount.subtract(amount); } catch(InsufficientFundsException ex) { throw new InsufficientFundsException("Insufficient funds in " + fromAcctId); } } } Figure 5. The business methods of the TransferBean class
27
no arguments; a stateful session bean can have multiple ejbCreate methods. Each ejbCreate method must correspond to a create method in the enterprise beans home interface. (Note that there is no ejbPostCreate method in a session bean as there is in an entity bean.) Like the business methods of the enterprise bean class, the ejbCreate methods cannot be invoked directly by the client. Instead, the client invokes the create method in the bean instances home interface, and the container invokes the ejbCreate method. If an ejbCreate method is executed successfully, an EJB object is created. Each ejbCreate method must meet the following requirements:
u It must return void. u It must contain code to set the values of any variables needed by the EJB
object. Figure 6 shows the ejbCreate method required by the TransferBean class. When a container invokes this method, the static method getInitialContext is called to set the enterprise beans initialContext variable. Next, a JNDI lookup is performed by calling the initialContext objects lookup method and passing the name of the Account enterprise bean in string form. The lookup yields a temporary object of type java.lang.Object, which is passed to the static method narrow contained in the Account enterprise beans AccountHomeHelper class to get the AccountHome EJB object. (The AccountHomeHelper class is one of the helper classes generated when the Account enterprise bean is deployed.)
28
public class TransferBean implements SessionBean { private javax.ejb.SessionContext mySessionCtx = null; private InitialContext initialContext = null; private AccountHome accountHome = null; ... public void ejbCreate() throws RemoteException { // Get the initial context try { Properties properties = new Properties(); ... properties.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.ibm.jndi.CosNaming.CNInitialContextFactory"); initialContext = new InitialContext(properties); } catch(Exception ex) { ... } ... // Lookup the home interface using the JNDI name try { java.lang.Object o = initialContext.lookup("Account); // this is the JNDI name if (o instanceof org.ong.CORBA.Object) { accountHome = AccountHomeHelper.narrow((org.omg.CORBA.Object) o); } else { // Unexpected object type ... } } catch (Exception e) { // Error getting the home interface ... } } ... }
29
u ejbActivate
This method is invoked by the container when the container selects an enterprise bean instance from the instance pool and assigns it a specific existing EJB object. This method must contain any code that you want to execute when the enterprise bean instance is activated.
u ejbPassivate
This method is invoked by the container when the container disassociates an enterprise bean instance from its EJB object and places the enterprise bean instance in the instance pool. This method must contain any code that you want to execute when the enterprise bean instance is passivated (deactivated).
u ejbRemove
This method is invoked by the container when a client invokes the remove method inherited by the enterprise beans home interface (from the javax.ejb.EJBHome interface). This method must contain any code that you want to execute when an enterprise bean instance is removed from the container.
u setSessionContext
This method is invoked by the container to pass a reference to the javax.ejb.SessionContext interface to a session bean instance. If an enterprise bean instance needs to use this context at any time during its life cycle, the enterprise bean class must contain an instance variable to store this value. This method must contain any code required to store a reference to the context. As shown in Figure 7, except for the setSessionContext method, all of these methods in the TransferBean class are empty because no additional action is required by the bean for the particular life cycle states associated with the these methods. The setSessionContext method is used in a conventional way to set the value of the mySessionCtx.
30
public class TransferBean implements SessionBean { private SessionContext mySessionCtx = null; ... public void ejbActivate() throws RemoteException { } ... public void ejbPassivate() throws RemoteException { } ... public void ejbRemove() throws RemoteException { } ... public void setSessionContext(.SessionContext ctx) throws RemoteException { mySessionCtx = ctx; } ... } Figure 7. Implementing the SessionBean interface in the TransferBean class
to a ejbCreate method in the enterprise bean class. Unlike entity beans, the home interface of a session bean contains no finder methods.
u The parameters and return value of each method defined in the interface
must be valid for Java RMI. In addition, each methods throws clause must include the java.rmi.RemoteException exception class.
31
Figure 8 shows the relevant parts of the definition of the home interface (TransferHome) for the example Transfer bean. This interface defines one create method.
import javax.ejb.*; import java.rmi.*; public interface TransferHome extends EJBHome{ Transfer create() throws CreateException, RemoteException; }
A create method is used by a client to create an enterprise bean instance. A stateful session bean can contain multiple create methods; however, a stateless session bean can contain only one create method with no arguments. This restriction on stateless session beans ensures that every stateless session bean instances is the same as every other instance of the same type. (For example, every Transfer bean instance is the same as every other Transfer bean instance.) Each create method must be named create and it must have the same number and types of arguments as a corresponding ejbCreate method in the EJB object class. The return types of the create method and its corresponding ejbCreate method are always different. Each create method must meet the following requirements:
u It must return the type of the enterprise beans remote interface. For
example, the return type for the create method in the TransferHome interface is Transfer.
u It must have a throws clause that includes the java.rmi.RemoteException
exception, the javax.ejb.CreateException exception class, and all of the exceptions defined in the throws clause of the corresponding ejbCreate method.
32
and implemented in the EJB object class created by the container during enterprise bean deployment. By convention, the remote interface is named Name, where Name is the name you assign to the enterprise bean. For example, the Transfer enterprise beans remote interface is named Transfer. Every remote interface must meet the following requirements:
u It must extend the javax.ejb.EJBObject interface. The remote interface
exception class. Figure 9 shows the relevant parts of the definition of the remote interface (Transfer) for the example Transfer bean. This interface defines the methods for transferring funds between two Account bean instances and for getting the balance of an Account bean instance.
import javax.ejb.*; import java.rmi.*; import com.ibm.ejs.doc.account.*; public interface Transfer extends EJBObject { ... float getBalance(long acctId) throws FinderException, RemoteException; ... void transferFunds(long fromAcctId, long toAcctId, float amount) throws InsufficientFundsException, RemoteException;} Figure 9. The Transfer remote interface
By stepping through the different tasks required to develop an Enterprise JavaBeans, you have probably realized that a lot of code can be generated for you. VisualAge for Java does it for you and a lot more. This is what we are going to describe in the rest of this book.
33
Creating EJBs
The EJB Development Environment provides tools to help you create EJBs that can be deployed in a WebSphere EJS or in EJB containers provided by other vendors. These tools allow you to accomplish core development activities in the EJBs page,such as creating EJB groups and EJBs. They also allow you to accomplish other development activities, such as writing and editing business logic, importing or exporting EJBs, and managing EJBs. A tool is also provided to help you map entity EJBs to back-end data stores, such as relational databases. There are also tools to help you set deployment descriptor and control descriptor properties prior to running the tools used to generate the deployed code.
34
In this chapter we create a stateless session bean called ReadCustomerInfo. It has the responsibility to read data from a serialized file and give as output a CustomerObject initialized with the data contained in the .ser file. The "customer.ser" file must exist in your environment and in order to have flexibility to change its location we set it using the environment property in the deployment descriptor as explained in Generate deployment code inside VisualAge for Java on page 64. The "customer.ser" file is already provided in the CdRom\Part1Samples\SessionBean directory of the CDROM provided with this book.
35
An EJB group is a logical group that allows you to organize your EJBs. You can perform global operations on an EJB group that iterate on all of the EJBs that reside in the group. For example, if you select an EJB group to export to an EJB jar file, all of the EJBs contained in the group are exported. Generally when you work with EJBs you need to perform the following three main actions: 1. In the Workbench Projects page create a project 2. In the EJB page create an EJB group. When doing this you are asked to specify the package name. If it does not exist it is created for you and put in the project specified in step 1 3. Create EJBs inside the group specified in step 2. There are two ways to add an EJB group to the EJBs page: Create a new EJB group. Retrieve one or more existing EJB groups from the repository. To add EJB groups: 1. In the Workbench Projects page, from the menu, select Selected->Add Project. The Add Project SmartGuide appears. 2. In the Create a new project named field, type ITSO Bank. This is the name assigned to the new project that will contain your EJBs, then click Finish. The new project appears in the projects page. When creating projects, we suggest that you create a project to hold the EJBs and their related classes, and another project to hold the client application code that will access the EJBs. This helps to keep your code organized. We havent done this for our small session bean sample because there are really few classes to manage. 3. In the Workbench Projects page, click on the EJBs tab. The EJBs page appears.
36
4. From the EJBs menu select Add-EJB Group. The Add EJB Group SmartGuide appears. 5. Beside the Project field, click the Browse button and look for the ITSO Bank the project that we want to contain the EJB group, then click OK. 6. You can do one of the following: Add an EJB group by creating a new group. Add one or more EJB groups by retrieving existing EJB groups from the repository. For our sample purpose we now create a new group. To add an EJB group by creating a new group, ensure that the Create a new EJB group named radio button is selected, and type ITSOEJBGroup which is the name we want to assign to the new group. Your window should now appear like Figure 12
37
38
Figure 13. EJB Page After the Creation of the New Group
This topic discusses how to add EJBs by creating new EJBs. Information about retrieving existing EJBs from the repository and adding EJBs by importing them from a jar file is found in the Appendix A.1, Importing EJBs from a Jar File on page 345. To add EJBs:
39
1. In the EJBs pane, select an EJB group to contain your EJB and click mouse button 2. 2. From the pop-up menu, select Add-EJB. The Create EJB SmartGuide appears.
Using the Create EJB SmartGuide, you can add an EJB by either creating a new EJB or by retrieving one or more existing EJBs from the Repository. Lets see how to add an EJB by creating a new EJB: 1. Ensure that the Create a new EJB radio button is selected.
40
2. In the Bean name field, type in ReadCustomerInfo which is the name that you want to assign to the your new EJB. 3. Since you are creating a new EJB bean class, you need to specify the type of EJB you want to create: session bean, entity bean with bean-managed persistence fields (BMP), or entity bean with container-managed persistence (CMP) fields. The ReadCustomerInfo is a Session Bean so from Bean type drop-down list choose Session Bean. 4. In the Project field, type the project name, modify the default name, or click the Browse button and select the project that contains (or will contain) the EJB bean class from the list of projects, then click OK. By default, the project to which the EJB group belongs is displayed. In our case the project is ITSO Bank. 5. In the Package field, type the project name, modify the default name, or click the Browse button and select the package that contains (or will contain) the EJB bean class, then click OK. If you enter a package that does not exist, a new package is created. type itso.samples.ejb.sessionbean in the package field. 6. In the Class field, either accept the default value or type in a name for the new class. We recommend that you use the default value so that all the implementation types of the EJB are named properly 7. Since we do not provide any superclass for our ReadCustomerInfo bean we do not fill the Superclass field. Before clicking the Next button your EJB Create SmartGuide should look like in Figure 15.
41
8. After clicking on Next, you are presented with the Define EJB Class Attributes and Interfaces panel (see Figure 16).
42
9. A default EJB Home Interface and EJB Remote Interface names are automatically generated. You can change them or keep the default values. The EJB Key Class is not accessible because session bean do not need a key.
43
10.In the Add import statements to the Bean class, click on Add Package button. 11. This opens a new window where you can select packages and add them by clicking Add button. 12.Repeat the previous step for each package. Once all packages have been added, you can close the window by clicking on Close. The list of added packages appears now in the Add import statements to the Bean class. 13.You can follow the same process to add Interfaces that your bean implements. You dont need to add javax.ejb.Session. The generated code automatically implements this interface because the tool knows we are creating a session bean. 14.Click on Finish at this point. You do not need to go the next page in the SmartGuide because we use the default names the EJB home interface, remote interface. Now you EJB workspace page should look like this:
44
Figure 17. EJB Workspace after the Creation of the New EJB
As you can see in Figure 17 if you select the ITSOEJBGroup the Types pane is populated with three classes: ReadCustomerInfo(remote interface of the ReadCustomerInfo EJB) ReadCustomerInfoBean(bean class of the ReadCustomerInfo EJB) ReadCutomerInfoHome(home interface of the ReadCustomerInfo EJB) If you go back to Developing Session Beans on page 23 you can see what is needed in order to create and EJB and how much easier is to create it using VisualAge for Java. In fact VisualAge for Java automatically generates the three classes required for creating an EJB following the specification rules. You can have a look of what is generated inside each of this class by simply selecting it in the Types pane and look the displayed methods in the Methods pane. As you can see the remote interface is empty. It is up to you to decide
45
which are the method you need to put in the Remote interface ReadCustomerInfo. The Home interface instead shows the create() method that our session bean at least must have. Remember since the ReadCustomer session bean is a stateless session bean we do not implement any additional create() method. You can add new methods to your bean class and make them appear in the Home or Remote interface. In order to do this you never manipulate the source code of these two interfaces directly. Detailed explanation on how to do this is found in Adding methods to EJBs on page 49 The ReadCustomerInfo is a simple stateless session bean that access a serialized file in order to read simple customer information. For this reason you need to do some additional steps before you can start developing your session bean. In CdRom\Part1Samples\SessionBean directory of the CDROM we provide the following CustomerObject.jar file. It contains a CustomerObject serialized JavaBeans to be used by the CustomerInfo sessionbean. Import it into your ITSO Bank project. An itso.samples.ejb.sessionbean.model package should now show up in the ITSO Bank project. Now we can proceed building our ReadCustomerInfo session bean. Go back to the EJB workspace. We need to create new fields to the ReadCustomerInfo session bean. Since this is a stateless Session Bean the field are private attribute for the bean.
You can display EJB fields by selecting the EJB in the EJBs pane, and then selecting the Fields icon in the upper right corner of the Types pane to toggle to the Fields pane. The Fields pane and the Types pane share the same space on the EJBs page and can be displayed alternately by selecting the icon in the upper right corner of the pane. To display the Types pane, select the Types icon .
46
The reason why we declared all the fields as private is because our session bean is stateless. If you want to make it a stateful session bean you have to declare all the fields as public so that the container takes care of their state during passivation. To add a field to the bean class: 1. In the Types pane of the EJBs page, select the EJB bean class to which you want to add a field. 2. Click mouse button 2, then select Add Field from the pop-up menu. The Create Field smartguide appears.
3. In Field Name, enter fileName 4. Select String in the Field Type combo box.
47
5. Type null in the Initial Value field. 6. Select private as Access Modifier. Our bean is stateless this is why we declare private fields. If the bean had been declared Stateful, then we should have declared the fields as public. 7. Check the Access with getter and setter methods checkbox so getters an setters methods are generated by the tool for you. This is how the smart guide should look like now:
8. Click Finish.
48
Since we all make mistakes, we may have created a field that we really dont need. The question is how do we delete fields?
49
3. Select Create a new method radio button. 4. Type CustomerObject readCustomer() as shown in Figure 21.
50
5. Click Next to go to the next page. 6. Select public as the Access Modifiers and since the readCustomer method can throw an IOException you need to add this exception in the What exception may this method throws? list. In order to do this click the Add button and type the exception name. When you are finished click Close (see Figure 22). You need to go on the second page only if you want to change the modifiers attribute or if you want the SmartGuide to handle additional
51
exception. If you are not under this condition you can skip step 5 and step 6.
7. Click Finish to create the new method You now need to create the other two methods following the same steps. The two methods have the following signature:
public void openFile(); public void closeFile() throws java.io.IOException;
52
Now we need to fill the methods with the right code and understand what do we do with this new business methods. Here is the code to be inserted in each method:
private void closeFile() throws java.io.IOException{ if(input!=null){ input.close(); input=null; } } private void openFile() { try { //Need to initialize the fileName field from what is defined in //the environment fileName=(String)props.get("customerFile"); fInput= new FileInputStream( fileName); input = new ObjectInputStream( fInput); } catch(Exception e){ System.out.println("Error in opening: " + e); } } public CustomerObject readCustomer() throws java.io.IOException{ try{ openFile(); if (fInput.available() > 0){ System.out.println("INIT ---> Reading object"); CustomerObject cO=(CustomerObject)input.readObject(); System.out.println("END ---> Reading object"); closeFile(); return cO; } } catch(Exception e) { e.printStackTrace(System.out); } return null; }
After you create methods, you need to promote to the remote interface those that will be accessed by a client. In our case, only the readCustomerInfo method needs to appear on the remote interface.
53
54
You have now completed the development steps for the ReadCustomerInfoBean. Let us see how to deploy it and test it inside VisualAge for Java.
55
For example, during analysis you may decide that a bean is going to use a file name that must not be hardcoded. Then, during development phase, the developer decides that the file name is going to be passed to the bean by using a property name. At last, during deployment, the deployer can change the value of the property name with a new value pointing to a different fully qualified path and file name (see Figure 61 on page 104). Every enterprise Bean (both session and entity) must have a deployment descriptor that contains settings for the following attributes; these attributes can be set for the entire enterprise Bean or for the individual methods in the Bean. The container uses the definition of the Bean-level attribute unless a method-level attribute is defined, in which case the latter is used.
u Transaction attribute:Defines the transactional manner in which the
container invokes a method. The values for this attribute are described Chapter 7, Transactions on page 211
u Transaction
isolation level attribute:Defines the degree to which transactions are isolated from each other by the container. users or roles that are permitted to access the methods in the enterprise Bean. The values for this attribute are defined by enterprise Bean deployers and the system administrator.
defines the identity used to invoke the method. If a specific identity is required, the RunAsIdentity attribute is used to specify that identity. The deployment descriptor for a session Bean must also contain settings for the following attributes. These attributes can be set on the Bean only; they cannot be set on a per-method level.
u State management attribute:defines the conversational state of the
56
Timeout attributeDefines the timeout value in seconds associated with this session Bean. This is a value needed for the container. Idle instances of a session Bean are removed by the container after this specified time period has elapsed. Deployment descriptors can be created by using the tools within an integrated development environment (IDE) like IBMs VisualAge for Java or by using the stand-alone tools contained in WebSphere. You provide this information to VisualAge for Java by using a smartguide and later, the tool generates the serialized deployment descriptor for you as well as all the required files that go into the deployable jar file. To launch this smartguide, from the EJB Workspace : 1. Go to the EJBs pane. 2. Select ITSOEJBGroup. 3. Select ReadCustomerInfo bean class. 4. Click mouse button 2, then select Properties. The Properties window appear:
57
In the first page that appear you recognize all values described in the The deployment descriptor on page 56 section. We keep the default values on this first page. If you need to change the Java Naming and Directory Interface ( JNDI) name or control attributes at the bean level, do one or more of the following:
u In the Enter the JNDI name for BeanHome field, type the JNDI
name to associate with the EJB in the JNDI name space. The container will bind the EJB's home interface with a JNDI name that includes the name you specified. The name you specify in this field is the name that your client code pass to the naming context.
u In the Transaction Attribute drop-down box, select a transaction
attribute. This attribute tells the container how to manage transaction scopes before and after the execution of the EJB method.
u In the Isolation Level drop-down box, select an isolation level. This
level tells the container what isolation level to set on the database connections used by the EJB at the start of each transaction.
58
u In the Run-As Mode drop-down box, select a run-as mode. This selection
tells the container the security identity to associate with the execution of the EJB method.
u For session EJBs only, in the State Management Attribute drop-down
box, specify whether or not you want the container to maintain state information for the EJB.
u For session EJBs only, in the Session Timeout Value (seconds) field,
specify after how many seconds a session should timeout. During runtime, our bean needs to know where to get a file called customer.ser which contains a serialized instance of a Customer object. We pass this information through the environment properties. Click the Environment tab. The Environment tab page appears.
Variables field and its associated value in the Values field, and click Set.
59
and click Delete. In order to add the property we need, to do the following: 1. In the Variables field type customerFile 2. In the Values field type c:\customer.ser. It indicates where the "customer.ser" is located. We assume the file is located under the root directory. If you copy it somewhere else, ensure that the property is updated. The properties window should now appears like in Figure 26.
60
If you want to use Environment properties you need to define a Properties field in the bean class (see Figure 27).
This Properties field is initialized in the setSessionContext() method as shown in Figure 28.
Now you need to initialize the fileName variable reading the information from the properties. We do it in openFile() (see Figure 29).
We do not need to to change the control attributes at the method level but if you need to do this click the Method tab. The Method page appears:
61
To add a method-level control descriptor, click Add. The Add Control Descriptor at Method Level dialog appears:
62
If you select a method from the list and click OK, the following dialog appears:
The displayed attribute values are those defined at the bean level. Modification done in this window affect the selected method only.
63
can be used to contain individual enterprise Beans, multiple enterprise Beans, and entire enterprise Bean-based applications. For an individual enterprise Bean, an ejb-jar file must contain the following files:
u The .class files that make up the Bean u The deployment descriptor u The manifest file that identifies the contents of the jar file.
Manifest files are organized into sections that are separated by blank lines;each section corresponds to a file stored in the .jar file. Each section contains one or more tag-value pairs with the syntax tag:value. The section corresponding to the deployment descriptor file for each enterprise Bean in a .jar file must contain the following headers:
Name: deploymentDescriptorFile Enterprise-Bean: True
The manifest file must be named META-INF/MANIFEST.MF. An ejb-jar file can be created by using the tools within an integrated development environment (IDE) like IBMs VisualAge for Java or by using the stand-alone tools contained in WebSphere.
the enterprise Beans home and remote interfaces (and the persistor and finder classes for entity enterprise Beans with CMP).
u The Java ORB, stub, and skeleton files required for remote method
invocation (RMI).
u Helper and holder classes for the home and remote interfaces.
An enterprise Bean can be deployed by using the tools within an integrated development environment (IDE) like IBMs VisualAge for Java or by using the stand-alone tools contained in WebSphere. NOTE: If you add a remote method and promote it to the remote interface after generating the deployed code, you must regenerate the deployed code.
64
1. In the EJBs pane select ReadCustomerInfo bean class. 2. Click mouse button 2, then select Generate->Deployed Code item from the EJB menu. The Types pane is now populated with the generated classes.
Figure 33. EJB WorkSpace after the EJB Deployment Code Generation
65
The test client is generated for each Enterprise JavaBeans. Then you can use it to do unit test. The main purpose of the test client is to interactively test each of the methods in the home and remote interfaces. The test client features a graphical user interface that allows you to select a method from either the home or remote interface and then test the selected method. The test client is generated from the home and remote interfaces and the deployment descriptor of the EJB. For each method defined in the remote interface, a local proxy method is generated into the test client class. You can customize each method by editing the method directly. To generate the EJB test client do the following: 1. Go to the EJBs pane. 2. Select ITSOEJBGroup. 3. Select ReadCustomerInfo bean class. 4. Click mouse button 2, then select Generate-Test Client item from the EJB menu. A default EJB test client class appears in the Types pane of the EJBs page under the following name ReadCustomerInfoTestClient.
66
Note: to hide the test client and other generated classes in the Types pane, in the upper right corner of the Types pane, click the Show Generated Types toggle button.
Testing EJBs
To run and test the ReadCustomerInfo session bean you need to create an EJB server configuration in which you can test your EJB. Configuring a server configuration for your EJB consists in adding the EJB group that contains your EJBs to a server configuration. To create an EJB server configuration: 1. From the EJBs page, select ITSOEJBGroup.
67
2. Click mouse button 2, and then select Add to - Server Configuration from the pop-up menu. The EJB Server Configuration browser appears.
An EJB server entry is added in the Servers pane. The EJB server contains the ITSOEJBGroup. Once you create your EJB server configuration, you may need to set some properties. Even though, in our case, we use default values, let us have a look to the different settings that can be done.
68
3. Type in the port number for the ORB Listener Port. Note that the value for the ORB Listener Port must match the value for the LSD Port in the Persistent Name Server.
69
2. Click mouse button 2 and select Properties from the pop-up menu. The Persistent Name Server Properties dialog appears.
3. Modify the default values accordingly. The Initial Root value is a working directory where certain information is written about the persistent data. In the LSD Name field, the Location Service Daemon can run on another machine other than the supplied default of localhost. Note that the LSD Port number must match the ORB Listener Port of the Location Service Daemon.
70
3. If you are testing an entity EJB, in the Database URL field, ensure that the URL of a database is specified that is configured on your system. For example: jdbc:db2:MyDatabase 4. If your database is set up so that a user ID and password is required to access the database, then specify a user ID and password in the Database User ID and Database Password fields. 5. If you changed the default port values, ensure that the LSD Port number matches the ORB Listener Port of the Location Service Daemon. Since we are dealing with session bean we do not need to take care about persistence aspects.
71
2. In the Servers pane, select the Location Service Daemon and click mouse button 2, then select Start Server. 3. In the Servers pane, select the Persistent Name Server and click mouse button 2, then select Start Server. You can also, select a server and from the tool bar, click on . In the same way, you can stop a server by clicking on the icon . The Console window appears in the background and monitors the two servers. 4. In the Console, check that the Location Service Daemon and the Persistent Name Server are listening by selecting each server (one at a time) in the All Programs pane and looking for the following messages in the Standard Out pane:
Location service daemon listening... NameServer is listening...
To start the EJB server: 1. Once the Location Service Daemon and the Persistent Name Server are running, in the Servers pane of the EJB Server Configuration browser, select the EJB server (server1) and click the icon to start the server. The Console window now also monitors the EJB servers.
72
2. In the Console, check that the EJB server is ready to process a call from the client by selecting the EJB server entry at the bottom of the All Programs pane and then looking for the following message in the Standard Out pane:
Server is listening...
3. You can change the source code of any EJB in the EJB server configuration and debug it without stopping the EJB server. However, if you change the home or remote interfaces, you must do the following: 1. Stop the EJB server. (Information about stopping the EJB Server is found in the topic Stopping the Name Service and EJB Servers on page 85.) 2. Regenerate the deployed code. 3. Start the EJB server again. Note: If you create an EJB server configuration that contains a number of EJBs and then you decide that you want to delete one of the EJBs, you should stop the EJB server before deleting the EJB.
Restarting Servers
In some situations, you may want to perform a restart on a server that is already running. Essentially, this resets the running server to the state it was in when it was first started. To restart a server: 1. In the EJBs page, select EJBs - Open To - Server Configuration. The EJB Server Configuration browser appears. 2. In the Servers pane, select the server that you want to restart. 3. Click mouse button 2, and select Restart Server from the pop-up menu. In the Servers pane, an icon appears beside the server to indicate that it is running.
73
Configuration browser or the EJBs page. The test client will also automatically locate the EJB using the JNDI name specified as part of the EJBs deployment descriptors. If you start the test client outside of the EJB Server Configuration browser or the EJBs page, you need to set the classpath of the test client program. We recommend that you start the test client in either the EJB Server Configuration browser or in the EJBs page. We now describes the basic steps required to run the test client. To run the default test client: 1. In the EJB Server Configuration browser, ensure that the Name Service servers and the EJB Server are running. (Information about starting these servers is found in the topic, Starting the Name Service and EJB Servers on page 71. 2. In the EJBs pane of the EJB Server Configuration browser, select the ReadCustomerInfo EJB for which you have created a test client. (If the EJB does not appear in the EJBs pane of the EJB Server Configuration browser, you must add the EJB to a server configuration by following the instructions in the topic, Testing EJBs on page 67.
74
3. Click on the Run Test Client icon to run the test client. The Connect page of the Test Client window appears:
4. The Provider URL field contains the hostname of the server you are connecting to. In this case iiop:/// stands for iiop://localhost. The JNDI name field contains the JNDI name for your EJB. To find out which is the JNDI name of your EJB please refer to Generate deployment code inside VisualAge for Java on page 64 on how to get to the EJB Properties window ( see Figure 24 on page 58) The Initial Context Factory field contains the class name to be used as the context factory of the naming service. The Home Interface contains the fully qualified name of the EJB Home interface. The Home Helper field contains the fully qualified name of the Helper class of the EJB being tested To establish a connection to the name server, click the Connect button. The client constructs an initial naming context, and ask the name server to look up an instance of the home interface for the ReadCustomerInfo EJB you are testing. Once the connection is made and an instance of the home interface is retrieved, the test client automatically switches to the Home Interface page
75
Figure 41 shows the test client for the ReadCustomerInfo bean. ReadCustomerInfo is a stateless session bean, so its home interface (ReadCustomerInfoHome) contains only one create method. The other methods shown are defined by the javax.ejb.EJBHome interface, which ReadCustomerInfoHome extends, and they are marked with a trailing :: EJBHome. 5. In the Methods pane, select the create() method. Click the Send button in order to create the remote interface object. This sends the method call to the EJB server to create the new ReadCustomerInfo bean. The resulting remote interface object will be used by the test client for testing remote methods When the remote interface object is retrieved, the test client will switch to the Remote Interface page:
76
In the Remote Interface page, the Methods pane contains the list of methods defined by the remote interface, plus methods defined by the interface javax.ejb.EJBObject. 6. Select the readCustomer() method in the Methods pane. 7. Click the Send button to send the method to the EJB. The result of the method call is displayed below the Methods pane. The result should look as in Figure 43.
77
8. If you want to examine the result object, click the Inspect button. This launches the VisualAge for Java Inspector.
78
After testing the ReadCustomerInfo EJB we can now build our own client application.
use an enterprise Bean in a Java client, the client must contain code that does the following: Imports the Java packages required for naming, remote method invocation,and EJB interaction. Instantiates the Beans EJB object. For more information, see Instantiating an EJB Object on page 80. Refreshes the reference to each EJB object associated with a session Bean if the reference becomes invalid.
Properties, Hashtable, and Enumeration used is a variety of ways throughout all enterprise beans.
u javax.ejb.* u javax.naming.* u The package for each enterprise Bean with which the client interacts.
80
The ReadCustomerInfo client application is made of two JavaBeans the ReadCustomerClient and the ViewController. It follows the MVC paradigm The ReadCustomerClient is the visual part and the ViewController is the controller on the visual part. This means that all the access to the EJB and the action performed on the button goes really to the controller, The model is represented by the ReadCustomerInfo EJB. The ViewController has a create(String,String,String ) method that is called inside the getCustomer() method of the ViewController class. The parameter passed here respectively the hostname,the naming service class to be used,and the port number. When the windowOpened event is detected for the ReadCustomerClient an instance of ViewController is created with the right parameters. The code in this section is taken from the example Java application ViewController.java; all of this code is contained in the applications create(String,String,String) method. The Enterprise JavaBeans specification contains instructions for using classes in the javax.rmi package to locate a Beans home interface. Unfortunately, this package has not been implemented. Therefore, IBM has implemented an alternative way to locate a home interface by using the IBM CosNaming naming and directory service. Locating an enterprise Beans home interface is a two-step process. First, you create a javax.naming.InitialContext object. Then, you use the InitialContext object to get the EJBHome object.
81
The code below shows what is required to create the InitialContext object. To create this object, you construct a java.util.Properties object, assign environment values to the Properties object, and then pass the object as the argument to the InitialContext constructor.
public void create(String host,String port) { ReadCustomerInfoHome rCHome = null; javax.naming.InitialContext initContext = null; // Get the initial context try { System.out.println("Retrieving initial context..."); java.util.Properties properties = new java.util.Properties(); // local name server System.out.println("-------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://"+host+":"+port); properties.put(javax.naming.Context.PROVIDER_URL, "iiop://"+host+":"+port); // IBM name services System.out.println("-------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory"); properties.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, com.ibm.jndi.CosNaming.CNInitialContextFactory"); System.out.println("-------Invoke: javax.naming.InitialContext(properties)"); initContext = new javax.naming.InitialContext(properties); } catch (javax.naming.NamingException e) { System.out.println("Error retrieving the initial context: " + e.getMessage()); System.exit(0); } // endtry catch (Exception e1) { System.out.println("Error retrieving the initial context: " + e1.getMessage()); e1.printStackTrace(System.out); System.exit(0); } // lookup the home interface using the JNDI name ........ // create a new ReadCustomerInfo to set ...... set... }
Once the InitialContext object is created, the application uses it to create the EJBHome object. This creation is accomplished by invoking the lookup method which takes the Java Naming and Directory Interface (JNDI) name
82
of the enterprise Bean in String form and returns a java.lang.Object object. The returned object is filtered, using the static method narrow, to obtain an EJBHome object for the specified enterprise Bean. The narrow method is contained in the home helper class generated during Bean deployment. For the ReadCustomerInfo Bean, this home helper class is named ReadCustomerInfoHomeHelper.
public void create(String host,String port) { ReadCustomerInfoHome rCHome = null; javax.naming.InitialContext initContext = null; ..... //Get the Initial context ..... // lookup the home interface using the JNDI name try { System.out.println("Retrieving the home interface..."); java.lang.Object o = initContext.lookup("ReadCustomerInfo"); // this is the JNDI name if (o instanceof org.omg.CORBA.Object) rCHome = ReadCustomerInfoHomeHelper.narrow((org.omg.CORBA.Object) o); } catch (javax.naming.NamingException e) { System.out.println("Error retrieving the home interface: " + e.getMessage()); System.exit(0); } // endtry ... // Create a new ReadCustomerInfo to set ... set.. }
The code below shows how to create the EJB object by using the EJBHome object. The EJB object is obtained by calling a create method.
public void create(String host,String port) { ReadCustomerInfoHome rCHome = null; javax.naming.InitialContext initContext = null; ..... //Get the Initial context ..... // lookup the home interface using the JNDI name // Create a new ReadCustomerInfo to set System.out.println("Creating new ReadCustomerInfo..."); ReadCustomerInfo rC = null;
83
try { rC = rCHome.create(); System.out.println("ReadCustomerInfo created!"); } catch (Exception e) { System.out.println("Exception creating new ReadCustomerInfo: " + e.getMessage()); e.printStackTrace(System.out); System.exit(0); } // endtry if(rC== null) System.out.println("Unable to creating ReadCustomerInfo "); //this method sets the ReadCustomerInfo instance in the ViewController class setReadCustomers(rC) }
You can open the ReadCustomerClient to the visual composition editor in order to understand the application flow. To start and test the ReadCustomerClient client inside VisualAge: 1. In the EJB Server Configuration browser, ensure that the Name Service servers and the EJB server are running. 2. In the EJBs pane of the EJB Server Configuration browser, select the EJB which you will access with your own client application. 3. In the Workbench Projects page or other page where your client resides, select your client class and click mouse button 2, then select Properties. The Properties dialog appears. 4. In the command line argument type hostname 9001 as parameters 5. Click the Class Path tab. 6. Beside the Project Path field, click the Edit button. The Class Path dialog appears. 7. Select the IBM WebSphere Test Environment project and click OK. 8. At the bottom of the Properties dialog, select the Save in repository (as default) check box and click OK. 9. Select your client class, then click mouse button 2 and select Run - Run main. 10.When the ReadCustomerClient window appear click the Get Customer Data button. The result should be as in Figure 45
1
In the VisualAge for Java IDE, the Persistent Name Server runs on port number 900.
84
Once you finished to test your EJB you need to sop the servers. (I put this in the appendix if it s ok we need to remove it from here and refer to the appendix)!!!!!!!
The Console window indicates that the server has been terminated. Removing EJB Servers You cannot remove the Location Service Daemon or the Persistent Name Server. You may, however, remove EJB servers from the EJB Server Configuration browser. To remove an EJB server: 1. In the EJB Server Configuration browser, in the Servers pane, select the EJB server that you want to remove. 2. Click on the icon to stop the server (if it is not already stopped). 3. Select the EJB server again, click mouse button 2, and select Remove Server from the menu. The EJB server is removed from the list of servers in the Servers pane.
85
An EJS jar file contains both EJB code and deployed classes. An EJB jar file contains EJB code, but no deployed classes. NOTE: All the EJS runtime files are excluded automatically from the jar file. To export an EJB to an EJS or EJB jar file: 1. In the EJBs pane of the EJBs page, select one or more EJB groups or EJBs. 2. Click mouse button 2, then do one of the following:
To export EJB code and deployed classes, select Export - EJS JAR from the pop-up menu. After the jar file is created, you can install it on a WebSphere EJS.
86
To export EJB code select Export - EJB JAR from the pop-up menu. After the jar file is created, you can deploy it into a EJB container using the deployment tool provided by the EJB Container provider. If you choose the Export to an EJB Jar File SmartGuide appears.
3. In the Jar file field, type the name of the jar file you want to create. Alternatively, click the Browse button to select an existing jar file to
87
overwrite. The SmartGuide marks all of the class files associated with the selected EJB groups or individual EJBs for exportation to the jar file. 4. To select individual file types to export, click one or more of the following check boxes: beans: export all the beans in the EJB group or the individual EJB you selected. class files: export all the bytecode files for the selected EJB group or EJB. java files: export all the source code files for the selected EJB group or EJB. resource: export all the non-.java and non-.class files for the selected EJB group or EJB. Details: by default, all the files for the selected file type are exported. Click the Details button next to a file type to see a list of the files that will be exported, and to specify individual files to export. 5. To ensure that any types or resources referenced by the selected EJB group or EJB are also exported, click the Select referenced types and resources button. 6. Specify additional options as appropriate using the Options check boxes as follows: Include debug attributes in .class files: if you want to debug the exported classes using an external debugger, click this check box to include debugging information for the exported classes. Compress the contents of the jar file: compress the exported files. Overwrite existing files without warning: if you are exporting to an existing jar file, and you do not want to be warned about overwriting existing files, click this check box. Automatically open a web browser on created .html files? Do not click this check box since we do not have any html file. 7. Click Finish. You will follow essentially the same steps if you decide to export to an EJS .jar file. The only difference will be the content of the file exported.
88
classpath of the client project, we recommend that you include the client jar file in the client classpath before executing the client application. This provides better code isolation between the client and server code. To export an EJB to a client jar file: 1. In the EJBs pane of the EJBs page, select one or more EJB groups or Gibson our case you will just select the ReadCustomerInfo sessionbean). 2. Click mouse button 2, then select Export - Client JAR from the pop-up menu. The Export to an EJB Jar File SmartGuide appears.
89
As you can see from Figure 48 the content of this dialog is exactly the same of the previous dialog in Figure 47. The meaning of the fields is the same the only difference is the content of the .jar file.
Export an EJB to a client.jar file As described in the topic "Exporting EJBs to Client Jar files" export the client .jar file to a file called ReadCustomerInfoCli.jar. Export it to the C:\ root directory. If you decide to export it to a different directory you will need to change the class path accordingly. Export the client code you need to export the content of the following packages: itso.samples.ejb.sessionbean.client itso.samples.ejb.sessionbean.client Export them to a .jar file called client.jar file. We pack all together because we have few classes but the right thing could be to have two different .jar file one for the client code and one for the mode that in our case is the CustomerObject JavaBean only. In the next session assume you have exported the .jar file in the C root directly: You will now have to check you have the following files in the c:\ ReadCustomerInfoCli.jar CustomerObject.jar Client.jar customer.ser Open a DOS prompt check your class path and check you have the following in your classpath:
.; c:\;
90
C:\ReadCustomerInfoCli.jar; c:\CustomerObject.jar; c:\client.jar; c:\WebSphere\AppServer\lib\ejs.jar; c:\WebSphere\AppServer\lib\jndi.jar; c:\IBMVJava\eab\runtime20; c:\IBMVJava\eab\runtime; c:\IBMVJava\eab\runtime20\jdebug.jar; c:\SQLLIB\java\db2java.zip; c:\SQLLIB\java\runtime.zip; c:\swing-1.0.3\swingall.jar
NOTE:
u You should not have to care about VisualAge for Java and DB2 path they
should have been set during the installation procedure of both products but you will for sure need to add manually the one regarding WebSphere.
u If you have exported the jar files to different directories make those
changes to be reflected in the classpath. But remember the customer.ser file has to be in the C:\ root. Make sure the EJB environment is up and running inside VisualAge for Java which mean all EJB servers are started. Run the java client from the DOS Prompt using the following command:
java itso.samples.ejb.sessionbean.client.ReadCustomersClient iron com.ibm.jndi.CosNaming.CNInitialContextFactory 900
91
Login into the administration server. In the left pane choose Enterprise Java Services - Containers. On the right side of the window choose defaultEntityContainer and click Remove. You should now have only the defaultSessionContainer shown in the list.
92
In Figure 50 you can see the container settings. Container Name field: shows the container name you assigned to the container Container Class files: contains the class name of the container services used by WebSphere. In this case we have com.ibm.ejs.container.EJSSessionContainer for Session Beans. com.ibm.ejs.container.EJSEntityContainer is used for Entity Beans. JDBC URL field: You need to specify this information only if you are defining a container that is supposed to contains Entity Beans in this case you have to specify something like
jdbc:db2:ejs_samp
EJB Jar Directory field: this is the directory where the WebSphere server look to find the jar file deployed in the container. The directory is called deployedEJBs and it is found under: drive:\WebSphere\Appserver directory.
93
Container Database Authentication: in this fields you see the Container User ID and password (which is the same as your DB2 administrator userid and password) Deployed EJB Jar File list: You can see the list of the already deployed jar files. In the left pane select Enterprise Java Services - EJB Jar Files to see which EJBs can be deployed and which have already been deployed. We now want to deploy the ReadCustomerInfo session bean inside WebSphere. 1. From VisualAge for Java go to EJB workspace select the ReadCustomerInfo bean and export it to EJS jar file as described in the topic "Exporting EJBs to EJS or EJB Jar Files on page 85. 2. Export the EJS jar file in the drive:\WebSphere\AppServer\deployableEJBs. following directory.
Call it ReadCustomerInfo.jar. Remember that you also need to export the client .jar file and the client application. As described in Running the client outside VisualAge for Java on page 90.
*** NOTE ***
Before you can deploy the ReadCustomerInfo.jar inside WebSphere you have to make sure that WebSphere has in his class path a reference to the CustomerObject.jar file. If it doesnt you get an error saying it could not read the .jar file when attempting to deploy. The reason why you get this is that the ReadCustomerInfo uses the CustomerObject class which is found in the CustomerObject file. To know how to update WebSphere class path please refer to Appendix A.3, Updating WebSphere Class Path on page 350 3. From Enterprise Java Services select EJB Jar Files. You now see the ReadCustomerInfo.jar file in the EJB Jar File list. 4. Select the ReadCustomerInfo.jar file the content of this file appears in the right pane. 5. Click Deploy button. The following window appear:
94
6. Make sure the container selected is the right one (defaultSessionContainer in our case). Click the Deploy button. The following window appear:
7. The Window in Figure 52 box shows three options: Regenerate which is used for JAR files that have never been deployed; it creates the stubs and skeletons and database tables necessary in a deployed EJB. Redeploy Existing is used for any predeployed samples; it uses the existing stubs and skeletons contained in the JAR file and creates the necessary database tables (only for Entity Bean). Cancel allows you to revert to the previous screen. Since we have exported an EJS jar file from VisualAge for Java the ReadCustomerInfo bean is already deployed. Click Redeploy Existing. If everything is ok with the deployment you get the following message.
95
8. Logoff from the administration server. Stop and restart your WebSphere Application Server for this to take effect. To stop WebSphere: Shut down the Web server(from Start- Settings- Control PanelServices and select Lotus Domino Go Webserver click the Stop button.) Shut down the WebSphere ServletService to stop Application Server. (Select the WebSphere Servlet Service from StartSettings- Control Panel- Services and push the Stop button.) To start WebSphere: The server starts automatically when you start your Web server(from Start- Settings- Control Panel- Services and select Lotus Domino Go Webserver click the Start button.) You are now ready to test your environment using the ReadCustomerClient application. Open a DOS Window check your classpath as explained inRunning the client outside VisualAge for Java on page 90. From the DOS Prompt run
java itso.samples.ejb.sessionbean.client.ReadCustomersClient iron com.ibm.jndi.CosNaming.CNInitialContextFactory 9019
NOTE: In the VisualAge for Java IDE, the Persistent Name Server runs on port number 900. However, in WebSphere Advanced Edition 2.0, it runs on port number 9019. The port number value can be configured. This is the reason why when you write your client application you need to pass in the right port number.
96
97
Once you get your new .jar file you can deploy it in any EJB container using the tools the container provide to you. You need to follow the container tool instruction. Just to let you understand which should be the common procedure we will deploy this new .jar file inside WebSphere. In this case we work as VisualAge for Java do not provide us the possibility to export directly to the EJS jar. Before we can deploy the jar again we need to undeploy it. 1. From Enterprise Java Services select EJB Jar Files. You now see the ReadCustomerInfo.jar file in the EJB Jar File list. 2. Select the ReadCustomerInfo.jar file the content of this file appears in the right pane. 3. Click Undeploy button. The following window appear:
4. Make sure the container selected is the right one(defaultSessionContainer in our case). Click the Undeploy button. The following window appear:
98
5. From VisualAge for Java go to EJB workspace select the ReadCustomerInfo bean and export it to EJB jar file as described in the topic "Exporting EJBs to EJS or EJB Jar Files on page 85. 6. Export the EJB jar file in the drive:\WebSphere\AppServer\deployableEJBs following directory.
7. Follow the steps for the deployment again. This time it will take longer since all the EJS files needed to be created. 8. Logoff from the administration server. Stop and restart your WebSphere Application Server for this to take effect.
We will give you an example on how to use the jet tool. To run jet navigate he WebSphere path as window shown in Figure 57
99
Select jet.bat and double click on it. The jet will start and the window shown in will appear.
100
To generate a deployment descriptor file for an enterprise Bean with the jet tool, do the following: 1. Specify the full path of the .jar file containing your enterprise Bean in the Input field. You can use the Browse button to obtain the file that you need. If you created your input .jar file correctly, all of the fields in either the EntityBean or SessionBean window are filled in with the default deployment descriptor values for your Bean. Try to import the ReadCustomerInfo.jar we used in Deployment for Other Enterprise JavaBeans Servers on page 97. The
101
ReadCustomerInfo.jar is an EJB jar file generated by VisualAge for Java it does already contain a deployment descriptor. This is the reason why you get the following message:
Click the Yes button to examine the content of the Deployment descriptor. Your jet tool should now appear like the following
102
Figure 60. The jet Tool after Importing the ReadCustomerInfo Bean
2. Specify the full path of the ejb-jar file to create in the Output field. You can use the Browse button to obtain the file that you need. (If you want to create an XML file containing the descriptor only, specify the full path to that file in the XML Output field. Note that this file is not required.). You generally specify the same name as the input. Here we want jut to see how the .jar file i modified with the deployment descriptor. So just type file name. 3. You can notice that only the SessionBean tab is available for the selection. This is why the tool recognize the type of Bean he is dealing with. Select the SessionBean tag. 4. You can navigate in the jet tool tag and you will discover a match of the information shown with the property dialog in Figure 24 on page 58. To create a deployment descriptor, you must specify appropriate values for
103
the type of Bean you are creating as described in Generate deployment code inside VisualAge for Java on page 64. 5. By selecting the Environment tab, you can modify the property customerFile and assign it a value different from what the developer set during development time (see Figure 26 on page 60). For example, we change the path to access the file customer.ser from: c:\customer.ser to z:\ITSO\SG245429\Redbook\customer.ser as shown in Figure 61:
6. When the attribute and other values are set, press the Build button to build the deployment descriptor file and add that file to the output .jar file For more detail on the jet tool please refer to Websphere Enterprise Server for Java Programming Guide At this point you can deploy your EJB inside WebSphere. During deployment, an ejs-jar file is generated from an ejb-jar file. The ejs-jar file contains the container-specific stub, skeleton, implementation, helper, and holder classes required by the container.
104
The WebSphere EJBDeploy command can be used to manually deploy an enterprise Bean. This command-line tool can also be used to generate the database tables required for entity Beans. The syntax of the EJBDeploy command follows:
java com.ibm.ivj.ejb.tools.deployment.EJBDeploy ejb-jarFile workingDirectory ejs-jarFile[options]
The following command parameters are required: ejb-jarFileIdentifies the ejb-jar input file to be deployed. workingDirectoryIdentifies a working directory that is used by the command to store temporary files during deployment. ejs-jarFileIdentifies the ejs-jar output file to be created during deployment. Optionally, you can specify one or more of the following command parameters to fine tune the actions of the EJBDeploy command:
u -analyzeDirects the command to analyze the contents of the ejb-jarFile
to ensure that it contains all required files and that the classes and interfaces define a valid enterprise Bean.
u -codegenDirects the command to create EJS implementation classes
table for use by the enterprise Bean. The argument to this parameter has the following format: dbAPI:database:tableName. For example, to create a database table named sample in an IBM DB2 database with the Java Database Connectivity (JDBC) API, the argument is jdbc:db2:sample.
u -dbuid dbUserIdDirects the command to associate the specified
database user ID with the Bean so that the container can access the database on the Beans behalf. This parameter must be used in conjunction with the -dbpass parameter.
u -dbpass dbPasswordDirects the command to associate the specified
database password with the Bean so that the container can access the database on the Beans behalf. This parameter must be used in conjunction with the -dbuid parameter.
u -forceDirects the command to ignore verification errors (those that can
be discovered by using the -analyze parameter) and create the ejs-jar file.
u -nocleanDirects the command to refrain from deleting the classes
105
The follow command deploys the example ReadCustomerInfo.jar ejb-jar file into an ejs-jar file named ReadCustomerInfoEJS.jar using the working directory C:\TestApp:
C:\TestApp> java com.ibm.ivj.ejb.tools.deployment.EJBDeploy ReadCustomerInfo.jar C:\TestApp ReadCustomerInfoEJS.jar
Once you have deployed your enterprise Beans, you have to copy the ReadCustomerInfoEJS in the deployable directory inside WebSphere and follow the steps in Deployment on WebSphere Advanced Edition 2.0 on page 91
106
107
information on the tasks required to develop an entity Bean with BMP, see Chapter 5, Developing a Bean-managed persistence bean on page 173.
108
5. Set your Deployment descriptors. (This step can be done anytime after you have added your EJBs. However, it must be done before you test/deploy your EJBs.) 6. Generate the EJB deployed classes. 7. Test the EJBs. 1. Create an EJB server configuration. 2. Start the DB2 servers (if testing entity beans). 3. Create any required database tables. 4. Start the Name Service and Location Daemon servers and the EJB server. 5. Generate an EJB test client. 6. Run the EJB test client. In this chapter we create a sample Customer EJB, add methods to their remote and home interfaces, add CMP fields, create an empty DB2 database, map the CMP fields to the database tables (using the meet in the middle approach), set the Deployment Descriptors, generate the deployed code and test the Bean.
109
As you can see using the Create EJB SmartGuide, you can add an EJB by either creating a new EJB or by retrieving one or more existing EJBs from the Repository. To add an EJB by creating a new EJB:
110
1. Ensure that the Create a new Bean Class radio button is selected. 2. In the Bean name field, type in Customer which is the name that you want to assign to your new EJB. 3. Since you are creating a new EJB bean class, you need to specify the type of EJB you want to create. The Customer is a Container-managed persistence Bean so from Bean type drop-down list choose Entity Bean with container-managed persistence fields (CMP). 4. In the Project field, you can type the project name, modify the default name, or click the Browse button and select the project that will contain the EJB bean class. If you type a project name that does not exist, VisualAge for Java will not let you create your Bean, see Figure 63. By default, the project to which the EJB group belongs is displayed. In our case we use the default project, which is ITSO Bank.
111
5. In the Package field, you can type the package name, modify the default name, or click the Browse button to select the package that will contain your EJB bean. If you enter a package that does not exist,
112
a new package is created. Type itso.samples.ejb.CMP in the package field. 6. In the Class field, either accept the default value or type in a name for the new class. We recommend that you use the default value so that all the implementation types of the EJB are named properly 7. Since we do not provide any superclass for our Customer bean we do not fill the Superclass field. Your SmartGuide should look like Figure 64.
113
114
Click on Next > to go to the next page of the Create EJB SmartGuide. Your screen should now look like Figure 65.
8. We use the default names in our Customer example for the EJB Home Interface, EJB Remote Interface and EJB Key Class or Field so we dont change their values. If you wish to use your own Home Interface,
115
Remote Interface or the KeyClass names you can change them in this window. The Create finder helper interface to support finder methods checkbox, tells VisualAge for Java to generate the CustomerBeanFinderHelper method. We need the CustomerBeanFinderHelper to add a special finder on the Customer Beans. If you dont need any other finder than the getByPrimaryKey for your Bean, you dont need to check this option. If you need to implement specific import and/or interfaces in your Bean, select them using the appropriate buttons. The Create method stubs which must be implemented (Recommended) checkbox ensure that stubs are created for the methods declared in the interfaces you selected. 9. Click on Finish to generate the classes you need to develop the Customer implementation. Now, your Workbench should look like Figure 66.
116
As you can see in Figure 66, VisualAge for Java generates 5 different types for you. These types are respectively:
u Customer interface (the remote interface) u CustomerBean class (the Entity Bean) u CustomerBeanFinder interface
117
VisualAge for Java automatically creates according to the EJB specification these 5 classes required for a Container-managed persistence EJB .
118
The association between the project and the package containing our bean code, schemas and maps is made at the creation of the EJB Bean, see Figure 68.
119
The Customer interface is the remote interface for the CustomerBean EJB object. The Customer Beans remote interface provides access to the business methods available in the CustomerBean class. By convention, the remote interface is named Name, where Name is the name you assign to the enterprise Bean. For example, the Customer enterprise Beans remote interface is named Customer. The Customer remote interface is covered in detail in topic 4.4, Adding remote interface methods on page 137.
u CustomerBean class
The CustomerBean class represents the Entity Bean. It must implement the business methods used to access and manipulate the data associated with the enterprise Bean.
120
It must define and implement an ejbCreate method for each way in which the enterprise Bean can be instantiated. A corresponding ejbPostCreate method must be defined for each ejbCreate method. A thumb rule for deciding the parameters for an ejbCreate method: all the non-nullable fields should be inititalized from the parameters so that there is no exception at the persistence store end. For example, when using RDBMs, if a row is inserted into a table with null values for columns declared as non-nullable, the RDBMs will throw an exception. The CustomerBean class defines and implements the business methods of the Customer enterprise bean, defines and implements the methods used to create instances of the Customer enterprise Bean, and implements the methods used by the container to inform the instances of the enterprise Bean of significant events in the instances life cycle (callbacks methods). By convention, the enterprise Bean class is named NameBean, where Name is the name you assign to the enterprise Bean. The enterprise Bean class for the example Customer enterprise Bean is named CustomerBean.
u CustomerBeanFinderHelper interface:
The CustomerBeanFinderHelper interface is used by the container to generate the necessary code for querying the database on custom filters. You use the special finder methods to retrieve instances from the database, using other search criteria than the primary key value (for example a search by customers last name). For each finder method defined in the home interface (CustomerHome) other than the create and findByPrimaryKey methods, you are responsible to define the corresponding query string. The topic 4.5, Modifying, adding home methods on page 140 explains how to add finder methods.
u CustomerHome interface:
The CustomerHome interface is the home interface for the Customer entity Bean. An entity Beans home interface defines the methods used by clients to create new instances of the Bean, find, remove existing instances, and obtain meta data information about an instance. This home interface is implemented by the EJB home class generated by the containers deployment tool. The container registers the home interface into the naming tree allowing EJB clients to access it using the JNDI API. By convention, the home interface is named NameHome, where Name is the name you assign to the enterprise Bean. For example, the Customer enterprise Beans home interface is named CustomerHome. The topic 4.5, Modifying, adding home methods on page 140 covers the Home interface.
121
u CustomerKey class:
Every enterprise entity bean has a unique identity within a container that is defined by using a combination of the objects home interface name and its primary key and assigned at object creation time. If two EJB objects have the same identity, they are considered identical. The bean key class is used to encapsulate a primaryKey. By convention, the bean key class is named NameKey, where Name is the name of the enterprise Bean. For example, the Customer enterprise Beans primary key class is named CustomerKey. It must be public and it must be serializable. Its instance variables must be public and the variable names must match a subset of the variable names defined in the enterprise Bean class. The CustomerKey class is an object generated by VisualAge for Java to help you creating new instances and finding existing instances of the Customer entity bean from the database. This CustomerKey object is a unique representation of the Customer. The methods from the CustomerHome interface using it: create(CustomerKey) findByPrimaryKey(CustomerKey) methods generated for the CustomerKey are described in the topic 4.3, Understanding the generated methods on page 132.
122
Now we add two additional fields firstName and lastName. 1. In the EJB list of the EJBs page, select the Customer EJB bean.
123
3. Select the CustomerBean class, click mouse button 2 in the types list. Select Add Field from the pop-up menu. The Create Field SmartGuide appears. 4. Fill in with the following informations, Field Name is firstName, Field Type is java.lang.String. All the CMP Fields of a CMP Entity Bean must be public, so the Access Modifiers has to be public. Mark the Access with setter and getter methods check box as checked and select in the setter and getter group boxes the public radio buttons. Your screen should look like Figure 70. Other Modifiers group box options are described in the topic , Regarding the other modifiers (final, transient, static) on page 129.
124
5. Click Finish. 6. Repeat steps 3 and 4 for two additional fields: lastName and dummy. 7. Click on the Fields icon to see the newly created fields: dummy, firstName and lastName, in your CustomerBean entity Bean, see Figure 71.
125
The idea with Container-managed persistence EJB is to let the container handle all of the database interactions involved with the creation, read, update and deletions of EJB. In order to achieve this, you need to identify which are the fields you want to be Container-managed persistence fields. Each of these identified CMP fields are persistent in a database record field. The container determines which fields are of Container-managed persistence type by calling the getContainerManagedFields() method of the entity descriptor which returns a Field[] array. VisualAge for Java lets you identify which fields are container managed. To define dummy, firstName and lastName as CMP fields: 1. Select dummy field press and hold on the Ctrl key on the keyboard and click with mouse button 1 on firstName and lastName. 2. Click on mouse button 2 and select Container Managed. An icon appears on the right side of dummy, firstName and lastName indicating that they are Container-managed persistence fields, see Figure 72.
126
The code you provide in your beans does not contain any database access, creation and updates. VisualAge for Java generates the necessary code at deployment time for you. VisualAge for Java also generates all the accessors (getter and setter). These methods are described in topic 4.4, Adding remote interface methods on page 137.
Removing a field
In this section we show you how to remove the dummy CMP field from the Customer CMP Bean. 1. Click on the dummy field from the Fields list. Click on mouse button 2 and deselect Container-Managed. 1. From the Methods list, you need to click on the getDummy() method. Press the Ctrl key on the keyboard and select the setDummy() method as well. 2. Click on the mouse button 2, select Delete. 3. VisualAge for Java ask you for a deletion confirmation, click Yes. 4. You just have deleted the getter and setter methods for the field you want to delete.
127
5. You need to click on the Customer EJB from the EJBs list to see the Class definition in the source window. You need to delete the dummy field declaration from the source window, see Figure 73.
6. Press Ctrl-S to save your Customer Bean. The dummy field disappears from the Fields list. Your Workbench now looks like Figure 74.
128
lifetime. If you select the final modifier, VisualAge for Java will not generate a setter method for the field, but it will generate a getter method. This means, you will be able to retrieve the value of the field, but you will be not able to set it. This final CMP field should be initialized properly in the ejbCreate method. You can use a final CMP field to store a constant value in from your database into a member attribute of your CMP Entity Bean.
u static modifier is not supported by CMP fields. u volatile u transient modifier can be used for local variables. The transient
modifier basically means that the CMP member field is not persisted to the database. For example, assume a field contains the result of a long calculation. A remote method needs this field several times during its execution. Instead of calling the fields getter methods several time, we can use a CMP transient field to store its value. This way we save CPU processing time. This is illustrated in Figure 75.
129
130
6. Press CTRL-S to save your method. Each time you create a Customer EJB using its CustomerKey object, the proper key fields (primaryKey and lastName) are initialized properly.
131
11. You can now work with your newly created key.
Creation State
An entity Bean instances life cycle begins when the container creates that instance. After creating a new entity Bean instance, the container invokes the instances setSessionContext method. This method passes the Bean instance a reference to an entity context interface that can be used by the instance to obtain container services and get information about the caller of e client-invoked method.
132
Pooled State
Once an entity Bean instance is created, it is placed in a pool of available instances of the specified entity Bean class. While the instance is in this pool, it is not associated with a specific EJB object. Every instance of the same enterprise Bean class in this pool is identical. While an instance is in this pooled state, the container can use it to invoke any of the Beans finder methods.
Ready State
When a client needs to work with a specific entity Bean instance, the container picks an instance from the pool and associates it with the EJB object initialized by the client. An entity Bean instance is moved from the pooled to the ready state if there are no available instances in the ready state. There are two events that cause an entity Bean instance to be moved from the pooled state to the ready state: When a client invokes the create method in the Beans home interface to create a new and unique entity of the entity Bean class (and a new record in the data source). As a result of this method invocation, the container calls the Bean instances ejbCreate and ejbPostCreate methods and the new EJB object is associated with the Bean instance When a client invokes a finder method to manipulate an existing instance of the entity Bean class (associated with an existing record in the data source). In this case, the container calls the Bean instances ejbActivate method to associate the Bean instance with the existing EJB object. When an enterprise Bean instance is in the ready state, the container can invoke the instances ejbLoad and ejbStore methods to synchronize the data in the instance with the corresponding data in the data source. In addition, the client can invoke the Bean instances business methods when the instance is in this state. All interactions required to handle an entity Bean instances business methods in the appropriate transactional (or non transactional) manner are handled by the container, unless the EJB developer has decided to handle these interactions. When a container determines that an entity Bean instance in the ready state is no longer required, it moves the instance to the pooled state. This transition to the pooled state results from either of the following events: When the container invokes the ejbPassivate method. When the client invokes a remove method on the EJB object associated with the Bean instance or on the EJB home object. When one of these 133
methods is called, the underlying entity is removed permanently from the data source.
Removal State
An entity Bean instances life cycle ends when the container invokes the unsetEntityContext method on a entity Bean instance in the pooled state. Do not confuse the removal of an entity Bean instance with the removal of the underlying entity whose data is stored in the data source. The former simply removes an uninitialized object, the latter removes data from the data source.
We describe these two methods at the same time, since their utilization is quite similar. The EJB Specifications from Sun are quite vague on this ejbLoad and ejbStore methods. They say that: "..., the container can invoke the ejbLoad() and ejbStore() methods one or more times, at anytime. " (section 9.3 - Instance Lifecycle, p.62) "The purpose of the ejbLoad method is to synchronize the state of the instance with the state of the entity in the underlying data source" (section 9.3 - Instance Lifecycle, p.62) Let us give you a clear understanding of what these two points mean with VisualAge for Java and WebSphere. First, for all CMP fields in your CMP Bean, you dont have to care about the CMP fields state synchronization with the data store, since the container takes care of it. This means for CMP fields, you dont need to add any code to these callback methods. WebSphere always call ejbLoad() after a new transaction has been started, and after you invoke a method from the remote interface. If you have any non-CMP fields in your CMP Bean which always needs the latest state (like stock tickers), you should use the ejbLoad() callback method to initialize them. The ejbStore is called after a transaction has been committed. public void ejbPassivate(); The EJB container invokes this method when it decides to send the instance to the pooled state based on a least recently used algorithm. With VisualAge for Java and WebSphere this means, your instance is disassociated from its EJB Object after a defined period (time-out). You can use this method to release any resources that were allocated in the ejbActivate() method. public void ejbPostCreate(CustomerKey key); This life-cycle callback method indicates that the EJB Object identity is available. For each ejbCreate(...) method, there is a matching ejbPostCreate(...) method with the same input parameters. If you add an ejbCreate() to the Entity Bean, you need to add an ejbPostCreate() method as well with matching parameters. public void ejbRemove(); This method is invoked by the container when the client invokes the remove method on an EJB object reference. You can use the ejbRemove method to implement actions you want to take place before the instance is removed from the database. The record is deleted from the
135
database after ejbRemove returns. You dont have to implement the logic to remove the entity from the persistence store, the container takes care of it. public void setEntityContext(EntityContext ctx); public void unsetEntityContext(EntityContext ctx); These two methods are explained in the topic , Life cycles of enterprise Bean instances on page 132.
136
method that enables a client to locate an EJB Object by using the primary key only. VisualAge for Java creates this default finder method automatically for you. We have in our example a findByPrimaryKey which uses a CustomerKey object to identify a particular entity. The findByPrimaryKey returns the type of the CustomerBean remote interface Customer.
137
1. It must extend the javax.ejb.EJBObject interface. The EJBs remote interface inherits several methods from the javax.ejb.EJBObject interface. VisualAge for Java takes care of this for you. See topic , Methods inherited from javax.ejs.EJBObject on page 139 for information on these methods. 2. Each method implemented in the enterprise bean class that needs to be accessed by a client must appear in the remote interface. VisualAge for Java automates this task. 3. The parameters and return value of each method defined in the interface must be a valid Java RMI type. For more information, see topic , Using valid parameters and return values for Java RMI on page 140. In this section we will add 4 methods to the remote interface. Two methods to get information from the Bean and two other to update information in the Bean. VisualAge for Java generated these methods for us when we created the fields. The steps to add them to the remote interface are: 1. select the CustomerBean Class in the Types list, this displays its corresponding methods. 2. select the getFirstName method and click mouse button 2. Choose Add To - EJB Remote Interface. The method is marked with an icon indicating the method has been added to the Customer remote interface. 3. to select multiple methods, press the Ctrl key on the keyboard and click each of the methods you want to select: getLastName, setFirstName, setLastName. Click mouse button 2 and select Add To - EJB Remote Interface. Your Types and Methods panes should look like Figure 76.
138
Figure 76. Methods added to the Remote Interface are identified by an Icon
4. To see where VisualAge for Java added your remote methods, select the Customer interface from the Types list. You see the 4 methods in the Methods list, see Figure 77.
139
getHandleReturns the handle for the EJB object. getPrimaryKeyReturns the EJB objects primary key. isIdenticalCompares this EJB object with the EJB object argument to determine if they are the same. removeRemoves this EJB object. These methods have the following syntax: public abstract EJBHome getEJBHome(); public abstract Handle getHandle(); public abstract Object getPrimaryKey(); public abstract boolean isIdentical(EJBObject obj); public abstract void remove(); These methods are implemented by the container (WebSphere Advanced Edition 2.0) in the EJB object class.
140
to write a description of this finder method in the <name>BeanFinderHelper interface in order to let VisualAge for Java know what to generate. We describe how to describe and generate a finder method for the Customer Bean in topic 4.9, Adding Special Finder methods on page 160.
141
With VisualAge for Java you make an association between CMP fileds and database columns by using two different browsers :
u Schema Browser and u Map Browser
With the Schema Browser you first define a schema by giving it a name (SCHEMA1). This schema must be associated to a given database (Database1). From this database you select all or a subset of tables (table1 and Table4). Then for each column you may accept or change the converter that transforms DB2 to Java data types (see Figure 79).
142
After this has been done, you use the Map Browser to associate CMP fields and columns. Once again, you need to give a name to your map (MAP1). Then you associate this map to a given schema (SCHEMA1). By doing this, the mapping possibilities are limited to those defined in the schema. You make another association between the map you are working with and a given EJB group. Then each CMP bean of this EJB group is associated to one and only one of the tables defined in the schema (CMP1 to Table 4, see Figure 80). The next operation consists in linking each field with a column in a simple or complex Map Type. In a simple Map type, a field is associated to only one column. In a complex Map Type, a field can be associated to more than one column. Figure 80 describes the relationship between the different elements and browsers involved in CMP field to column mapping.
143
The EJB Development Environment from VisualAge for Java allows top-down, bottom-up, and meet-in-the-middle mapping of EJBs to database tables. In our Customer example, we cannot use the top-down approach since WebSphere does not support primary key objects with more than one field, and we have two fields (primaryKey and lastName) in our CustomerKey class. We will use the meet-in-middle approach.
144
1. Select your EJB Group and click mouse button 2. From the popup window, select Generate->Deployed Code. This is going to generate all the classes required to execute the EJB in the WebSphere Advanced Edition 2.0 container. 2. Select the EJB Group for which you want to create the database tables. Click mouse button 2 and select Add To - Server Configuration. 3. Select your EJB Server from the Servers list and click on mouse button 2, select Properties, see Figure 81.
4. Enter the JDBC database path in the Database URL (in this version of WebSphere Advanced Edition 2.0, you cannot change the default value sampleDB). The database you specify here must exist in order to get a successful tables and fields generation. Click OK. 5. Select your EJB Server from the Servers list and click on mouse button 2, select Create Database Table from the pop-up menu. When the focus returns to the EJB Server Configuration window, your database table has been created (see Figure 82). Then, you can start your server and test it.
145
Figure 82. Characteristics of DB2 Table and Columns Created for CMP Fields
For each bean class a table is generated. In each table definition, a column is defined for each container-mapped field of the bean class. The container-managed fields are mapped as described in Table 1 on page 146. Table 1. Container-Managed fields mapping
CMP fields Java type java.lang.String short or java.lang.Short int or java.lang.Integer float or java.lang.Float double or java.lang.Double byte or java.lang.Byte long or java.lang.Long char or java.lang.Character Mapped Java type String short int float double short String String SQL Type VARCHAR(251)* SMALLINT INTEGER FLOAT DOUBLE SMALLINT VARCHAR(22) CHAR(1)
146
CMP fields Java type boolean or java.lang.Boolean java.math.BigDecimal java.sql.Date java.sql.Time java.sql.Timestamp Other
* Strings are limited to 251 characters in length due to DB2 restrictions dealing with varying length data types and their use in primary key types and certain SQL clauses. ** Non-primitive java types are stored as serialized instances in the database using BLOB data types.
147
2. define a map between the EJBs and schema using the Map Browser which is defined in topic , Defining a map between the EJBs and the database schema on page 153.
148
The Schema Browser window is divided in 5 sections: the schemas list lets you interact with schemas, the tables display a schemas tables and the columns and foreign key relationships panes are associated with a selected table. The bottom part gives some information and statistics according to what is selected in the top panes. To import our Customer Table schema: 1. Click the mouse button 2 in the Schemas list and select Import / Export Schema - Import Schema from the Database. 2. You then need to give a name to your schema, in our example we use the same name as the Customer EJB class name. Enter Customer then click OK. 3. VisualAge for Java will display the Database Connection Info dialog. Enter COM.ibm.db2.jdbc.app.DB2Driver as the connection type to tell it you want to use the IBM DB2 JDBC driver. Then enter the database JDBC name, jdbc:db2:CMPS. Your screen should now look like Figure 84, click OK.
149
4. You need to select the tables from which you want to import into. Select the CMPS then click the Build table list. You should see your CUSTOMER table in the tables list as in Figure 85. 5. Select the CUSTOMER table and click OK. The Qualifier corresponds to the schema name defined in your DB2 database.
150
6. The Schema Browser now has one table added to the Customer schema, the CUSTOMER table. If you select the Customer Schema and then the CUSTOMER table, you will see the different columns in the columns list, see Figure 86.
151
We need to change the default type converter for all Char fields to VapTrimStringConverter. If VapTrimStringConverter is not used and the default VapConverter is used with database mappings of specific lengths then there will be persistence problems. 7. Select CUSTOMER from the Tables list. Double-click on the CUSTID column to open its definition. This brings the column editor. A data type conversion must be applied between DB2 and Java types. This is the role of Converters. 8. Select VapTrimStringConverter as the converter in the Type details group. This converter performs the correct transformation between VARCHAR and other string* to java.lang.String objects with leading and trailing blanks deleted. Your window should look like Figure 87. Click OK. Repeat this process for the FNAME and LNAME columns.
9. Select Schemas - Save Schema.... Choose the ITSO Bank project and the itso.samples.ejb.CMP package. Click Finish. This create a new class named <schemaName>Schema with a single static method
152
infoString() containing information gathered by the Schema browser (see Figure 88).
153
To create a new map for your Customer schema, you need to: 1. Click the mouse button 2 in the Datastore Maps list then select New EJB Group Map from the pop-up menu. (The choice New datastore Map... should not appear when working with EJBs. In this version of VisualAge for Java only the Persistent Builder knows about models.) VisualAge for Java displays the New Datastore Map. 2. Enter CMPS for the map name, this is the name VisualAge for Java will use to save the map defined. Select ITSOEJBGroup from the EJB Group choice list and the Customer schema, which we created previously. Your window should look like Figure 90. Be sure you selected the proper EJB Group and Schema because we are not able to change them after. Click OK.
154
3. VisualAge for Java displays the newly created CMPS Datastore map in the map browser with its associated persistent class Customer. 4. A table map define the links between your EJBs and database tables. To create a new table map, click the mouse button 2 in the Table Maps list then select New Table Map - Add Table Map with no inheritance. Choose the CUSTOMER table from the combo-box (this CUSTOMER table is coming from the table associated with the Customer Database Schema) and click OK. Your screen should now look like Figure 91.
155
5. For this table map, you now need to define a property map. With this property map you tell VisualAge for Java what are the database fields the member fields of your EJB map to. Select the CUSTOMER Table Map, since we need to define its properties. Click the mouse button 2 on it and select Edit Property Maps. You see a window like Figure 92.
6. The Property Map Editor lets you define, for each of your beans members, what is the corresponding field in the database. The Class Attribute column lists all of the CMP fields of your Enterprise bean. The Table Column lists the fields from the database table. From the Map Type column you can choose 3 values: Simple: the simple mapping type is used to map one member field to one table column. We use this type in our Customer example. Complex: the complex mapping type is used when you need to map one member field to multiple database columns. The complex mapping is described in "Using Composers" from the EJB Development Environment documentation which comes with the Enterprise Update of VisualAge for Java. Not Mapped: no mapping has been defined yet for your field. Select the values according to what is shown in the Figure 93 and click OK. You have now a map defined for the CUSTOMER table.
156
7. Select the CMPS Datastore map. Select Datastore Maps - Save Datastore Map from the menu. Choose the ITSO Bank project and the itso.samples.ejb.CMP package. Be sure you selected the proper EJB Group and Schema because we are not able to change them after. Click Finish. This create a new class named <mapName>Map with a single static method infoString() containing information gathered by the Map browser (see Figure 94).
157
158
In the Bean page you can specify the following: In the Enter the JNDI name for BeanHome field, type the JNDI name to associate with the EJB in the JNDI name space. The container binds the EJB's home interface with a JNDI name that includes the name you specified. The name you specify in this field is the name that your client code provides when invoking a lookup on the initial naming context. In the Transaction Attribute drop-down box, select a transaction attribute. This attribute tells the container how to manage transaction scopes before and after the execution of the EJB method. We keep the default, TX_REQUIRED. The different transaction attributes are described in the Chapter 7, Transactions on page 211. In the Isolation Level drop-down box, select an isolation level. This level tells the container what isolation level to set on the database connections used by the EJB at the start of each transaction. Actually, WebSphere ignores this isolation level. The Chapter 7, Transactions on page 211 covers this. In the Run-As Mode drop-down box, select a run-as mode. This selection tells the container the security identity to associate with the execution of the EJB method. To learn more about security, see Chapter 8, Security on page 235. Reentrant, By default, an entity Bean instance is not re-entrant. If an instance executes a client request in a given transaction context, and another request with the same transaction context arrives at the EJB object, the container throws the java.rmi.RemoteException to the second request. This rules allows the Bean developer to program the Bean as single-threaded, non-reentrant code. Re-entrant Beans must be programmed and used with great caution. First, the Bean programmer must code the Bean with the anticipation of a loopback call. Second, since the container cannot, in general, tell a loopback from a concurrent call from a different client, the client programmer must be careful to avoid code that could lead to concurrent call in the same transaction context. Concurrent calls in the same transaction context targeted at the same EJB object are illegal, and may lead to unpredictable results. Since the container cannot, in general, distinguish between an illegal concurrent call and a legal loopback, application programmers are encouraged to avoid using loopbacks. Entity Beans that do not need callbacks can be marked as non-reentrant in the deployment descriptor, allowing the container to detect and prevent illegal concurrent calls from clients.
159
The Environment and Method pages are explained in Chapter 3, Developing a session enterprise bean on page 19. We are now ready to generate the deployment code for the Bean:
160
3. In the Create Method smart guide, enter the following declaration in the text field: public java.util.Enumeration findByLastName(java.lang.String param) and press Next. 4. From the Attributes window press Add... button. In the Exceptions window, in the Pattern (# = any character, * = any string) text field enter RemoteException, select it from the Type Names list and click Add. Repeat the same actions but in the Pattern (# = any character, * = any string) text field enter FinderException select it from the Type Names list, click Add and Close buttons. This takes you back to the Attributes window where you can check that java.rmi.RemoteException and javax.ejb.FinderException have been added. Press Finish. 5. Save your changes. 6. The findByLastName(String) method appears in the Methods list of the CustomerHome interface.
161
class contain a static String constant called findByKeySqlString. Construct your query string by copying this select statement and modifying the where clause. 1. To show the deployed generated methods. Click on the Show Generated Types icon which is beside the Field icon in Types list header. The list of generated classes appear and you can see that three classes (_CutsomerHomeSkeleton, _CustomerHomeStub and EJSCustomerHome) are marked with a cross indicating an error due to the addition of a new method in the home interface. Do not worry, the next generation of deployment code done by VisualAge for Java will fix these errors. 2. Select the EJSJDBCPersisterCustomerBean from the Types list. 3. Find the findByKeySqlString static member from the EJSJDBCPersisterCustomerBean class. Copy the SQL Select statement. 4. To hide the deployed generated methods. Click on the Show Generated Types icon which is beside the Field icon in Types list header. 5. Select the CustomerBeanFinderHelper interface from the Types list. 6. In the Source pane, paste the SQL statement from the clipboard inside the body of the method, change the method name to findByLastName:
public static final String findByLastName = "SELECT T1.CUSTID, T1.FNAME, T1.LNAME FROM CMPS.CUSTOMER T1 WHERE (T1.CUSTID = ?) AND (T1.LASTNAME = ?) ";
7. Modify the where clause from the SQL String. We want a filter on the LASTNAME only. You code should look like:
public static final String findByLastName = "SELECT T1.CUSTID, T1.FNAME, T1.LNAME FROM CMPS.CUSTOMER T1 WHERE T1.LASTNAME = ? ";
8. Save your interface. 9. Select the Customer EJB in the EJBs list and click the mouse button 2. Select Generate - Deployed code. If you recreate a Schema map later, you will first have to regenerate the code and then copy the query string from the EJSJDBCPersisterYourBeanName class. The query string is referenced by the finder implementation class generated by the deployment tool. You need to follow a few guidelines when you create special finder methods. The name part of nameQueryString must be the name of the method.
162
The number of question marks in your nameQueryString must match the number of parameters in the Finder method. When you later generate the deployment classes, the question marks in the nameQueryString are automatically replaced with the parameters defined in the Finder method. If you use the top-down approach for creating your database schemas and maps, you will not find the findByKeySqlString static member, you have to look for the loadString static member in your EJSJDBCPersisteryourName class. Copy and modify the SQL select from this member.
163
7. Go back to the EJB Server Configuration window. In the EJBs pane expand ITSOEJBGroup by clicking on the "+" sign beside the ITSOEJBGroup (see Figure 97).
164
8. Select the Customer EJB. Click mouse button 2 and select Run Test Client. You can also select Customer and click on the yellow icon . Wait to see a window like Figure 98.
165
9. Click on Connect. VisualAge for Java tries to locate the Customer EJB using the JNDI. When the object is located, VisualAge for Java displays the home interface of the Customer EJB, see Figure 99.
166
10.We want to find the Customer with the id equals to "104 " and which last name is "Picon". Click on the findByPrimaryKey(CustomerKey) from the Methods list. 11. We need to create the CustomerKey object to pass as parameter. Click on New....To know how to create the CustomerKey, refer to the Figure 100. Select the new CustomerKey(String, String) constructor, since we need to specify the key members value. Enter 104 as the parameter[0] value and Picon as the parameter[1] value. Click Send and Done.
167
12.You are now back to the Customer home interface. Click on the Send button to execute the findByPrimaryKey. After a while, VisualAge for Java returns to you with the remote interface of the Customer EJB, see Figure 101.
168
13.Select the getFirstName() method then click the Send button. VisualAge for Java returns to you with the first name of the Customer EJB previously returned by the findByPrimaryKey, see Figure 102.
14.We now want to add a new instance of Customer EJB. From the top of the test client Customer window, select in the Page combo box Home interface. Click on the Create(CustomerKey) method click on New.... Select the new CustomerKey(String, String) constructor and enter 999 in the [0] (String) parameter text field as the first parameter value and Dessureault in the [1] (String) text field as the second parameter value. Click Send and Done.
169
15.Click the Send button from the home interface. 16.The test client does not allow you to work with the newly created instance. So, you need to Exit and restart the Test client again. 17.After the TEst client is opened, press Connect. 18.In the Methods list of the Remote interface select the findByLastName(String) method enter Dessureault as the parameter value and click on the Send button see Figure 104.
170
19.The Test client Customer VisualAge for Java returns to the Remote Interface and an enumeration containing our Customer bean. You can now select getLastName() method and press Send. As a result you see (String) Dessureault. 20.Click on the Exit button to quit the Test client. Go to the EJB Server Configuration window and stop the Location Service Daemon, the Persistent Name Server and the EJB Server (server1).
171
172
173
Enterprise Javabean containers. Most containers use databases as persistence store. If you prefer storage mechanisms like flat/XML files which are supported by only a few containers its best to use Bean-managed persistence.
u If you are paranoid about the code generated by the container!
174
2. From the pop-up menu, choose Add - EJB. The Create EJB SmartGuide appears.In the Bean name field, type in the name of the new EJB (TransactionRecord).
3. From the Bean type drop-down list, select the Entity bean with Bean-managed persistence fields (BMP) item to indicate that the bean is a BMP entity.
175
4. In the Project field, type the project name, modify the default name, or click the Browse button and select the project that contains (or will contain) the EJB bean class from the list of projects, then click OK. By default, the project to which the EJB group belongs is displayed. 5. Click on Finish to create the bean. The names for the EJB home interface, remote interface, and key class (for entity EJBs only) will serve as the default names.
These fields are declared as public and are accessible via public getter methods. To add a field to the TransactionRecord bean: 1. In the Types pane of the EJB page, select the TransactionRecord bean class.
176
2. Click on the Add Field button to launch the Create Field SmartGuide.
3. Fill in the field name, type name and select the Access with getter and setter methods. 4. Select the public radio button for Getter and private for Setter. 5. Click Finish to generate the field.
177
TransactionRecord bean in the EJBs pane, the Java methods of the bean implementation class are displayed in the methods pane.
VisualAge for Java automatically creates the following methods, in addition to the getter and setter methods for the fields we defined, for a BMP entity bean:
u public void ejbActivate();
This life-cycle call-back method of the entity bean is invoked when the container assigns an instance from the pool to a specific EJB object identity. This signals the ready state for the enterprise bean. You can use this method to load additional resources in the bean.
u public TransactionRecordKey ejbCreate(TransactionRecordKey key);
VisualAge for Java generates a default ejbCreate(...) method which takes the EJB Key class, TransactionRecordKey, as a parameter. This signature matches the create(...) method of the beans home interface. You should use this method to: Validate the passed arguments Initialize the instances variables
178
Create an entry representing the entity in the persistence store Finally, you should return the primary key for the entity at the end of this method.
u public
ejbFindByPrimaryKey
VisualAge for Java creates this default finder method which uses a TransactionRecordKey object to identify a particular entity. You should do the following: Validate the client-passed arguments Locate the entity in the persistence store Refresh the state of the instance from the state in the persistence store Return the primary key at the end of the method
u public void ejbLoad();
This life-cycle call-back method is invoked on an instance in order to refresh its state. You should implement the logic to read the entity state from the persistent store and synchronize the instance variables accordingly.
u public void ejbPassivate();
The EJB container invokes this method when it decides to send the instance to the pooled state. In the pooled state, the instance is disassociated from its EJB Object identity. You can use this method to release any resources that were allocated in the ejbActivate() method.
u public void setEntityContext(EntityContext ctx);
The EJB container uses this method to pass a EntityContext reference to the Entity bean. VisualAge for Java generates the code for storing the entity context in an instance variable.
u public void ejbPostCreate(TransactionRecordKey key);
This life-cycle call back method indicates that the EJB Object identity is available. For each ejbCreate(...) method, there is a matching ejbPostCreate(...) method with the same input parameters.
u public void ejbRemove();
This method is invoked by the container when the client invokes the remove method. This ends the life of an EJB object. You should implement the logic to remove the entity from the persistence store.
u public void ejbStore();
The container invokes this method on the instance when it decides to synchronize the instances state in the persistence store with the
179
current state. You should implement the logic to update the instances state in the persistence store.
u public void unsetEntityContext(EntityContext ctx);
The container invokes this method when it wants to reduce the size of the instance pool.
Returns the amount transacted in the transaction. The amount may be negative if the transaction is a credit, positive for a debit and zero for a checking operation.
u public String getTransType();
Returns the type of transaction- "debit", "credit" or "checking" depending on the amount transacted.
180
u A create(...) method which takes the key as input u A findByPrimaryKey(...) method which takes the key as input
In this section, we will modify the create method to accept the customers account ID and the amount transacted. 1. Select the ejbCreate(...) method in the Methods pane of the EJB page. The source of this method is displayed in the Source pane. 2. Modify the method in the Source pane as below: Alter the argument list of the method to include a BigDecimal argument (to pass the amount) and a String argument (to pass the account ID). Perform any validation or null-check on the passed arguments in the body of the method. Set the amount and accountId fields of the bean to the respective arguments. Set the transId to the a Timestamp representing the current time. Return a TransactionRecordKey wrapping the transId. 3. Save the changes. 4. Add the method to the beans home interface. Next, we add a finder method (ejbFindTransactionSummary) to the TransactionRecord bean which returns an enumeration of the last 10 transactions made by a particular customer. 1. Select TransactionRecord in the Types pane. 2. Click on the Add method button. This launches the Create Method SmartGuide. 3. Specify the signature for the new public method: Set the name of the method as ejbFindTransactionSummary Set the return type as java.util.Enumeration Specify a String input argument, accountId, which identifies the customer. Specify the exceptions that this method may javax.ejb.FinderException and java.rmi.RemoteException. throw:
4. Click on the Finish button in the Create Method SmartGuide to generate the method. 5. Add the method to the beans home interface.
181
We have not as yet provided any logic to manage the persistence store as yet. In the remaining portion of the chapter we describe how an entity bean can persist itself to an XML file. We start with a brief introduction to XML and developing XML based applications with java. You can skip these portions if you know them already and directly go to Chapter 5.4, Persisting to an XML File on page 183.
HTML is the most widely used markup language for Web-based documents. As the popularity of HTML increases, the limitations of the language have become more apparent. Those limitations include restricting the user to a relatively small set of tags. HTML authors cannot create their own HTML tags, because commercially available Web browsers have no knowledge of tags that are not part of the HTML standards that the browsers support. In the XML document, the tag names convey the meaning of the data they contain. The structure of the document is easily discerned and follows a pattern. In contrast, the HTML tag names reveal little about the meaning of their content and the structure is not particularly useful for manipulating the document and exchanging it between applications.
182
by object-oriented programs (such as Web browsers, document search engines, conversion tools, business logic, and scripting languages). By using the DOM, these programs can create, navigate, manipulate, and modify the documents. The DOM can be used to represent an existing XML document or generate an XML document. The document is stored in computer memory. In the DOM, a document consists of a collection of Nodes that have parent/child relationships. The Node is the primary object and can be of different types (such as, Document, Element, Attribute, Text, Processing Instruction, CDATA Section, and Comment). The DOM Java classes are included in the XML4J parser. Point your browser to http://www.alphaWorks.ibm.com/formula/XML to download the XML4J documentation and http://www.w3c.org/DOM/ to learn more about DOM.
183
Figure 108 illustrates the mapping between the Entity bean and the XML file. Every instance of the TransactionRecord bean corresponds to a unique transaction element. All the transaction elements are nested within a root document element named transactionDB. The attribute transId and the sub-elements, amount and accountId, within the transaction element represent the fields of the TransactionRecord bean. The choice of XML as the persistence store for the bean stems from the fact that the number of TransactionRecords will be large and that this data will be used infrequently as it is only reference data. Now we will illustrate the steps involved in creating the XML file to store the Entity beans instances.
184
The map is in the form of a Document Type Definition (DTD). The DTD represents the metadata of the XML file. Creating the Document Type Definition is not important but it will help describe the mapping process between the Entity bean (TransactionRecord) and the XML file.
<!DOCTYPE transactionDB [ <!ELEMENT transactionDB (transaction)*> <!ELEMENT transaction (amount, accountId)> <!ATTLIST transaction transId ID #REQUIRED> <!ELEMENT amount (#PCDATA)> <!ATTLIST amount class CDATA "java.math.BigDecimal"> <!ELEMENT accountId (#PCDATA)> <!ATTLIST accountId class CDATA "java.lang.String"> ]>
Transaction Record
The DTD describes the hierarchy of the elements that will exist in the XML file. It has a root element transactionDB. Nested within the transactionDB element are zero or more transaction elements. Every instance of the TransactionRecord bean is represented as a transaction element. The transaction element has an attribute transId and two sub-elements, amount and accountId. The fields of the TransactionRecord are mapped as follows
u The transId field is represented as an ID attribute of the transaction
element
u The amount field is stored as text within an amount element which is a
is a child of the transaction element You could alternatively map the transId field as text within a sub-element like the other fields. We use the earlier approach due to the inherent benefit of using an ID attribute in an XML file- it does not allow duplicate attributes.
185
transactionDB
transaction
amount
accountId
666.6
SL2447
The figure shows the DOM for a TransactionRecord Log. The Element node (folder) is the root of the tree. Each of the Element nodes (transactionDB, transaction, amount and accountId) is a tag in the document. The text (data) within each tag is a Text node, represented in the figure as rectangular nodes. Attribute nodes (dashed ovals) represent attributes within tags, like the transId of the transaction. Listed below is a summary of the DOM operations. You can refer to w3cs DOM specification to get more information about the interfaces to access the DOM objects. All the classes used in the descriptions below have the package name org.w3c.dom unless explicitly stated.
186
A transId Attribute for the transaction element An amount Node for the transaction element
The accountId node can be created just like the amount node. The creation of the DTD has not been described because there is no standard API for constructing the DTD nodes. Moreover, the DTD only validates the XML document which is enforced by the Persister class.
187
The transId Attribute of the element The amount Node of the transaction element The amount data of the amount node
Removing a transaction element from the hierarchy Saving the DOM "file:/e:/ejb/Log.xml" to a file,
188
Fields
The TransactionRecordXMLPersister class contains the following significant fields:
u public String xmlLocation;
Contains the location of the XML file. This is initially null and is set to a location specified as an environment property in the deployment descriptor of the TransactionRecord bean.
u private static TransactionRecordXMLPersister persister;
The Document node of the XML files Document Object Model. Each entity bean is contained as a unique node within the document element.
Methods
In keeping with the Singleton design pattern which the Persister class uses, we define a private no-arg constructor for the class and a public static method, getPersister() , which returns the singleton persister object. We need to define the following book-keeping methods for this class:
u private void loadDocument();
This method loads the XML file specified by xmlLocation into the Document Object Model. If the specified file does not exist a new XML file is created using the XML4J parser API.
u private void saveDocument();
Saves the DOM Document, xmlDocument, into the file specified by xmlLocation.
The Persister class addresses the different stages of the Entity beans lifecycle:
u Creation-
An Instance of the Entity bean is created when its ejbCreate(...) method is invoked via its home interface. Within this method the Enitity bean initializes the fields and invokes the create method on the Persister, passing itself as an argument. The Persister then creates a sub-tree representing the state of the Entity and appends the root element of the sub-tree to the document element.
u Updation-
189
The state of the Entity bean is updated in the XML file when the container invokes the ejbStore() method on it. Within this method, the Entity bean invokes the update method on the XML file passing itself as an argument. The Persister searches for the element corresponding to the primary key of the passed Entity bean and updates the sub-tree accordingly.
u Refreshal-
The state of the Entity bean is refreshed when the container invokes the ejbLoad() method on the bean. In this method, the Entity bean invokes the refresh method on the Persister, passing itself and a primary key field as arguments. The Persister searches for the element containing the primary key field and updates the fields of the passed bean from the sub-tree of the element.
u Deletion-
The instance of a Entity bean is destroyed when its ejbRemove() method is invoked via its home interface. Within this method, the Entity bean invokes the remove method on the Persister, passing itself as an argument. The Persister searches for the element specified by the primary key field of the passes entity bean and deletes this node from its parent. We include an additional method in the Persister class, getTransactionSummary, which returns an enumeration of IDs of the last 10 transactions made by a particular customer. The Persister traverses through all the transaction elements and checks if the accountId of the transaction matches the customers account ID. The xmlLocation field is set in the setEntityContext(...) method of the TransactionRecord bean. Its value is specified by the value of the transaction.file property in the contexts environment.
190
you should set the isModified flag to true only when the beans state has been changed. Also, in the ejbLoad() and ejbStore() methods you should: 1. Check whether beans state has been modified (check if isModified is true) 2. Perform the necessary read/writes from the persistence store 3. Set the isModified flag to false Now, when a remote method is invoked on the bean, the container calls the ejbLoad and the ejbStore methods before and after the method which first checks whether a read/write to the persistence store is required. The isModified flag must be set to true in the following methods:
u ejbActivate u ejbPassivate u setEntityContext u ejbRemove u Any business method which alters the beans state
You should unset the isModified flag (set it to false) at the end of the ejbLoad, ejbStore and ejbPostCreate methods.
191
3. In the Environment page of the Properties dialog, set transaction.file property along with the location of the XML file.
the
192
afterCompletion. The EJB 1.0 Specification has restricted the usage of this interface only to Session beans and although Websphere allows its use in Entity beans this approach is non-standard and may not work on other servers.
193
194
6 Naming Services
A fundamental facility in any organized system is the means by which objects are found given their names. This is the role provided by a Naming Service. Many naming services are extended with a directory service. While a naming service allows you to look up an object given its name, a directory service also allows such objects to have attributes. Therefore, in addition to lookup, you can also get an objects attributes or search for objects given their attributes. Java Naming and Directory Interface (JNDI) is an API specified in the Java programming language that provides directory and naming functionality to Java applications. It is defined to be independent of any specific directory service implementation giving access to new and existing directories through a common way. The JNDI Service Provider Interface (SPI) provides the means by which different directories can be made accessible from application using JNDI. Figure 112 shows how the different components relate to each other.
195
By using the JNDI API an application can get access to an initial context. From this initial context it can navigate through a naming tree composed of sub-contexts to which are attached atomic name bound to object reference. This naming tree can represent a complexe system including:
u naming system.
It is a name that spans multiple naming systems. As a result, a composite name can be made up of different parts belonging to different name spaces: DNS and a file system name space for example. The JNDI is divided into three packages:
u javax.naming
This package contains classes and interfaces for accessing naming services.
u javax.naming.directory
This package extends the javax.naming package to provide functionality for accessing directory services in addition to naming services. This package allows applications to retrieve attributes associated with objects
196
stored in the directory and to search for objects using specified attributes. WebSphere Advanced Edition 2.0 supports naming only.
u javax.naming.spi
This package provides the means by which naming/directory service providers can develop and hook up their implementations so that the corresponding services are accessible from applications that use the JNDI. From this high level view of what a JNDI implementation can support, let us see what has been made available to us in WebSphere Advanced Edition 2.0.
Naming Services
197
Even though different Enterprise JavaBeans servers could be running in different hosts, it is recommend to keep all EJB servers and the Persistent Name Server in the same host. Enterprise JavaBeans servers register EJBs with one and only one Persistent Name Server. If more than one Persistent Name Server exist in the network each one maintains an independent name space.
198
EJB Server
Enterprise JavaBeans are deployed and executed in an EJB server. When started, an EJB server automatically registers EJB Home objects into the naming tree. To be able to perform this operation, an EJB server is given at startup the Location Server Daemons hostname and port number. In this way it can retrieve the naming trees root initial context and bind EJB home objects with their JNDI names into the name tree.
Naming Services
199
public JpPing create() { JpPingHome pingHome = null; javax.naming.InitialContext initContext = null; // Get the initial context try { String ProviderURL = "iiop://" + EJSHostName + ":" + EJSPort; java.util.Properties properties = new java.util.Properties(); properties.put(javax.naming.Context.PROVIDER_URL, ProviderURL); // IBM name services properties.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.ibm.jndi.CosNaming.CNInitialContextFactory"); initContext = new javax.naming.InitialContext(properties); } catch (javax.naming.NamingException e) { System.out.println("Error retrieving the initial context: " + e.getMessage()); } // endtry Figure 114. Creating the InitialContext Object
or
u "anyServerName.ibm.com" which is the fully qualified host name
cannot be changed.
u "9019" if the EJB server is running inside WebSphere Advanced Edition
2.0 runtime. This value is configurable from the WebSphere Advanced Edition 2.0 Application Server Administration by selecting in the left pane WebSphere Application Server->Enterprise Java Services->Global Settings and changing the Boot Port value as shown in Figure 115.
200
Figure 115. Changing the Boot Port Value in WebSphere Advanced Edition 2.0
Once the InitialContext object is created, the application uses it to create the EJB home object, as shown in Figure 116.
Naming Services
201
// lookup the home interface using the JNDI name try { java.lang.Object o = initContext.lookup(JNDIBeanName); // this is the JNDI name if (o instanceof org.omg.CORBA.Object) pingHome = JpPingHomeHelper.narrow((org.omg.CORBA.Object) o); } catch (javax.naming.NamingException e) { System.out.println("Error retrieving the home interface: " + e.getMessage()); System.exit(0); } // endtry Figure 116. Creating the EJBHome object
This creation is accomplished by invoking the lookup method which takes the JNDI name of the enterprise bean in String form and returns a java.lang.Object object. An EJB JNDI name can be modified. You change it, inside VisualAge for Java, by opening the EJB properties and changing the value in Enter the JNDI name for BeanHome field see Figure 117.
202
Figure 117. Changing the JNDI Name under VisualAge for Java
Outside VisualAge for Java you use the WebSphere Advanced Edition 2.0s Jet tool to read the exported Jar file containing EJBs. You start the Jet tool by running drive:\WeBSphere\AppServer\sample\ejs\jet.bat command file. In the Input/Output tab, select Browse followed by the Jar file containing your EJB. According to the type of bean session or entity, the Jet tool highlights the corresponding tab. By selecting the tab, you get access to the deployment descriptor information see Figure 118.
Naming Services
203
Once you have changed the JNDI name you select Input/Output tab and enter in the Output field the path and name of a new or the same Jar file to be created or modified and then press Build button. This updates the deployment descriptor serialized file with the new JNDI name. The returned object of the lookup operation is filtered, using the static method narrow, to obtain an EJBHome object for the specified enterprise bean. The narrow method is contained in the home helper class generated during bean deployment. For the JpPing bean, this home helper class is named JpPingHelper.
204
Once a reference to the home object has been obtained, you use it to create the EJB object by using the EJB home object as shown in the following snippet of code (see Figure 119).
JpPing ping = null; try { ping = pingHome.create(); System.out.println("JpPing created!"); } catch (Exception e) { System.out.println("Exception creating new JpPing: " + e.getMessage()); } Figure 119. Creating the EJB Object
The EJB object is obtained by calling a create method or (for entity beans only) a finder method. Because the JpPing bean is a stateless session bean, the only choice is the default create method.
Naming Services
205
To make this change, from the workbench, select the EJBs tab, in the menu select EJBs->Open To->server Configuration as indicated in Figure 121.
This opens the EJB Server Configuration window as shown in Figure 122.
206
In the Servers pane, select Persistent Name Server click mouse 2 and select Properties. This opens the Properties for Persistent Name Server window shown in Figure 123 giving access to three parameters:
Naming Services
207
This is the host name where the Location Server Daemon is running. The LSD Name is by default set to localhost and needs to be set to the fully qualified IP host name.
u LSD Port
This is the port name on which the Location Server Daemon is listening. It must match the value defined during Location Server Daemon configuration. You also need to configure the EJB server. Follow the same steps to get access to its properties.
208
Once you have changed the localhost by the fully qualified host name in the two servers, you can start all three servers: Location Server Daemon, Persistent Name Server and the EJB server. Now your client running on a different machine can get access to the EJB running inside VisualAge for Java as long as it uses the correct fully qualified name and port number (see Figure 114 on page 200).
Naming Services
209
210
7 Transactions
Nowadays, we see a lot of developpers are centralizing their business code inside objects running on a central application server. This centralization of components give more control over the application logic to these developpers. The applications developped using this kind of architecture are easier to scale as well (via things like: load balacing, database multiplexing). In the traditional procedural approach, developpers are using transactions to achieve a high degree of application integrity. A transaction is described by four properties: Atomic: transactions are all or nothing, they either work or they dont, they are never left incomplete. Consistent: transactions always let the system in a consistent state. Isolated: transactions executes in a safe manner, they will not fail if other transactions running on the same server are failing. Durable: transactions can survive system failures once they are completed and committed. The transactional application servers combine the execution of component centralized on application servers with transactionality.
211
212
The EJB Specifications describe different scenarios using transactions. We decided to illustrate the Bean-managed demarcation and the Container-managed demarcation. The client-demarcated transactions are explained in the topic 7.8, Client-demarcated transactions on page 230. We were not able to test the following scenarios, because they are not supported by the WebSphere environment: 1. the update of multiple databases via one server 2. the update of databases via multiple servers
Transactions
213
context is passed to any enterprise Bean objects or resources that are used by this Bean method. TX_NOT_SUPPORTEDDirects the container to invoke Bean methods without a transaction context. If a client invokes a Bean method from within a transaction context, the container suspends the association between the transaction and the current thread before invoking the method on the enterprise Bean instance. The container then resumes the suspended association when the method invocation returns. The suspended transaction context is not passed to any enterprise Bean objects or resources that are used by this Bean method. TX_REQUIRES_NEWDirects the container to always invoke the Bean method within a new transaction context, regardless of whether the client invokes the method within or without a transaction context. The transaction context is passed to any enterprise Bean objects or resources that are used by this Bean method. TX_REQUIREDDirects the container to invoke the Bean method within a transaction context. If a client invokes a Bean method from within a transaction context, the container invokes the Bean method within the client transaction context. If a client invokes a Bean method without a transaction context, the container creates a new transaction context and invokes the Bean method from within that context. The transaction context is passed to any enterprise Bean objects or resources that are used by this Bean method. TX_SUPPORTSDirects the container to invoke the Bean method within a transaction context if the client invokes the Bean method within a transaction. If the client invokes the Bean method without a transaction context, the container invokes the Bean method without a transaction context. The transaction context is passed to any enterprise Bean objects or resources that are used by this Bean method.
214
Phantom reads, where one transaction reads all rows that satisfy an SQL WHERE condition, a second transaction inserts a row that also satisfies the WHERE condition, and the first transaction applies the same WHERE condition and gets the row inserted by the second transaction. TRANSACTION_REPEATABLE_READThis level prohibits dirty reads and nonrepeatable reads, but it allows phantom reads. TRANSACTION_READ_COMMITTEDThis level prohibits dirty reads, but allows nonrepeatable reads and phantom reads. TRANSACTION_READ_UNCOMMITTEDThis level allows dirty reads, nonrepeatable reads, and phantom reads. These isolation levels correspond to the isolation levels defined in the Java Database Connectivity (JDBC) java.sql.Connector interface. The container uses the transaction isolation level attribute as follows: Session Beans and entity Beans with Bean-managed persistence (BMP)For each database connection used by the Bean, the container sets the transaction isolation level at the start of each transaction. Entity Beans with container-managed persistence (CMP)The containergenerates database access that achieve the specified isolation level.ion and gets the row inserted by the second transaction. Actually WebSphere does not support these isolation levels and will, in the presence of transactions, always open a database connection with the TRANSACTION_REPEATABLE_READ isolation level.
Transactions
215
The Control object represents the transaction. From this object we can obtain the Coordinator and the Terminator. An EJB developer never sees the Control object. It is used by the container to manage the transaction on behalf of the bean. The Terminator is also used by the container to commit or roll back the transaction when a thread returns from a bean method where the method is described in the deployment descriptor as requiring the container to terminate the transaction upon completion of the method. When a commit or rollback is requested, all the objects in the transaction will be committed or rolled back, as appropriate. The Resource is the object that has transactional state. For example, it may be a connection to a database. Calling commit() on this object would cause the database updates to be applied to the database. A rollback() would revert all changed made to the database through this connection since the start of the transaction. Once the commit or rollback completed, the corresponding rows in the database would be unlocked. The level of locking applied would have been specified in the deployment descriptor. The full set of methods for this object would show that these objects actually implement the two-phase commit protocol, allowing each object to vote as to whether the entire transaction should be committed or rolled back. The Synchronization is an object that wishes to be notified upon completion of the transaction whether the transaction was committed or rolled back. Unlike the Resource,
216
it does not participate in the two-phase commit protocol and has no vote as to whether the EJB. transaction should be committed or rolled back. It plays a passive role in the transaction. This is the role that a session bean may play by implementing a special interface. The Coordinator is the object that makes all this work. Through this object both Resource objects and Synchronization objects are registered in the transaction. The bean does not get access to this object directly. Transaction-aware objects that are intended for use with EJB will transparently obtain a reference to the current transactions Coordinator to register itself.
Transactions
217
The afterBegin notification signals a session instance that a new transaction has begun. At this point, the instance is already in the transaction and may do any database work it requires within the scope of the transaction. The beforeCompletion notification is issued when a session instances client has completed work on its current transaction but prior to committing the instances resources. This is the time when the instance should write out any database updates it has cached. The instance can cause the transaction to rollback by invoking the setRollbackOnly method on its session context. The afterCompletion notification signals that the current transaction has completed. A completion status of true indicates the transaction committed; a status of false indicates a rollback occurred. In WebSphere Advanced Edition 2.0 the entity bean implementation class can implement the SessionSynchronization interface so they can also be notified when a new transaction begins or completes. We used this in our scenario testing, since we needed to know how many transactions were involved in the test cases. Each time the afterBegin method was called in one of our Beans we printed something to the console, this way we were able to know how many transactions were started by the transaction service. Please note that we do not recommend to implement the javax.ejb.SessionSynchronization for Entity beans. This is not portable across different EJB Container vendors.
7.4 Scenarios
Scenario Description
Our design model to test the effect the transactions attributes has 4 components: one Session Bean (TransactionTest), 2 Container-managed persistence Entity Beans (CMPSample1 and CMPSample2) and one client application (SimpleClient). One scenario consist of setting the transaction attributes of the CMP Beans and run the SimpleClient Java application. The SimpleClient creates a myTransactionTest session Bean. The client application then calls 3 method on this SessionBean: test1(), test2() and test3(), see Figure 127 on page 219.
218
The myTransaction.test1() and myTransaction.test2() represent our implementation of the Bean demarcated transaction model. They show the effect of the transaction attributes within the Bean demarcated transaction model. The myTransaction.test1() execute a committed transaction, see Figure 128.
Transactions
219
The myTransaction.test2() represents the rollbacked transaction, see Figure 129 on page 221.
220
The last method the SimpleClient application calls is test3() . This method illustrates the effect of the transaction attributes within the Container-demarcated transaction model. All the transaction processing is handled by the container, see Figure 130 on page 222.
Transactions
221
222
myTransactionTest.test1()
The myTransactionTest.test1() starts by obtaining CMPSample1 home interface. The myTransaction then gets a transaction, myTransaction, from the SessionContext object. MyTransactionTest initiates the transaction with a myTransaction.begin( ) (the control of transactions from our myTransactionTest EJB forced us to specify its transaction attribute as TX_BEAN_MANAGED). Our myTransaction Bean then ask 2 values from the user: a key and a state (both strings). It creates a primary key object for CMPSample1 and tries to find using this key object. If the myTransactionTest bean does not find the CMPSample1 bean, it calls create with the key object. The CMPSample1.setState() method is called with the previously entered state as parameter. This CMPSample1.setState() method set the value of the state member of our CMPSample1 Entity Bean. Following this, the CMPSample1 Bean asks for other values (key and state) from the user and tries to find an instance of CMPSample2. If the CMPSample1 bean doesnt find it creates an instance of the CMPSample2 bean and then call the CMPSample2.setState( ) method. To complete, the myTransactionTest myTransaction.commit( ). commits the myTransaction using:
myTransaction.test2( )
The myTransaction.test2() is the second method the SimpleClient application calls. The test2() method behaves like the test1() with a few differences. The CMPSample1 Bean does not need to get the transaction object from the SessionContext, it has already be initialized in the test1() method. The myTransaction object does not commit the changes to the database, it rollbacks them with the myTransaction.rollback( ) call.
myTransaction.test3( )
The last method the SimpleClient application calls is test3(). It does the same steps as test1( ) but without the transaction related actions. The MyTranasctionTest doesnt begin a transaction. The MyTransactionTest doesnt commit nor rollback.
Transactions
223
Result tables
For CMPSample1 and CMPSample2: Table 4. Scenario 1 - TX_REQUIRED
Method called test1( ) Result in Database Data inserted and updated in both tables No Data updated inserted or Comments Only one transaction is used during this scenario, the transaction started from the myTransactioTest session bean. Only one transaction is used during this scenario, the transaction started from the myTransactioTest session bean.
test2( )
224
Comments Only one transaction is used during this scenario, the transaction started by the container after the CMPSample1.setState() method call and is carried on to the CMPSample2 Bean..
test2( )
No Data updated.
inserted
or
test3( )
a. this strange results are described in the topic , Test scenarios results explanation on page 226. b. this strange results are described in the topic , Test scenarios results explanation on page 226. c. this strange results are described in the topic , Test scenarios results explanation on page 226.
Transactions
225
test2( )
Not applicable
226
In the case of the presence of a transaction context, your Bean is not isolated from a clients rollback. This means if the client (either application, servlet or Bean) decides to rollback the transaction, the changes in your bean will be rollbacked as well. If no transaction is available (like in myTransactionTest.test3( )), the container will get one from the transaction service and provide it to the Bean, before any methods are invoked on it. The execution of the myTransactionTest.test3() made us realized something regarding the way our container modeled the transaction control. Our container, WebSphere Advanced Edition 2.0 forces all methods from the home to be called within a transaction context. This means all the finder and create methods will be executed transactionally. WebSphere Application Server 3.0 will make the Home interfaces EJBs, so it will be possible to describe the type of transaction attribute you need on specific finder in their deployment descriptor.
Transactions
227
In our rollback situation method (myTransactionTest.test2()) WebSphere sent the com.ibm.ejs.container.ContainerObjectNotFoundException. This is a bug we had with WebSphere Advanced Edition 2.0.
228
lock is placed on the active instance for the duration of the transaction. This exclusive lock avoids a common deadlock that can occur as multiple transactions access multiple beans.
Transactions
229
230
committed or aborted. To obtain a reference to the org.omg.CosTransactions.Current interface, the client application may simply call the static getCurrent method on the com.ibm.ejs.client.EJClient class. For example,
org.omg.CosTransactions.Current current = com.ibm.ejs.client.EJClient.getCurrent(); current.begin(); // do transactional work current.commit(false);
Note: To ensure that the transactions created using the current interface are propagated as method invocations are made on enterprise JavaBeans, the current reference should be obtained before creating a JNDI InitialContext. For portability of client applications across different EJB implementations, developers may wish to program their clients using the javax.jts.UserTransaction interface. The following simple class implements the javax.jts.UserTransaction interface using the CosTransactions.Current interface:
package myPackage; import org.omg.CosTransactions.*; public final class UserTransaction implements javax.jts.UserTransaction { Current current = null; public UserTransaction() { current = com.ibm.ejs.client.EJClient.getCurrent(); } public void begin() throws IllegalStateException { try { current.begin(); } catch (SubtransactionsUnavailable e) { throw new IllegalStateException(e.toString()); } } public void commit() throws IllegalStateException, javax.jts.HeuristicRollbackException, SecurityException, javax.jts.TransactionRolledbackException, javax.jts.HeuristicMixedException { try { current.commit(true); } catch (org.omg.CosTransactions.NoTransaction nte) { throw new IllegalStateException("No transaction."); } catch (org.omg.CosTransactions.HeuristicMixed hme) {
Transactions
231
throw new javax.jts.HeuristicMixedException(); } catch (org.omg.CosTransactions.HeuristicHazard hze) { throw new javax.jts.HeuristicRollbackException(); } } public int getStatus() { Status stat = current.get_status(); if (stat == Status.StatusActive) return javax.jts.UserTransaction.STATUS_ACTIVE; if (stat == Status.StatusCommitted) return javax.jts.UserTransaction.STATUS_COMMITTED; if (stat == Status.StatusCommitting) return javax.jts.UserTransaction.STATUS_COMMITTING; if (stat == Status.StatusMarkedRollback) return javax.jts.UserTransaction.STATUS_MARKED_ROLLBACK; if (stat == Status.StatusNoTransaction) return javax.jts.UserTransaction.STATUS_NO_TRANSACTION; if (stat == Status.StatusPrepared) return javax.jts.UserTransaction.STATUS_PREPARED; if (stat == Status.StatusPreparing) return javax.jts.UserTransaction.STATUS_PREPARING; if (stat == Status.StatusRolledBack) return javax.jts.UserTransaction.STATUS_ROLLEDBACK; if (stat == Status.StatusRollingBack) return javax.jts.UserTransaction.STATUS_ROLLING_BACK; return javax.jts.UserTransaction.STATUS_UNKNOWN; } public void rollback() throws IllegalStateException, SecurityException { try { current.rollback(); } catch (NoTransaction nt) { throw new IllegalStateException("No Transaction."); } } public void setRollbackOnly() throws IllegalStateException { try { current.rollback_only(); } catch (NoTransaction ne) { throw new IllegalStateException("No Transaction."); } } public void setTransactionTimeout(int seconds) { current.set_timeout(seconds); } }
232
Client-demarcated transactions have disadvantages over the container-demarcated transactions. You do not control the period of time the client will use your Beans within a transaction context. This means you can waste precious server resources. For example, a client starts a transaction query an EJB, leave for the weekend. The client transaction will be active for all the weekend. Your server resources are then tied up for all this period. When you use client-demarcated transactions, you lose the flexibility to let the deployer adjust the transaction attribute as well. This means all your Beans are TX_BEAN_MANAGED and cant be tailored on depending on the deployment servers. It is generally, a good practice to specify your transactional Beans as TX_REQUIRED because they are executed whitin a transactional context.
7.9 Conclusion
Enterprise JavaBeans simplifies the developpers tasks with component transactionality as we saw in this chapter. Although, the Enterprise JavaBeans Specifications are lacking definition details and are not explaining the nature of the technology for important things such as: thread pooling concurrency control resource management. These details are left to the different EJB Server vendors. This can result into proprietary EJB solutions, meaning less portable. These technological issues should be addressed in the Enterprise JavaBeans specifications if we want to keep one of their goal: platform independence and portability.
Transactions
233
234
8 Security
The Internet has exposed distributed applications to possible malicious users. This has necessitated security management in these applications to ward off threats by hackers and virus attacks. The security feature of the Java language and the Virtual Machine (VM) along with the EJB specification address many of the security concerns. Enough literature is already available about the security features of the Java language and the VM. This chapter will delve only in the security features specific to EJB.
235
Deploying an application on the Internet provides it access to audiences who could misuse it. It is necessary, therefore, for these applications to identify a priveleged user and to grant access only on a successful authentication.
Groups
Groups are sets of users. Groups provide an efficient way to manage large numbers of users because an administrator can specify permissions for an entire group at one time.
236
Usually, group members have something in common. For example, a company might have one group for managers and another for non-managerial employees. It may be that non-managers are given access to view sales data files, and managers are allowed both to view and to edit the sales data files. A person can be defined as both an individual user and as a member of a group. For example, the person Amy might be represented both as individual user amy and as a member of the group managers. When an individual user also belongs to a group, the individual access permissions override any group access permissions.
Resources
Resources are the valuable items accessible by your Web server:
u HTML files and directories, such as http://www.anycompany.com (Web
pages)
u Other files and directories, such as ftp://www.anycompany.com u Web applications: Java servlets or CGI programs
servlets
u Custom
servlets that enable access to enterprise resources and applications (such as databases)
Note
In the current release of WebSphere Advanced Edition 2.0 you cannot specify an EJB as a resource. Each resource can be protected by establishing a single access control list (ACL) for that resource, in a single realm (discussed below). The ACL specifies which users or groups are allowed to access or modify the resource. For each resource to protect, youll specify:
u An access control list (ACL) - a list defining who can use the resource u A security realm - a logical security area the resource belongs to u An authentication scheme - a way to verify users who ask for the resource
Security
237
The relationship among these items will more become apparent later in this discussion.
Permissions
Permissions represent the privileges required for accessing resources. An administrator protects resources by establishing access control lists to grant permissions to users and groups. Application Server lets you set a variety of permissions. For example, there are permissions to send and receive files, delete files, read and write files, load servlets, link to libraries, open and listen on sockets, and more. For descriptions of the available permissions, view the field help for the Access Control Lists page, the Manager page for setting permissions. Individual user permissions take precedence over group permissions. For example, if the user amy has both read and write access to a file, but the group amy belongs to has only read access to the file, amy remains able to read and write to the file because the individual user permission overrides the more restrictive group permission. (Even if the group permission is less restrictive than the user permission, the user permission overrides the group permission). Permissions are related to specific resources. Suppose a user has permission to view FileA and has permission to modify FileB. The users permission to modify FileB does not allow the user to modify FileA. Each permission applies to a particular resource and is nontransferable.
Realms
A realm is a database of users, groups, and access control lists. A user must be defined in a realm in order to access any resources belonging to that realm. A user can belong to several realms, but a user ID cannot be duplicated within a realm. For example, the user amy can belong to the realms fileRealm and anyRealm. Each of those realms can contain only one user named amy. The user amy can be given different permissions for different resources in each realm. A person, such as Kilroy, might have different user IDs in each realm. For example, he might be kilroy in the fileRealm, but is kilroy2 in the anyRealm because there is already a person in anyRealm using the user ID kilroy. Realms the Application Server ships with IBM WebSphere Application Server ships with some pre-established realms:
238
locally. You can establish access control lists (discussed shortly) to determine which users and groups have access to which resources.
u The UNIX or NT realm is named for your operating system and defines
how users with accounts on the system the server is running on may access Application Server resources. Users and groups defined in the underlying system are shared by the IBM WebSphere Application Server, and continue to exist for as long as they exist in the underlying system. The Application Server Manager interface lets you view this realm; to change it, you must use the facilities provided by your operating system.
u The servletMgrRealm defines how servlets may access resources
defined remotely, such as remotely loaded servlets. The servletACL is the only access control list in this realm. When a remotely loaded, digitally-signed servlet tries to access a protected resource, the digital certificate in the servlet is compared with digital certificates associated with users in the servletMgrRealm. The servletACL decides whether permission is granted or denied. For example, suppose the digital certificate of userX is packaged in the anyServlet..JAR file. If userX is added to the servletMgrRealm, any servlet containing the same digital certificate as that of userX (found in anyServlet..JAR) may execute and access resources granted to userX.
u Finally, the LDAPRealm will be displayed if you have enabled a
directory service on the Directory Management page of the Application Server Manager. Users and groups defined in the directory service are shared by Application Server, and continue to exist for as long as they exist in the directory service or until you disable directory management support. The Application Server Manager interface lets you view this realm; to change it, you must use the facilities the LDAP server provides.
Security
239
In some cases, a service does not require its customers to be in an access control list. For example, many Web page (HTTP) services make their documents available to all users without requiring them to register in an access control list (ACL).
protocol. HTTPS is preferable to HTTP, unless you are operating in an already secure environment (or lack security concerns) and seek to avoid the overhead related to using HTTPS.
240
u Certificate
Certificate authentication requires HTTPS; the other schemes can use either HTTP or HTTPS. An authentication protocol defines how authentication information (such as a user ID and password) is exchanged. IBM WebSphere Application Server requires clients to authenticate themselves to the server when requesting protected resources. IBM WebSphere Application Server supports:
u Basic authentication
Uses HTTP or HTTPS to request a user name and password from the client. The information is sent to the server in plain text for verification. All browsers support basic authentication. Consider using it if a user id and password provide sufficient authentication.
u Digest authentication
Uses HTTP or HTTPS to request a user name and password from the client. The user name and an encrypted form of the password (using a digest) are sent to the server for verification. Not all browsers support digest authentication. (Currently, only the Sun HotJava browser supports it). If a browser does not support digest authentication, its user cannot access the resources protected with this protocol.
u Custom authentication
Uses HTTP or HTTPS to request client information using a customized HTML form. The information is sent in plain text to the server for verification by a CGI or servlet. Use custom authentication when you need user authentication other than an id and password. For example, you can request a social security number from the user for authentication. With this protocol, you establish HTML forms to ask the user for data. Authentication is performed by server-side code (CGIs and servlets), not by the IBM WebSphere Application Server runtime application. If you use custom authentication, use HTTPS to protect the data.
u Certificate authentication
Uses HTTPS to request a client certificate. The SSL client authentication option must be enabled. The information is sent to the server for verification.
Security
241
Authentication using digital certificates is highly secure, and certificate authentication is often transparent to the user. The system or site administrator manages the client certificates. Often the task is delegated to certificate authority server software, such as the IBM Vault Registry product.
HTTPS
u For maximum security, use Certificate authentication over HTTPS
242
Part 2
243
244
245
As you can see in Figure 132, internet users get access to the bank application through an HTTP server using servlets and JSPs pages. Servlets and JSPs pages deal with a session bean UserSB which implements all use cases. In a real environment, each use case could be mapped on individual session bean. This would allow the deployer to distribute session beans on different machines and provide better scalability. For each use case, UserSB session bean retrieves and invokes business methods on entity beans. These same entity beans can also be accessed by the AdminSB session bean implementing the use cases for administration purpose. The AdminSB implements use cases to create, remove bank accounts, customers. This type of activity could also be done through the Internet using JSP pages but seems more suitable for a Java based application taking advantage of the higher bandwidth generally available on an intranet network.
246
The Bank application entity beans are implemented as Container-managed persistence enterprise beans and have their persistent state managed by the container using the ITSOBANK database. In the following chapters, we describe how we have implemented the bank application. We do not describe how to create the client applications in this book. If you want to learn more you can refer to SG24-5423 book which addresses this part of the application. It is based on the same home banking application. Now we can continue by looking to the home banking applications class diagram.
247
These classes are connected in different ways. A customer has a 1 to many relationship with a BankAccount. A BankAccount can be derived in CorporateAccount, SavingAccount or CheckingAccount. By introducing in the application basic object oriented concepts like aggregation and inheritance we put ourselves face to face with some of the
248
current Enterprise JavaBeans specification limitations. It does not yet addresses these problems and the tools do not yet provide help either. Because we believe that readers of this book will expect to find some guidance in solving these problems, we have investigated and propose a way to implement inheritance and aggregation. The solutions used in this book to solve these very difficult problems are described in the following chapters: Chapter 10, Relationships on page 251 and Chapter 11, Inheritance on page 265.
249
250
10 Relationships
10.1 Problem description
As we have already mentionned, the Enterprise JavaBeans specification 1.0 does not define how associations must be supported. The current version 2.1 of VisualAge for Java does not support EJB associations either. To be able to build the one-to-many relationships in our banking application, we developed a relation package (itso.bank.ejb.relation) which wraps the association complexity.
251
Class ManyLink implements the multi-value association end. Depending on the relation type parameter in the constructor, ManyLink supports an aggregation association (the parent controls the live cycles of its children) or a normal association. Class SingleLink is the single-valued inverse association end of the one-to-many relationship.
Mutators (set-methods) and collection add/remove methods automatically invoke the appropriate referential integrity maintenance behavior, such as updating the inverse association end. For aggregation associations the operations performed on the associations owner are cascaded to the member objects. For example, deletion of the associations owner object causes the member objects to be deleted: bank.remove() causes customer.remove(). Also when a member object is removed from the association the member is deleted: bank.removeCustomer(customer) causes customer.remove().
u Retrieving the member(s) at the other association end
state of the link to "uninitialized" in the ejbLoad() method of the entity bean.
u invoking the appropriate link methods [ManyLink.removeAllMembers() /
(Properties pane)
252
Design Considerations
In this section we describe the design considerations for the one-to-many relationship implementation (aggregation or normal association)
u Persistent association technique
There are different techniques to implement persistent association. Our implementation depends on storing and retrieving primary or foreign key values in the database.
u Usability
Our solution hides the association complexity in link classes. Entity beans delegate the relationship maintenance and members retrieval to the relation package. Two link objects are involved in each one-to-many relationship: at the multi-valued association end the entity bean owns a ManyLink object, the entity bean at the single-valued association end has a SingleLink object. A link object gets the association-relevant parameters from the entity at creation time (for example: relationship type [aggregation or normal association], role of the class, name of the primary / foreign key). To be able to retrieve and maintain the association members, the link objects use introspection (java. reflect package). The link objects invokes the appropriate EJB homes to retrieve the member(s). Example : The SingleLink object in a CustomerBean entity invokes bankHome.findByPrimaryKey(bankId) to get the bank reference of a customer. CustomerBean has a public instance variable which represents the bank foreign key in the customer object. SingleLink gets the foreign key value from its entity and passes the value in the findbyPrimaryKey call. The ManyLink object in a BankBean invokes customerHome.findByBankId(bankId) to retrieve the customers of a bank and gets the parameter value from its entity key object (BankKey). The SingleLink object updates the foreign key instance variable of its entity. Making the foreign key value persistent is the responsibility of the EJB container (CMP entity) or the bean (BMP entity). The relation package supports CMP and BMP entities.
u Database design
Relationships
253
are explicitly mapped to the primary-key/foreign-key relationships defined in the relational database. One-to-many relationships are mapped to backward pointing foreign-key reference (the child table refers to the parent table). Example: To map the one-to-many relationship between Bank and Customer the Customer table has a foreign key field (bankId) which points to the primary key field of the Bank table.
u Introspection
A link object gets the association-relevant parameters (for example : relationship type, role, name of primary / foreign key) at run time (constructor parameters). To be able to retrieve the members and maintain the associations, the link objects are working with introspection (package java. reflect).
u EJB server compatibility
We have tested the relation package with WebSphere 2.0 Advanced. We expect that our solution runs on other EJB servers supporting relational database persistence.
Naming conventions
In this section we describe itso.bank.ejb.relation package. the naming conventions of the
254
Accessor methods
The user of the itso.bank.ejb.relation package has to define the accessor methods in the bean class and the Remote Interface. The naming rules for the multi-valued association end of a one-to-many relationship are :
u public void add<inverseRole>(EJBRemoteType) u public void remove<inverseRole>(EJBRemoteType) u public Enumeration get<inverseRole>s()
The <inverseRole> indicates the role played by the entity bean at the other end of the association. It is a parameter in the constructor of the ManyLink class and has to correspond to the Remote Interface name of the inverse entity bean. Each of the methods throws java.rmi.RemoteException. For the BankBean class we define the accessor methods :
u public void addCustomer(Customer) throws RemoteException u public void removeCustomer(Customer) throws RemoteException u public Enumeration getCustomers() throws RemoteException
The naming rules for the single-valued inverse association end are :
u public void set<inverseRole>(EJBRemoteType) Note : If the one-to-many association is an aggregation, no set method is needed. The parent reference has to be passed in the ejbcreate( ...) and ejbPostCreate( ... ) methods of the child entity bean. The association type is a parameter in the constructor of the ManyLink class owned by the entity bean at the other end of the association. u public void get<inverseRole>()
The <inverseRole> indicates the role played by the entity bean at the other end of the association. It is a parameter in the constructor of the SingleLink class and has to correspond to the Remote Interface name of the bean. Each methods throws java.rmi.RemoteException. The Bank - Customer relationship is an aggregation. For the CustomerBean class we define :
u public void getBank() throws RemoteException u public void ejbCreate(CustomerKey customerKey, Bank parent, ...)
throws RemoteException
u public void ejbPostCreate(CustomerKey customerKey, Bank parent, ...)
throws RemoteException
Relationships
255
The current implementation of the itso.bank.ejb.relation package supports bean key classes with one instance variable (no compound keys allowed). The instance variable has to be public.
u Bank interface u BankHome interface
We lazy initialize the link object when it is used for the first time.
private ManyLink getCustomerLink() throws java.rmi.RemoteException { if (customerLink == null) customerLink = new ManyLink(this, "Customer", "itso.bank", "findByBankId", "primaryKey", ManyLink.AGGREGATION); return customerLink; } u Retrieving the customers public Enumeration getCustomers() throws RemoteException { return getCustomerLink().getMembers();
256
} u Adding a customer
The method is called from the SingleLink object owned by the entity of the other end of the association when a new customer is created.
public void addCustomer(Customer customer) throws java.rmi.RemoteException { getCustomerLink().addMember(customer); } u Removing a customer
The ManyLink object removes the relationship. Because we defined the association as an aggregation (constructor of ManyLink) the link object deletes the customer (child of the aggregate).
public void removeCustomer(Customer customer) throws java.rmi.RemoteException { getCustomerLink().removeMember(customer); } Note : customer.remove() gives the same result. u Maintaining the life cycle state of the the link object
The ejbLoad() method of the link owners entity bean sets the life cycle state of the link as uninitialized. The ManyLink object initializes its member collection during the next accessor call by invoking the home query method of the inverse association end bean (CustomerHome).The query members method name is a parameter of the ManyLink constructor.
public void ejbLoad () throws java.rmi.RemoteException { getCustomerLink().setUninitialized(); } u Removing the bank
Because we defined the association as an aggregation (constructor of ManyLink) the link object deletes all his children (customers) during the delete process of his owner entity bean.
public void ejbRemove() throws java.rmi.RemoteException { super.ejbRemove(); getCustomerLink().removeAllMembers(); }
Relationships
257
public class CustomerBean extends ITSOEntityBean implements javax.ejb.EntityBean { private SingleLink bankLink; public String primaryKey; public String bankForeignKey; } u Instantiating / accessing the SingleLink object
We lazy initialize the the link object when it is used for the first time.
private SingleLink getBankLink() throws java.rmi.RemoteException { if (bankLink == null) bankLink = new SingleLink(this, "Bank", "itso.bank", "bankForeignKey", "primaryKey"); return bankLink; } u Retrieving the bank public Bank getBank() throws RemoteException { return (Bank) getBankLink().getValue(); } u Setting the bank
A customer is a part of a bank (Bank - Customer is an aggregation association). In CustomerBean.ejbCreate(...) and CustomerBean.ejbPostCreate(...) we pass the reference to the aggregate of the part (Bank). CustomerBean has no setBank(Bank) method (a customer can not change the aggregate). SingleLink.setValue(EJBObject) called from ejbCreate(..) sets the foreign key instance variable in link owners entity to the primary key of link owners aggregate. Column BANKID in table CUSTOMER is a non nullable field. Not setting the foreign key in ejbCreate(..) results in an SQL error. We pass the foreign key field name and the primary key field name of the aggregate bean key in the constructor of SingleLink.
258
SingleLink.setValue(EJBObject) called from ejbPostCreate(..) sets the value of the association end and updates the inverse association end by calling the appropriate add member method of the owner aggregate and passing the link owners reference (its EJBObject reference). The ejbObject reference is accessible in the postCreate(..) method of the link owners entity.
u Maintaining the life cycle state of the the link object
The ejbLoad() method of the link owners entity sets the life cycle state of the link as uninitialized. The SingleLink object initializes its member value during the next accessor call by invoking the home of the inverse association end :
bankHome.findByPrimaryKey (primaryKeyOfBank) public void ejbLoad () throws java.rmi.RemoteException { super.ejbLoad(); getBankLink().setUninitialized(); } u Removing the customer public void ejbRemove() throws java.rmi.RemoteException { super.ejbRemove(); //superclass maintains the entity live cycle state bank.setValue(null); }
SingleLink.setValue(EJBObject) called from CustomerBean.ejbRemove(..) sets the value of the association end to null and updates the inverse association end by calling the appropriate remove member method of the owner aggregate. Note : bank.removeCustomer(customer) gives the same result.
Class ManyLink
Constructor
ManyLink(ITSOEntityBean linkOwner,
Relationships
259
String inverseRole, String packageNameInverseAssociationEnd, String queryMembersMethodName, String primaryKeyFieldNameOfLinkOwnerBeanKey, int relationType) throws RemoteException
The constructor has six parameters : 1. reference to the owner of the link (entity bean) 2. inverse role (role of the entity bean at the other end of the association). The name of the role has to correspond to the Remote Interface of the inverse entity bean. 3. package name of the inverse association end (ManyLink expects the bean key class of the link owner entity in the same package as the link owner). 4. name of the members querying method of the inverse home class. Extensions to the home provide the services for finding the members of a many-link. 5. name of the primary key field in the key class of the link owner entity. The primary key field has to be public. The ManyLink object gets the field from the key class and passes the value as foreign key in the members querying method (see previous parameter). 6. relation type : Aggregation [ManyLink.AGGREGATION] controls the life cycle of the member objects or normal association [ManyLink.NORMAL_ASSOCIATION].
invoking the query members method of the inverse home (home of the entity at the other end of the association) and passes the primary key of the link owners entity as a parameter. The name of the query members method and the name of the primary key field of the link owners bean key are parameters of the ManyLink constructor.
u converts the member vector to EJBObjectEnumeration and returns to
enumeration.
getMembers() method).
u if the member vector does not contain the member reference : adds the
260
singled-value reference at the other end of the association by invoking the appropriate set method of the inverse bean and passing the EJBObject reference of the link owners entity as a parameter.
u if the relation is an aggregation : the parent reference is passed to the
child entity in the ejbCreate(...) and ejbPostCreate(...) method of the child. Both methods pass the parent reference to the SingleLink object by invoking singleLink.setValue(EJBObject parentReference). SingleLink invokes the appropriate add method of the inverse multi-valued side of the association.
getMembers() method).
u if the member vector does contain the member reference : remove the
singled-value reference at the other end of the association by invoking the appropriate set method of the inverse bean and passing a null value.
u if the relation is an aggregation : deletes the child by invoking the childs
remove() method.
getMembers() method).
u invokes removeMember(entityToRemove) for each member.
Class SingleLink
Constructor
SingleLink(ITSOEntityBean linkOwner, String inverseRole, String packageNameInverseAssociationEnd, String foreignKeyFieldName, String primaryKeyFieldNameOfInverseBeanKey) throws RemoteException
The constructor has six parameters : 1. reference to the owner of the link (entity bean) 2. inverse role (role of the entity bean at the other end of the association). The name of the role has to correspond to the Remote Interface of the inverse entity bean
Relationships
261
3. package name of the inverse association end 4. name of the foreign key field in the link owner entity. 5. name of the primary key field in the key class of the inverse association name of the role (Customer)
If the link owners entity bean is in the pre-creating state [calling method : ejbCreate(...)] : sets the foreign key instance variable of link owners entity bean to the primary key value of newRelation (parameter in the setValue() method).
Note : not setting a non nullable foreign key for CMP entities during ejbCreate(...) results in an SQL error when the container tries to insert the row after ejbCreate(...) has ended. Updating the object references on both end of the association during ejbCreate(...) is not possible because the link owners entity has no identity yet.
If the link owners entity bean is not in the pre-creating state [calling method : ejbPostCreate(...) or wrapper method set<inverseRole>(EJBRemoteType)] : sets the foreign key instance variable of the link owners entity (see above), sets the value of the association end to newRelation and updates the inverse association end by calling the appropriate add member method and passing the link owners EJBObject interface (also referred as the remote interface).
262
Note : <inverseRole> is a parameter in the constructor of SingleLink class. u delete relationship (current relation : not null / new relation : null) : sets the foreign key instance variable of the link owners entity and the value of the association end to null and updates the inverse association end by calling the appropriate remove member method and passing the link owners EJBObject interface (also referred as the remote interface). u update relationship (current relation : not null / new relation : not null) :
Limitations
The itso.bank.ejb.relation package has the following limitations :
u The SingleLink class implements the single-valued end of a one-to-many
association (the entity bean at the other end of the association has to own a ManyLink object). One-to-one association in both directions are not supported..
u No compound keys allowed. Bean key classes have one (public) instance
variable.
Relationships
263
264
11 Inheritance
In this chapter we describe how Entity EJBs can be used to display polymorphism.
11.1 Inheritance
The main motive for implementing inheritance is to support polymorphism and to provide reuse of the objects. Polymorphism in the Object-Oriented sense means using a superclass variable to represent a subclass object. For example, a bank could have different types of accounts like Savings, Checkings and Corporate. Polymorphism implies using an object (a BankAccount) to represent any type of account. The 1.0 version of the EJB specification does not provide inheritance support between EJBs. In this chapter we describe the programming model to support inheritance and a sample implementation using this model.
265
target class along with its subclasses, that is, a search for all the BankAccounts returns even the Saving Accounts, Checking Accounts and Corporate Accounts.
u Making relationship finders return heterogenous results, containing
A subclass of Parent bean called Child bean would have the following characteristics:
u Remote interface, Child u Home interface, ChildHome u Bean implementation class ChildBean u Primary key class, ParentKey
266
Remote Interface
The remote interface of the child EJB, Child, must extend the remote interface of the parent EJB, Parent. This ensures that an instance of the child EJB may be used where an instance of the parent EJB is expected, one of the important benefits of inheritance.
EJB Homes
The home of the Child bean, ChildHome, must not extend the Parent home, ParentHome. However, it is important to define the relationship between methods on the ParentHome and ChildHome interfaces. A create method on ParentHome can only create a Parent bean instance, and a create method on ChildHome creates both a Child bean and a Parent bean instance. A remove method on ParentHome can remove Parent bean instances only. A remove method on ChildHome removes both the Child and Parent bean instances. A custom finder method on ParentHome returns an Enumeration that may contain Parent bean instances. The determination of the actual contents of the Enumeration is described as an example in Accessing the BankAccount Hierarchy on page 275. For bean implementations that are the root of an inheritance hierarchy, we define a discriminator field which determines that actual type of the instance. A getter method must also be defined for the discriminator and this method should be promoted to the remote interface. For a bean that inherits from a parent class, the child beans implementation class must extend from a Proxy class. The Proxy superclass contains all the methods defined in the remote interface of the parent bean. An invocation on any of these methods is redirected to an instance of the parent bean. A client must not work directly with an instance of the Parent bean but only with the Child beans. The discriminator field is useful in identifying the specific child bean to which the instance belongs to. The client then looks up the corresponding child home for obtaining the true instance.
Inheritance
267
table, a discriminator column identifies the type of object to be instantiated from a row, tables are not fully-normalized, but the whole hierarchy can be accessed easily.
Figure 134. Single-table mapping u "Root/leaf" mapping: The root of the hierarchy specifies the root table
which also provides a discriminator column. Each subtype specifies the leaf table which must be joined to gather the subclass-specific columns. Tables are fully-normalized, but multiple joins can be required to read a single instance, and joins and unions are required to read a hierarchy.
268
Figure 135. Root/leaf mapping u "Distinct-table" mapping: Each class in the hierarchy maps to a separate
table, which contains the complete row for that type. Tables are likely not normalized, access to a single type requires no joins, but access to a hierarchy always requires unions. Since the tables do not have to be related, key consistency problems between the tables can make this pattern very difficult to automate.
Inheritance
269
The Above class diagram has a superclass BankAccount and its subclassesCorporateAccount, SavingsAccount and CheckingAccount. We now develop the EJBs to match this hierarchy.
270
Note
VisualAge for Java does not generate the deployment classes properly for remote interfaces which extend from other interfaces. The tool does not identify any of the methods defined in the super class. You need to manually copy all the methods from the superclass (interface) to the remote interface even though there is an inheritance to enable the tool to generate the classes without any errors.
Inheritance
271
An obvious question would be as to why SavingsAccountBean has not been directly extended from the BankAccountBean. The problem with the direct inheritance approach is that the super class bean, BankAccountBean, is not registered with the Home, BankAccountHome. Entity beans not registered with their respective homes (via create or find methods) operate just like any other Java object inaccessible to container callbacks and hence can not avail the transaction, persistence and security features.
Proxy Superclass
The BankAccountProxy class contains the methods that wrap the remote methods of the BankAccount bean. It also contains a method getProxy() that returns the actual BankAccount object. All the remote method calls are routed to this object. The BankAccount object is obtained after a lazy initialization. In the initialization, the Home interface, BankAccountHome, is looked up using the findByPrimaryKey method passing the same key as that of the subclass.
if (proxy == null) { proxy = getBankAccountHome().findByPrimaryKey( getKey() ); }
The getKey() method is an abstract method whose implementation is provided in the subclass, where the primary key of the instance is returned as follows:
if (entityContext != null) return (BankAccountBean) entityContext.getPrimaryKey();
272
We also define a protected method createBankAccount which is invoked within the ejbCreate method of the subclass in order to create an instance of the superclass bean. In the createBankAccount method, the create(...) method is invoked on the BankAccountHome passing the necessary parameters.
protected void createBankAccount(BankAccountKey key, ...) { proxy = getBankAccountHome().create(key, ...); }
The state of the actual BankAccount object that the BankAccountProxy is using must be synchronized with the current state of the subclass entity bean, like the SavingsAccount bean. This can be done by initializing/uninitializing the proxy object in the container callback methods invoked on the subclass entity bean during different stages of its lifecycle:
u ejbPassivate
The container invokes this method when it decides to send the entity to the pooled state. After the completion of this method, the proxy object no longer corresponds to the state of the subclass. We uninitialize the proxy object in this method, by setting it to null.
u ejbActivate
The container invokes this method when it sends the entity to the ready state. At this point the proxy object is out of synch with subclasses state. Its state will not be determined till the next ejbLoad and hence left uninitialized.
u ejbRemove
When the subclass is being removed, even the superclass needs to be removed. In this method we remove the proxy object by a getProxy().remove() operation.
u When any of the remote methods of the superclass remote methods are
invoked the actual proxy object needs to be located in order to invoke the remote methods on it. This is done by a lazy initialization described earlier in this section.
u When a new instance of the subclass is created a new instance of the
superclass entity bean must be created and the proxy objects value set to the created instance. We defer the loading of the super class until any of its remote methods are invoked. This way there is not unnecessary Home interface lookup which is an expensive operation.
Inheritance
273
BankAccount Table
The figure above shows how the SavingsAccount and the BankAccount beans can be mapped using the root/leaf mechanism:
u All the fields of the superclass, BankAccount, are mapped to the
BankAccount table as distinct columns with ACCID (accountId) being the primary key for the table
u The fields of the SavingsAccount class are mapped similarly to the
SavingsAccount table with an additional field ACCID being the primary key
u ACCID in the BankAccount table acts as the foreign key in the
SavingsAccount table.
274
We prefer this approach over the single table and distinct table mapping for the following reasons:
u Classes can be added to the hierarchy without altering any of the existing
tables. This is not true for single table mapping where the fields of the new class in the hierarchy must be mapped to new columns in the single table.
u The resulting tables are compacter than in the distinct table mapping. In
the distinct table mapping all the columns of the parents table are duplicated in the tables of the subclasses.
u In the single table mapping, when different subclass beans share the
same key class, it is possible for the findByPrimaryKey method to return an instance which does not correspond to the specified bean. For example, the findByPrimaryKey method invoked on the SavingsAccountHome passing a BankAccountKey may return a CheckingAccount. The restriction on the type of inheritance mapping may hamper development of EJBs from existing tables. You also can not define any foreign key constraints (DELETE, RESTRICT) on the subclasses table using the primary key of the superclasses table.
Inheritance
275
2. The find<METHOD> returns an instance or an enumeration of instances of the Parent bean 3. The client obtains the discriminator field of an instance by invoking the getter method for the discriminator field. The value of this field is one of SAVINGS, PAYEE or CHECKING 4. The client determines the child beans home to be looked up based on the value of the discriminator SavingsAccountHome for SAVINGS, CorporateAccountHome for PAYEE and CheckingAccountHome for CHECKING 5. The client invokes the findByPrimaryKey method on the child beans home passing the primary key of the parent beans instance 6. The result of the above find method is the actual instance which should be used by the client When a client attempts to invoke methods belonging to the subclass, the object needs to be narrowed using the necessary CORBA helper class in the following way:
public void main(String[] args) { /** * Find a specific BankAccount using the Key * If its a SavingsAccount determine the Minimum amount * We could have used the specific home - SavingsAccountHome but this step * is necessary when you are using * the parents Home to lookup a child bean */ BankAccountHome bankAcHome = .... BankAccount ba = bankAcHome.findByPrimaryKey(...); if (ba.getAccountType().equals("Saving") ) { SavingsAccount sa = SavingsAccountHelper.narrow(ba); /* * we cannot directly do * SavingsAccount sa = bankAcHome.findByPrimaryKey(".."); * and we also cannot type cast it directly like sa = (SavingsAccount) ba; */ sa.getMinimumAmount(); // get the minimum amount } }
276
It contains two methods to convert the instance of the parent bean to an instance of the child bean typeCast(BankAccount) and typeCastEnumeration(Enumeration). The typeCast method implements the steps described earlier to return the actual instance from an instance of the parent bean.
public static BankAccount typeCast(BankAccount parent) throws RemoteException{ String discriminator = parent.getAccountType(); if ("SAVINGS".equals(discriminator)) return getSavingsHome().findByPrimaryKey( parent.getPrimaryKey()); if ("PAYEE".equals(discriminator)) return getCorporateHome().findByPrimaryKey(parent.getPrimaryKey()); if ("CHECKING".equals(discriminator)) return getCheckingHome().findByPrimaryKey(parent.getPrimaryKey()); throw new RemoteException("Could not locate actual instance"); }
The typeCastEnumeration method returns an Enumeration of the actual instances from an Enumeration of the instances of the parent bean.
public static Enumeration typeCastEnumeration(Enumeration enum) throws RemoteException{ Vector actual = new Vector(); while (enum.hasMoreElements()) { actual.addElement( typeCast((BankAccount) enum.nextElement()); } return actual.elements(); }
Inheritance
277
SingleLink
In a Bank, a TransactionRecord is created by a particular BankAccount which could be a SavingsAccount, CorporateAccount or a CheckingAccount. We extend the SingleLink class to represent an association between the TransactionRecord and the BankAccount. The TransactionRecord uses the link class, BankAcountSingleLink, to set and obtain the value of the BankAccount reference. The BankAccountSingleLink extends the SingleLink class. Please refer to Class SingleLink on page 261 for more information about the SingleLink class. The usage of this class remains the same except as indicated below:
Constructor
The Constructor takes only the linkOwner and foreignKeyFieldName parameters. The inverseRole, packageNameInverseAssociationEnd and primaryKeyFieldNameOfInverseBeanKey are already known and their values are BankAccount, itso.bank.ejb and accountId respectively. The super classes constructor is invoked with these parameters in the body.
ManyLink
In a similiar Bank scenario, a Customer has an aggregation of BankAccounts. A BankAccount in the aggregation could be a SavingsAccount, CheckingAccount or CorporateAccount. We extend the ManyLink class to represent the relationship between the Customer and the BankAccount(the root of the hierarchy). The Customer uses this link class, BankAccountManyLink, to add, remove and retrieve the BankAccounts. The BankAccountManyLink extends the ManyLink class. Please refer to Class ManyLink on page 259 for more information about the ManyLink Class. The usage of this class remains the same except as indicated below:
Constructor
The Constructor takes only the linkOwner, queryMembersMethodName, primaryKeyFieldNameOfLinkOwnerBankKey and relationType
278
parameters. The inverseRole and packageNameInverseAssociationEnd are already known and their values are BankAccount and itso.bank.ejb respectively. The super classes constructor is invoked with these parameters in the body.
Inheritance
279
280
281
282
Add the necessary add, remove and accessor methods to support the different relationships. Make the necessary changes within the ejbCreate, ejbPostCreate, ejbActivate, ejbPassivate, setEntityContext and unsetEntityContext methods as described in Responsibilities of the bean developer on page 252.
283
u Project: ITSOBank u Package: itso.bank.ejb u Class: BankBean u Superclass: itso.bank.ejb.base.ITSOEntityBean u EJB Home Interface: BankHome u EJB Remote Interface: Bank u EJB Key Class or Field: BankKey u import statements:
Add Fields
CMP
For directions on how to add CMP fields see , Adding fields to the Bean on page 122.
284
Transient
Table 10. Create Field customerLink
Field Name Filed Type Access Modifiers Other Modifiers Access with getter and setter methods Getter Setter Container Managed customerLink itso.bank.ejb.relation.ManyLink private transient checked
private (none) no
private (none) no
285
286
u removeBankAccount public void removeBankAccount(BankAccount account) throws java.rmi.RemoteException { traceMethod("start Bank.removeBankAccount(BankAccount account)"); try { getBankAccountLink().removeBankAccount(account); traceMethod("end Bank.removeBankAccount(BankAccount account)"); } catch(Exception e) { throw wrapperNonRemoteException("BankBean.removeBankAccount(BankAccount)", e); } } u removeCustomer public void removeCustomer(Customer customer) throws java.rmi.RemoteException { traceMethod("start Bank.deleteCustomer(Customer customer)"); try { getCustomerLink().removeMember(customer); traceMethod("end Bank.deleteCustomer(Customer customer)"); } catch(Exception e) { throw wrapperNonRemoteException("BankBean.deleteCustomer(Customer)", e); } } u traceMethod private void traceMethod(String methodNameAsString) { String bankKeyAsString = null; Object ejbObject = null; try { bankKeyAsString = ((BankKey) getPrimaryKey()).primaryKey; ejbObject = getEJBObject(); } catch(RemoteException e) { bankKeyAsString = "unknown"; } System.out.println(">> " + methodNameAsString + " [" + this + "] / Key " + bankKeyAsString +" [EJBObject: " + ejbObject + "]"); }
287
u ejbCreate public void ejbCreate(BankKey key, String name) throws RemoteException { // All CMP fields should be intialized here. super.ejbCreate(); primaryKey = key.primaryKey; bankName = name; traceMethod("ejbCreate(BankKey)"); } u ejbLoad public void ejbLoad () throws java.rmi.RemoteException { super.ejbLoad(); getCustomerLink().setUninitialized(); getBankAccountLink().setUninitialized(); traceMethod("ejbLoad()"); } u ejbPassivate public void ejbPassivate() throws java.rmi.RemoteException { super.ejbPassivate(); traceMethod("ejbPassivate()"); } u ejbPostCreate public void ejbPostCreate(BankKey key, String name) throws java.rmi.RemoteException { super.ejbPostCreate(); traceMethod("ejbPostCreate(BankKey)"); } u ejbRemove public void ejbRemove() throws java.rmi.RemoteException { super.ejbRemove(); traceMethod("ejbRemove()"); getCustomerLink().removeAllMembers(); getBankAccountLink().removeAllMembers(); } u ejbStore public void ejbStore () throws java.rmi.RemoteException { super.ejbStore(); traceMethod("ejbStore()"); } u getBankAccountLink
288
private BankAccountManyLink getBankAccountLink() throws java.rmi.RemoteException { if (accountLink == null) //accountLink = new ManyLink(this, "BankAccount", "itso.bank.ejb", "findByBankId", "primaryKey", ManyLink.AGGREGATION); accountLink = new BankAccountManyLink(this, "findByBankId", "primaryKey", ManyLink.AGGREGATION); return accountLink; } u getCustomerLink private ManyLink getCustomerLink() throws java.rmi.RemoteException { if (customerLink == null) customerLink = new ManyLink(this, "Customer", "itso.bank.ejb", "findByBankId", "primaryKey", ManyLink.AGGREGATION); return customerLink; } u setEntityContext public void setEntityContext(EntityContext ctx) throws java.rmi.RemoteException { super.setEntityContext(ctx); } u unsetEntityContext public void unsetEntityContext() throws java.rmi.RemoteException { super.unsetEntityContext(); traceMethod("unsetEntityContext()"); }
289
u removeCustomer u setBankName
Add Fields
CMP
For directions on how to add CMP fields see , Adding fields to the Bean on page 122. We need to add six fields with the same characteristics. Only the name of the field is different. Use the information given in Table 12, but changing Field Name accordingly, to create the following fields :
u bankForeignkey u firstName u lastName u password u title
290
u userid
bankForeignKey
String public none checked
Transient
We create two transient fields required to implement the associations between:
u Customer and Bank (SingleLink) u Customer and BankAccount (BankAccountManyLink)
private (none)
291
public (none) no
292
bank = new SingleLink(this, "Bank", "itso.bank.ejb", "bankForeignKey", "primaryKey"); return bank; } u getCustomerId public String getCustomerId() { return primaryKey; } u removeBankAccount public void removeBankAccount(BankAccount bankAccount) throws java.rmi.RemoteException { getBankAccountLink().removeBankAccount(bankAccount); }
293
} u ejbLoad public void ejbLoad () throws java.rmi.RemoteException { super.ejbLoad(); getBankLink().setUninitialized(); getBankAccountLink().setUninitialized(); traceMethod("ejbLoad()"); } u ejbPassivate public void ejbPassivate() throws java.rmi.RemoteException { super.ejbPassivate(); traceMethod("ejbPassivate()"); } u ejbPostCreate public void ejbPostCreate(CustomerKey customerKey, String customerTitle, String customerFirstName, String customerLastName, String customerUserid, String customerPassword, Bank bank) throws RemoteException { super.ejbPostCreate(); getBankLink().setValue(bank); //updates the object relation traceMethod("ejbPostCreate(CustomerKey customerKey, String customerFirstName, String customerLastName, Bank bank"); } u ejbRemove public void ejbRemove() throws java.rmi.RemoteException { super.ejbRemove(); bank.setValue(null); getBankAccountLink().removeAllMembers(); traceMethod("ejbRemove()"); } u ejbStore public void ejbStore () throws java.rmi.RemoteException { //bankId = getBankRelation().getBankId(); super.ejbStore(); traceMethod("CustomerBean.ejbStore()"); } u setEntityContext public void setEntityContext(EntityContext ctx) throws java.rmi.RemoteException { super.setEntityContext(ctx); traceMethod("setEntityContext(EntityContext)"); }
294
In addition to adding these methods to the CustomerHome, you need to modify the CustomerBeanFinderHelper as indicated below:
public interface CustomerBeanFinderHelper { public static final String findByBankIdQueryString = "SELECT T1.TITLE, T1.CUSTID, T1.PASSWORD, T1.FNAME, T1.USERID, T1.BANKID, T1.LNAME FROM ITSO.CUSTOMER T1 WHERE T1.BANKID = ?"; public static final String findByUserIdQueryString = "SELECT T1.TITLE, T1.CUSTID, T1.PASSWORD, T1.FNAME, T1.USERID, T1.BANKID, T1.LNAME FROM ITSO.CUSTOMER T1 WHERE T1.USERID = ? AND T1.PASSWORD = ?"; }
295
For additional information about how to add finder methods see 4.9, Adding Special Finder methods on page 160.
Add Fields
CMP
For directions on how to add CMP fields see , Adding fields to the Bean on page 122. We need to add two fields with the same characteristics. Only the name of the field is different. Use the information given in Table 15, but changing Field Name accordingly, to create the following fields :
u accountId u traccId
296
accountId
String public none unchecked
transamt
java.math.BigDecimal public none checked
transtype
String
297
transtype
public none checked
Transient
Table 18. Create Field accountLink
Field Name Filed Type Access Modifiers Other Modifiers Access with getter and setter methods Getter Setter Container Managed accountLink itso.bank.ejb.inheritance.relation.BankAccountSingleLink private transient checked
private (none) no
298
u getBankAccount public BankAccount getBankAccount() throws java.rmi.RemoteException { return getAccountLink().getBankAccount(); } u getTransactingAccount public BankAccount getTransactingAccount() throws java.rmi.RemoteException { //this.traccId = ((BankAccountKey) otherAccount.getPrimaryKey()).accountId; if (traccId == null) { return null; } try { BankAccount account = itso.bank.ejb.inheritance.relation.TypeConverter.getBankAccountHome().findByPri maryKey( new BankAccountKey(traccId)); return itso.bank.ejb.inheritance.relation.TypeConverter.typeCast(account); } catch (Exception exc) { throw new RemoteException(exc.getMessage()); } } u getTransactionID public java.sql.Timestamp getTransactionID() throws java.rmi.RemoteException{ return primaryKey; } u setTransactingAccount public void setTransactingAccount(BankAccount otherAccount) throws java.rmi.RemoteException { this.traccId = ((BankAccountKey) otherAccount.getPrimaryKey()).accountId; }
299
primaryKey = key.primaryKey; this.transamt = amount; this.transtype = transType; getAccountLink().setValue(account); } u ejbLoad public void ejbLoad () throws java.rmi.RemoteException { super.ejbLoad(); } u ejbPassivate public void ejbPassivate() throws java.rmi.RemoteException { super.ejbPassivate(); } u ejbPostCreate public void ejbPostCreate(TransactionRecordKey key, BankAccount account, java.math.BigDecimal amount, String transType) throws RemoteException { super.ejbPostCreate(); // All CMP fields should be intialized here. getAccountLink().setValue(account); } u ejbRemove public void ejbRemove() throws java.rmi.RemoteException { super.ejbRemove(); getAccountLink().setValue(null); } u ejbStore public void ejbStore () throws java.rmi.RemoteException { super.ejbStore(); } u setEntityContext public void setEntityContext(javax.ejb.EntityContext ctx) throws java.rmi.RemoteException { super.setEntityContext(ctx); } u unsetEntityContext public void unsetEntityContext() throws java.rmi.RemoteException { super.unsetEntityContext(); }
300
In addition to adding these methods to the TransactionRecordHome, you need to modify the TransactionRecordBeanFinderHelper as indicated below:
public interface TransactionRecordBeanFinderHelper { public static final String findByAccountIdQueryString = "SELECT T1.TRANSID, T1.TRANSTYPE, T1.TRANSAMT, T1.ACCID, T1.TRACCID FROM ITSO.TRANSRECORD T1 WHERE T1.ACCID = ?"; }
For additional information about how to add finder methods see 4.9, Adding Special Finder methods on page 160.
301
We use these additional capabilities to create the Container-managed persistence field mapping to a persistent store. For our bank application, the persistent store is based on an existing database called ITSOBANK. Details about the definition of the ITSOBANK database can be found in Appendix C, ITSOBANK database on page 365. For directions on how to create a schema see , Importing a database schema into VisualAge for Java on page 148. In order to create this schema, you need to provide the following information:
The next step consist in using the schema to create a datastore map.
302
In the Map browser, you need to specify for each Persistent Classes the corresponding Table Maps as described hereafter: Table 21. Bank Table Maps
Persistent Classes Bank BankAccount CheckingAccount CorporateAccount Customer SavingsAccount TransactionRecord Table Maps BANK ACCOUNT CHECKING PAYEE CUSTOMER SAVINGS TRANSRECORD
For each Table Maps item, you indicate the relationship between the class attribute and a table column. In addition, you also give the map type as follows: Table 22. Bank Property Map Relationship
Persistent Classes Bank Class Attribute primaryKey bankName BankAccount accountId accountType balance customerFK bankFK CheckingAccount overdraft accountId CorporateAccount billPaymentTitle accounId SavingAccount accountId minAmount Map Type Simple Simple Simple Simple Simple Simple Simple Simple Simple Simple Simple Simple Simple Table Column BANKID BANKNAME ACCID ACCTYPE BALANCE CUSTID BANKID OVERDRAF ACCID TITLE ACCID ACCID MINAMT
303
Map Type Simple Simple Simple Simple Simple Simple Simple Simple Simple Simple Simple Simple
Table Column TITLE CUSTID FNAME PASSWORD USERID BANKID LNAME ACCID TRANSAMT TRANSTYPE TRANSID TRACCID
TransactionRecord
We have finished with the implementation of the bank application entity beans. Another part of the business logic is implemented as session beans. We have defined a UserSB which implements customer use cases and an AdminSB which implements administrative use cases. These two session beans are the subjects of the following chapters.
304
305
306
The authenticate method uses a user defined finder method on the CustomerHome in order to get an enumeration of customers with the same userId. Since each userid is unique only one customer should be returned. Once the customer is found we store the customerLogin password and object reference for later use.
307
308
309
310
311
312
313
314
We
extend
from
ITSOSessionBean
which
extends
itself
from
Homefactory class manage to find and caches the homes. In this way we save the processing time to go to the naming services and find the homes. 8. Modify the State Management Attribute to #STATEFUL
Add Fields
The UserSB session bean needs to maintain some information like the login password. We also need values like the reference to the customer who logs in. In this way we do not have to get it everytime we need because since the UserSB is alive it will be tied to that particular customer session.
315
We also cache the Home objects for all the classes involved in our use case. In this way we avoid to do a lookup each time we need to deal with a class we have already used.
bankAccountHome
itso.bank.ejb.BankAccountHome private none checked
private (none) no
bankHome
itso.bank.ejb.BankAccountHome private none checked
private (none) no
316
custKey
itso.bank.ejb.CustomerKey private none checked
private private no
customerHome
itso.bank.ejb.CustomerHome private none checked
private private no
317
customerRef
itso.bank.ejb.Customer private none checked
private private no
initialCtx
javax.naming.Context private none checked
private private no
318
loginPassword
String private none checked
private private no
loginStatus
boolean private none checked
private private no
transactionRecordHome
itso.bank.ejb.TransactionHome
319
transactionRecordHome
private none checked
private private no
320
// Enumeration is empty, no Customer found setLoginState(false); return loginStatus; } // User Id and password are valid, authentication is OK. Now we need to check // if only one instance has been returned from the database setLoginState(true); loginPassword = password; setCustomerRef(tempCust); return getLoginState(); } u buildBankAccountHome private void buildBankAccountHome() throws java.rmi.RemoteException { bankAccountHome = (BankAccountHome) getHome("BankAccount"); } u buildBankHome private void buildBankHome() throws RemoteException { bankHome = (BankHome) getHome("Bank"); } u buildCustomerHome private void buildCustomerHome() throws RemoteException { customerHome = (CustomerHome) getHome("Customer"); } u buildTransactionRecordHome private void buildTransactionRecordHome() throws java.rmi.RemoteException { transactionRecordHome = (TransactionRecordHome) getHome("TransactionRecord"); } u deposit public void deposit(String accId,java.math.BigDecimal amt) { TransactionRecordKey txKey = null; // Get the home interface try { // Create the BankAccountKey from the ID BankAccountKey bAcKey = new BankAccountKey(accId); //Find the right BankAccount instance with from the key BankAccount account=TypeConverter.typeCast(getBankAccountHome().findByPrimaryKey(bAcKey)); //call the deposit method on the account account.deposit(amt); // Since the deposit action is a transaction made on the account we need to create a TransactionRecord
321
// and store i in the DataBase. TransactionRecordHome trHome = (TransactionRecordHome)getHome("TransactionRecord"); try { // Now that the withdraw has been processed we need to create an instance of TransactionRecord java.sql.Timestamp transId = new java.sql.Timestamp(System.currentTimeMillis()); txKey = new TransactionRecordKey(transId); TransactionRecord newRecord = trHome.create(txKey, account, amt,"C"); } catch (javax.ejb.CreateException e) { // setRollbackFlag(); } } catch (BankTransactionException e1) { System.out.println(e1.getMessage()); // setRollbackFlag(); } catch (Exception e) { e.printStackTrace(System.out); }// endtry } u getBalance public java.math.BigDecimal getBalance( String accountId) { try { //this is only needed for testing. BankAccountKey bAcKey = new BankAccountKey(accountId); BankAccount account= TypeConverter.typeCast(getBankAccountHome().findByPrimaryKey(bAcKey)); return account.getBalance(); } catch(Exception except) { except.printStackTrace(System.out); //throw wrapperNonRemoteException("UserSB.getCustomer(String)", except); return null; } } u getCustomer public Customer getCustomer(String customerId) throws RemoteException { CustomerHome cHome =null; try { //this is only needed for testing. CustomerKey cKey = new CustomerKey(customerId);
322
setCustomerRef(getCustomerHome().findByPrimaryKey(cKey)); return (customerRef); } catch(Exception except) { except.printStackTrace(System.out); //throw wrapperNonRemoteException("UserSB.getCustomer(String)", except); return null; } } u getHistory public String[][] getHistory(String accId,java.util.Date startDate,java.util.Date endDate,String type) { // Get the home interface for the Bank Account TransactionRecordHome trHome =null; try { // Create the BankAccountKey from the ID BankAccountKey bAcKey = new BankAccountKey(accId); //Find the right BankAcount instance with from the key BankAccount account= TypeConverter.typeCast(getBankAccountHome().findByPrimaryKey(bAcKey)); // Vector to contain the right transaction to return java.util.Vector v = new java.util.Vector(); //call the getTransactionRecords to get all tasaction related to this account java.util.Enumeration transEnum = account.getTransactionRecords(); while(transEnum.hasMoreElements()) { TransactionRecord tRecord = (TransactionRecord)transEnum.nextElement(); if( startDate != null){ if(((java.util.Date)(tRecord.getTransactionID())).before( startDate)){ continue; } } if( endDate != null){ if(((java.util.Date)(tRecord.getTransactionID())).after( endDate)){ continue; } } if( type != null){ if( !(type.equals( tRecord.getTranstype()))){ continue; } } v.addElement( tRecord); } String[][]transDataArray = new String[v.size()][3]; if( v.size() > 0){
323
for( int i = 0; i < v.size(); i++){ transDataArray[i][0]=((java.util.Date)(((TransactionRecord)(v.elementAt(i))).getTransactionID())) .toString(); transDataArray[i][1]= (((TransactionRecord)(v.elementAt(i))).getTranstype()); transDataArray[i][2]= (((TransactionRecord)(v.elementAt(i))).getTransamt()).toString(); } } return transDataArray ; } /*********/ catch(Exception except) { except.printStackTrace(System.out); return null; } } u paybill public void paybill(String source, String destination, java.math.BigDecimal amount, String password) throws java.rmi.RemoteException { // CustomerHome custHome = getCustomerHome(); BankAccountKey keyObject = null; // First, we need to verify the validity of the password if (!(password.equals(this.loginPassword))) { // throw new BankException(); } else // Proceed with the transfer transfer(source, destination, amount); } u transfer public void transfer(String source, String destination, java.math.BigDecimal amount) throws java.rmi.RemoteException { BankAccountHome bankAccountHome = getBankAccountHome(); TransactionRecordHome trxHome = getTransactionRecordHome(); BankAccountKey sourceKeyObject = null; BankAccountKey destKeyObject = null; TransactionRecordKey txKey = null; try { sourceKeyObject = new BankAccountKey(source);
324
BankAccount sourceAccount = TypeConverter.typeCast(bankAccountHome.findByPrimaryKey(sourceKeyObject)); destKeyObject = new BankAccountKey(destination); BankAccount targetAccount = TypeConverter.typeCast(bankAccountHome.findByPrimaryKey(destKeyObject)); // Use the next line with inheritance implemented sourceAccount.withdraw(amount); // Use the next block if no inheritance is implemented (Using one object and one table) sourceAccount.withdraw(amount, sourceAccount.getAccountType()); try { // Now that the withdraw has been processed we need to create an instance of TransactionRecord java.sql.Timestamp transId = new java.sql.Timestamp(System.currentTimeMillis()); txKey = new TransactionRecordKey(transId); TransactionRecord newRecord = trxHome.create(txKey, sourceAccount, amount,"T"); newRecord.setTransactingAccount(targetAccount); } catch (javax.ejb.CreateException e) { // setRollbackFlag(); } targetAccount.deposit(amount); try { // Now that the withdraw has been processed we need to create an instance of TransactionRecord java.sql.Timestamp transId = new java.sql.Timestamp(System.currentTimeMillis()); txKey = new TransactionRecordKey(transId); TransactionRecord newRecord = trxHome.create(txKey, targetAccount, amount,"F"); newRecord.setTransactingAccount(sourceAccount); } catch (javax.ejb.CreateException e) { // setRollbackFlag(); } } catch (FinderException e) { // setRollbackFlag(); } catch (BankTransactionException e1) { System.out.println(e1.getMessage()); // setRollbackFlag(); } catch (Exception ex) { System.out.println(ex.getMessage()); } // } u withdraw public void withdraw(String account, java.math.BigDecimal amount) throws java.rmi.RemoteException { BankAccountHome bankAccountHome = getBankAccountHome();
325
TransactionRecordHome trxHome = getTransactionRecordHome(); BankAccountKey keyObject = null; TransactionRecordKey txKey = null; try { keyObject = new BankAccountKey(account); BankAccount sourceAccount = TypeConverter.typeCast( bankAccountHome.findByPrimaryKey(keyObject) ); // Use the next line with inheritance implemented sourceAccount.withdraw(amount); // Use the next block if no inheritance is implemented (Using one object and one table) // sourceAccount.withdraw(amount, sourceAccount.getAccountType()); try { // Now that the withdraw has been processed we need to create an instance of TransactionRecord java.sql.Timestamp transId = new java.sql.Timestamp(System.currentTimeMillis()); txKey = new TransactionRecordKey(transId); TransactionRecord newRecord = trxHome.create(txKey, sourceAccount, amount, "D"); } catch (javax.ejb.CreateException e) { // setRollbackFlag(); } } catch (FinderException e) { // setRollbackFlag(); } catch (BankTransactionException e1) { System.out.println(e1.getMessage()); // setRollbackFlag(); } }
326
buildBankHome(); return bankHome; } u getCheckingAccount private CheckingAccount getCheckingAccount(String bankingAccountId) throws RemoteException { try { return getCheckingAccountHome().findByPrimaryKey(new BankAccountKey(bankingAccountId)); } catch(Exception except) { throw wrapperNonRemoteException("UseCaseSB.getCheckingAccount(String bankingAccountId)", except); } } u getCheckingAccountHome private CheckingAccountHome getCheckingAccountHome() throws RemoteException { if (checkingAccountHome == null) buildCheckingAccountHome(); return checkingAccountHome; } u getCorporateAccount private CorporateAccount getCorporateAccount(String bankingAccountId) throws RemoteException { try { return getCorporateAccountHome().findByPrimaryKey(new BankAccountKey(bankingAccountId)); } catch(Exception except) { throw wrapperNonRemoteException("UseCaseSB.getCorporateAccount(String bankingAccountId)", except); } } u getCorporateAccountHome private CorporateAccountHome getCorporateAccountHome() throws RemoteException { if (corporateAccountHome == null) buildCorporateAccountHome(); return corporateAccountHome; } u getCustomer private Customer getCustomer(String customerId) throws RemoteException { try { return getCustomerHome().findByPrimaryKey(new CustomerKey(customerId)); }
327
catch(Exception except) { throw wrapperNonRemoteException("UseCaseSB.getCustomer(String)", except); } } u getCustomerHome private CustomerHome getCustomerHome() throws RemoteException { if (customerHome == null) buildCustomerHome(); return customerHome; } u getSavingsAccount private SavingsAccount getSavingsAccount(String bankingAccountId) throws RemoteException { try { return getSavingsAccountHome().findByPrimaryKey(new BankAccountKey(bankingAccountId)); } catch(Exception except) { throw wrapperNonRemoteException("UseCaseSB.getSavingsAccount(String bankingAccountId)", except); } } u getSavingsAccountHome private SavingsAccountHome getSavingsAccountHome() throws RemoteException { if (savingsAccountHome == null) buildSavingsAccountHome(); return savingsAccountHome; }
328
The StringX?ArrayHelper and the StringX?ArrayHolder have been generated because we have used arrays of string as return type for getAccounts and getHistory methods. These classes are used to marshal the arrays before sending them through the ORB. The UserSB is now ready for use by a client application. You can also use the test client to verify the behavior of the UserSB (See Running the Generated
329
Test Client on page 64.) You need to start with the first business method: authenticate.
330
331
u Bean type: Session Bean) u Project: ITSOBank u Package: itso.bank.ejb.sb.admin u Class: AdminSBBean u Superclass: itso.bank.ejb.base.ITSOSessionBeanEJB u Home Interface: AdminSBHome u EJB Remote Interface: AdminSB u EJB Key Class or Field: none u import statements:
itso.bank.ejb.* itso.bank.ejb.base.*
Add Fields
The AdminSB requires the creation of the following fields:
u customerHome u bankHome u savingsAccountHome u checkingAccountHome u checkingAccountHome
private (none)
332
333
u getCustomer private Customer getCustomer(String customerId) throws RemoteException { try { return getCustomerHome().findByPrimaryKey(new CustomerKey(customerId)); } catch(Exception except) { throw wrapperNonRemoteException("UseCaseSB.getCustomer(String)", except); } } u getSavingsAccount private SavingsAccount getSavingsAccount(String bankingAccountId) throws RemoteException { try { return getSavingsAccountHome().findByPrimaryKey(new BankAccountKey(bankingAccountId)); } catch(Exception except) { throw wrapperNonRemoteException("UseCaseSB.getSavingsAccount(String bankingAccountId)", except); } } u buildBankHome private void buildBankHome() throws RemoteException { bankHome = (BankHome) getHome("Bank"); } u buildCheckingAccountHome private void buildCheckingAccountHome() throws RemoteException { checkingAccountHome = (CheckingAccountHome) getHome("CheckingAccount"); } u buildCorporateAccountHome private void buildCorporateAccountHome() throws RemoteException { corporateAccountHome = (CorporateAccountHome) getHome("CorporateAccount"); } u buildCustomerHome private void buildCustomerHome() throws RemoteException { customerHome = (CustomerHome) getHome("Customer"); } u buildSavingsAccountHome private void buildSavingsAccountHome() throws RemoteException { savingsAccountHome = (SavingsAccountHome) getHome("SavingsAccount");
334
} u createBank public void createBank(String bankId, String bankName) throws java.rmi.RemoteException { try { getBankHome().create(new BankKey(bankId), bankName); } catch(Exception e) { throw wrapperNonRemoteException("AdminSBBean.createBank(String bankId, String bankName)", e); } } u createCheckingAccount public void createCheckingAccount(String accountId, String customerId, BigDecimal overdraftLimit) throws java.rmi.RemoteException { try { Customer customerOfCheckingAccount = getCustomer(customerId); Bank bankOfCustomer = customerOfCheckingAccount.getBank(); CheckingAccount newCheckingAccount = getCheckingAccountHome().create(new BankAccountKey(accountId), customerOfCheckingAccount, bankOfCustomer); newCheckingAccount.setOverDraftLimit(overdraftLimit); } catch(Exception e) { throw wrapperNonRemoteException("AdminSBBean.createCheckingAccount(String accountId, String customerId, BigDecimal overdraftLimit)", e); } } u createCorporateAccount public void createCorporateAccount(String accountId, String customerId, String billPaymentTitle) throws java.rmi.RemoteException { try { Customer customerOfCorporateAccount = getCustomer(customerId); Bank bankOfCustomer = customerOfCorporateAccount.getBank(); CorporateAccount newCorporateAccount = getCorporateAccountHome().create(new BankAccountKey(accountId), customerOfCorporateAccount, bankOfCustomer); newCorporateAccount.setBillPaymentTitle(billPaymentTitle); } catch(Exception e) { throw wrapperNonRemoteException("AdminSBBean.createCorporateAccount(String accountId, String customerId, String billPaymentTitle)", e); } }
335
u createCustomer public void createCustomer(String customerId, String customerTitle, String customerFirstName, String customerLastName, String customerUserid, String customerPassword, String bankId) throws RemoteException { try { Customer newCustomer = null; Bank bankOfCustomer = getBank(bankId); newCustomer = getCustomerHome().create(new CustomerKey(customerId), customerTitle, customerFirstName, customerLastName, customerUserid, customerPassword, bankOfCustomer); } catch(Exception e) { throw wrapperNonRemoteException("AdminSBBean.createCustomer(String customerId, String customerTitle, String customerFirstName, String customerLastName, String customerUserid, String customerPassword, String bankId)", e); } } u createSavingsAccount public void createSavingsAccount(String accountId, String customerId, BigDecimal minimumBalance) throws java.rmi.RemoteException { try { Customer customerOfSavingsAccount = getCustomer(customerId); Bank bankOfCustomer = customerOfSavingsAccount.getBank(); SavingsAccount newSavingsAccount = getSavingsAccountHome().create(new BankAccountKey(accountId), customerOfSavingsAccount, bankOfCustomer); newSavingsAccount.setMinimumBalance(minimumBalance); } catch(Exception e) { throw wrapperNonRemoteException("AdminSBBean.createSavingsAccount(String accountId, String customerId, BigDecimal minimumBalance)", e); } } u deleteBank public void deleteBank(String bankId) throws java.rmi.RemoteException { try { Bank bankToDelete = getBank(bankId); bankToDelete.remove(); } catch(Exception e) { throw wrapperNonRemoteException("AdminSBBean.deleteBank(String bankId)", e); } }
336
u deleteCheckingAccount public void deleteCheckingAccount(String bankAccountId) throws java.rmi.RemoteException { try { CheckingAccount checkingAccountToDelete = getCheckingAccount(bankAccountId); checkingAccountToDelete.remove(); } catch(Exception e) { throw wrapperNonRemoteException("AdminSBBean.deleteCheckingAccount(String bankAccountId)", e); } } u deleteCorporateAccount public void deleteCorporateAccount(String bankAccountId) throws java.rmi.RemoteException { try { CorporateAccount corporateAccountToDelete = getCorporateAccount(bankAccountId); corporateAccountToDelete.remove(); } catch(Exception e) { throw wrapperNonRemoteException("AdminSBBean.deleteCorporateAccount(String bankAccountId)", e); } } u deleteCustomer public void deleteCustomer(String customerId) throws java.rmi.RemoteException { try { Customer customerToDelete = getCustomer(customerId); customerToDelete.remove(); } catch(Exception e) { throw wrapperNonRemoteException("AdminSBBean.deleteCustomer(String customerId)", e); } } u deleteSavingsAccount public void deleteSavingsAccount(String bankAccountId) throws java.rmi.RemoteException { try { SavingsAccount savingsAccountToDelete = getSavingsAccount(bankAccountId); savingsAccountToDelete.remove();
337
338
339
340
Part 3
APPENDIXES
341
342
ITSOBANK database
343
344
345
1. In the EJBs pane of the EJBs page, select the EJB group that you want to contain the imported EJBs. 2. Click mouse button 2, then select Import EJBs from the pop-up menu. The Import from an EJB Jar File SmartGuide appears.
3. Beside the Filename field, type the name of the jar file you want to import. Alternatively, click the Browse button. A dialog appears. In the dialog, navigate to the jar file, select it, and click OK. The SmartGuide marks for importation all of the types and beans found in the jar file. In the CDROM \Part1Samples\SessionBean we provide .jar file called CreateCustomerInfo.jar.This is an EJB jar file so it does not contain EJS jar file. Select it to try to import a EJB jar file.
346
4. To select individual file types to import, click one or more of the following check boxes: beans: Import all the beans in the jar file. .class Import all the bytecode files in the jar file. .java Import all the source code files. resource Import all the non-.java and non-.class files Details By default, all the selected file types in the jar file are imported. Click the Details button next to a file type to see a list of the files in the jar file, and to specify individual files to import.
347
5. If needed specify additonal options using the Options check boxes as follows: Create new/scratch editions of versioned projects/packages If you are importing into a versioned EJB group, and you want to create a new or scratch edition of the versioned EJB group, click this check box.If you havent done a version of our ITSO BANK project you will not need this option. Overwrite existing resource files without warning If you do not want to be warned about overwriting existing resource files in the EJB group into which you are importing, click this check box. Version imported classes and new editions of packages/projects If you want to automatically version imported classes and the projects and packages they change, click this check box. Also, specify either automatic naming for the new version or a name of your own choosing by selecting either the Name automatically (recommended) radio button or the Version name radio button . 6. Click Finish. At this point in your ejb workspace shold look like this:
348
Since we have imported and EJB jar file in order to test it you have to generata the deployed code first.To do this seeGenerate deployment code inside VisualAge for Java on page 55
349
7. Version the project and export it as a .dat file into the target repository. (To open the export dialog, click on File - Export in the Packages page.) Note: If the target repository is on a different machine, once you export the project to the .dat file, move the .dat file to the other machine. Then, import the .dat file into the repository where you want to locate the project. (To open the import dialog, click on File - Import in the Packages page.)
In the WebSphere Application server administration left pane choose Setup-Java Engine.Select the Path tab and add the C:\customerObject.jar in the Application Server Classpath field.
350
For this changes to make effect you need to stop and start WebSphere Advanced Edition 2.0
351
352
353
354
355
356
TransactionTest Output: -------Starting Client-demarcated rollbacked transaction Scenario... TransactionTest Output: -------Retrieving initial context... TransactionTest Output: -------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://cobalt:900 TransactionTest Output: -------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory TransactionTest Output: -------Invoke: javax.naming.InitialContext(properties) TransactionTest Output: Retrieving the home interface... TransactionTest Output: ******************* TransactionTest: afterBegin() **************88 TransactionTest Output: Transaction Status after myTransaction.begin() is: 0 TransactionTest Output: CMPSample1 Object... TransactionTest Output: Enter key value: TransactionTest Output: Enter state value: TransactionTest Output: Searching for existing object with this key: 1 TransactionTest Output: Object 1 found. CMPSample1 Output: Enter key value for CMP2 Entity Bean: CMPSample1 Output: Enter state value: CMPSample1 Output: -------Retrieving initial context... CMPSample1 Output: -------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://cobalt:900 CMPSample1 Output: -------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory CMPSample1 Output: -------Invoke: javax.naming.InitialContext(properties) CMPSample1 Output: CMPSample2Bean CMPSample1 Output: Retrieving the home interface... CMPSample1 Output: Searching for existing object with this key: 1 CMPSample1 Output: Object 1 found. CMPSample1 Output: State updated. TransactionTest Output: State updated. TransactionTest Output: ************************** TransactionTest: afterCompletion() ************ CMPSample1 Output: ************************** CMPSample1: afterCompletion() ************ CMPSample2 Output: ************************** CMPSample2: afterCompletion() ************ TransactionTest Output: Transaction Status after myTransaction.rollback() is :6
357
TransactionTest Output: -------Starting Container-demarcated transaction Scenario... TransactionTest Output: -------Retrieving initial context... TransactionTest Output: -------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://cobalt:900 TransactionTest Output: -------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory TransactionTest Output: -------Invoke: javax.naming.InitialContext(properties) TransactionTest Output: Retrieving the home interface... TransactionTest Output: CMPSample1 Object... TransactionTest Output: Enter key value: TransactionTest Output: Enter state value: TransactionTest Output: Searching for existing object with this key: 13 TransactionTest Output: Object 13 found. CMPSample1 Output: ******************* CMPSample1: afterBegin() **************88 CMPSample1 Output: Enter key value for CMP2 Entity Bean: CMPSample1 Output: Enter state value: CMPSample1 Output: -------Retrieving initial context... CMPSample1 Output: -------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://cobalt:900 CMPSample1 Output: -------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory CMPSample1 Output: -------Invoke: javax.naming.InitialContext(properties) CMPSample1 Output: CMPSample2Bean CMPSample1 Output: Retrieving the home interface... CMPSample1 Output: Searching for existing object with this key: 13 CMPSample1 Output: Object 13 found. CMPSample1 Output: State updated. CMPSample1 Output: ********************* CMPSample1: beforeCompletion() ************** CMPSample2 Output: ********************* CMPSample2: beforeCompletion() ************** CMPSample1 Output: ************************** CMPSample1: afterCompletion() ************ CMPSample2 Output: ************************** CMPSample2: afterCompletion() ************ TransactionTest Output: State updated.
358
TransactionTest Output: -------Starting Client-demarcated commited transaction Scenario... TransactionTest Output: -------Retrieving initial context... TransactionTest Output: -------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://cobalt:900 TransactionTest Output: -------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory TransactionTest Output: -------Invoke: javax.naming.InitialContext(properties) TransactionTest Output: Retrieving the home interface... TransactionTest Output: Retrieving User Transaction... TransactionTest Output: Transaction Status after mySessionCtx.getUserTransaction() is: 6 TransactionTest Output: ******************* TransactionTest: afterBegin() **************88 TransactionTest Output: Transaction Status after myTransaction.begin() is: 0 TransactionTest Output: CMPSample1 Object... TransactionTest Output: Enter key value: TransactionTest Output: Enter state value: TransactionTest Output: Searching for existing object with this key: 1 TransactionTest Output: Object 1 found. CMPSample1 Output: ******************* CMPSample1: afterBegin() **************88 CMPSample1 Output: Enter key value for CMP2 Entity Bean: CMPSample1 Output: Enter state value: CMPSample1 Output: -------Retrieving initial context... CMPSample1 Output: -------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://cobalt:900 CMPSample1 Output: -------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory CMPSample1 Output: -------Invoke: javax.naming.InitialContext(properties) CMPSample1 Output: CMPSample2Bean CMPSample1 Output: Retrieving the home interface... CMPSample1 Output: Searching for existing object with this key: 1 CMPSample1 Output: Object 1 found. CMPSample2 Output: ******************* CMPSample2: afterBegin() **************88 CMPSample1 Output: State updated. TransactionTest Output: State updated. TransactionTest Output: ********************* TransactionTest: beforeCompletion() ************** CMPSample1 Output: ********************* CMPSample1: beforeCompletion() ************** CMPSample2 Output: ********************* CMPSample2: beforeCompletion() ************** TransactionTest Output: ************************** TransactionTest: afterCompletion() ************ CMPSample1 Output: ************************** CMPSample1: afterCompletion() ************ CMPSample2 Output: ************************** CMPSample2: afterCompletion() ************ TransactionTest Output: Transaction Status after myTransaction.commit() is :6
359
TransactionTest Output: -------Starting Client-demarcated rollbacked transaction Scenario... TransactionTest Output: -------Retrieving initial context... TransactionTest Output: -------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://cobalt:900 TransactionTest Output: -------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory TransactionTest Output: -------Invoke: javax.naming.InitialContext(properties) TransactionTest Output: Retrieving the home interface... TransactionTest Output: ******************* TransactionTest: afterBegin() **************88 TransactionTest Output: Transaction Status after myTransaction.begin() is: 0 TransactionTest Output: CMPSample1 Object... TransactionTest Output: Enter key value: TransactionTest Output: Enter state value: TransactionTest Output: Searching for existing object with this key: toe TransactionTest Output: Object not found. Creating a new instance... TransactionTest Output: New Object instance created! CMPSample1 Output: ******************* CMPSample1: afterBegin() **************88 CMPSample1 Output: Enter key value for CMP2 Entity Bean: CMPSample1 Output: Enter state value: CMPSample1 Output: -------Retrieving initial context... CMPSample1 Output: -------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://cobalt:900 CMPSample1 Output: -------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory CMPSample1 Output: -------Invoke: javax.naming.InitialContext(properties) CMPSample1 Output: CMPSample2Bean CMPSample1 Output: Retrieving the home interface... CMPSample1 Output: Searching for existing object with this key: toe CMPSample1 Output: Object not found. Creating a new instance... CMPSample1 Output: New Object instance created! CMPSample2 Output: ******************* CMPSample2: afterBegin() **************88 CMPSample1 Output: State updated. TransactionTest Output: State updated. TransactionTest Output: ************************** TransactionTest: afterCompletion() ************ CMPSample1 Output: ************************** CMPSample1: afterCompletion() ************ CMPSample2 Output: ************************** CMPSample2: afterCompletion() ************ TransactionTest Output: Transaction Status after myTransaction.rollback() is :6
360
TransactionTest Output: -------Starting Container-demarcated transaction Scenario... TransactionTest Output: -------Retrieving initial context... TransactionTest Output: -------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://cobalt:900 TransactionTest Output: -------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory TransactionTest Output: -------Invoke: javax.naming.InitialContext(properties) TransactionTest Output: Retrieving the home interface... TransactionTest Output: CMPSample1 Object... TransactionTest Output: Enter key value: TransactionTest Output: Enter state value: TransactionTest Output: Searching for existing object with this key: 23 TransactionTest Output: Object 23 found. 109.054 00006c47 EJSRemote W Bean method raised execption: javax.jts.TransactionRequiredException java.lang.Throwable() java.lang.Exception() java.io.IOException() java.rmi.RemoteException() javax.jts.TransactionRequiredException() boolean com.transarc.jmon.container.tran.TransactionControlImpl$Mandatory.tranBegin(com.ibm.ejs.contain boolean com.transarc.jmon.container.tran.TransactionControlImpl.tranBeginControl(com.ibm.ejs.container.E boolean com.transarc.jmon.container.tran.TransactionControlImpl.tranBeginControl(com.ibm.ejs.container.E boolean com.ibm.ejs.container.EJSContainer.preInvoke(com.ibm.ejs.container.EJSRemote, int) boolean com.ibm.ejs.container.EJSEntityRemote.preInvoke(int) void com.alain.cmps.EJSRemoteCMPSample1.setState(java.lang.String) void com.alain.cmps._CMPSample1Skeleton.setState(java.lang.String) java.lang.Object com.alain.cmps._CMPSample1Skeleton._dispatch(com.alain.cmps.CMPSample1, int, long java.lang.Object [], org.omg.CORBA.Context) java.lang.Object com.alain.cmps._CMPSample1Skeleton._dispatch(int, int, long [], java.lang.Object [], org.omg.CORBA.Context) void com.ibm.CORBA.iiop.GenericServerSC.dispatch(com.ibm.CORBA.iiop.IIOPInputStream, com.ibm.CORBA.iiop.IIOPOutputStream) void com.ibm.CORBA.iiop.ORB.dispatch(com.ibm.CORBA.iiop.IIOPInputStream, com.ibm.CORBA.iiop.IIOPOutputStream) void com.ibm.CORBA.iiop.WorkerThread.run()
361
TransactionTest Output: -------Starting Client-demarcated commited transaction Scenario... TransactionTest Output: -------Retrieving initial context... TransactionTest Output: -------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://cobalt:900 TransactionTest Output: -------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory TransactionTest Output: -------Invoke: javax.naming.InitialContext(properties) TransactionTest Output: Retrieving the home interface... TransactionTest Output: Retrieving User Transaction... TransactionTest Output: Transaction Status after mySessionCtx.getUserTransaction() is: 6 TransactionTest Output: ******************* TransactionTest: afterBegin() **************88 TransactionTest Output: Transaction Status after myTransaction.begin() is: 0 TransactionTest Output: CMPSample1 Object... TransactionTest Output: Enter key value: TransactionTest Output: Enter state value: TransactionTest Output: Searching for existing object with this key: 1 TransactionTest Output: Object not found. Creating a new instance... TransactionTest Output: New Object instance created! CMPSample1 Output: Enter key value for CMP2 Entity Bean: CMPSample1 Output: Enter state value: CMPSample1 Output: -------Retrieving initial context... CMPSample1 Output: -------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://cobalt:900 CMPSample1 Output: -------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory CMPSample1 Output: -------Invoke: javax.naming.InitialContext(properties) CMPSample1 Output: CMPSample2Bean CMPSample1 Output: Retrieving the home interface... CMPSample1 Output: Searching for existing object with this key: 1 CMPSample1 Output: New Object instance created! CMPSample1 Output: State updated. TransactionTest Output: State updated. TransactionTest Output: ********************* TransactionTest: beforeCompletion() ************** TransactionTest Output: ************************** TransactionTest: afterCompletion() ************ TransactionTest Output: Transaction Status after myTransaction.commit() is :6 TransactionTest Output: -------Starting Client-demarcated rollbacked transaction Scenario... TransactionTest Output: -------Retrieving initial context... TransactionTest Output: -------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://cobalt:900 TransactionTest Output: -------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory TransactionTest Output: -------Invoke: javax.naming.InitialContext(properties) TransactionTest Output: Retrieving the home interface... TransactionTest Output: ******************* TransactionTest: afterBegin() **************88 TransactionTest Output: Transaction Status after myTransaction.begin() is: 0 TransactionTest Output: CMPSample1 Object... TransactionTest Output: Enter key value: TransactionTest Output: Enter state value: TransactionTest Output: Searching for existing object with this key: 9 066.434 00000992 EJSEntityHome < findOrActivateFromKey: object not found com.ibm.ejs.container.ContainerObjectNotFoundException java.lang.Throwable() java.lang.Exception() java.io.IOException() java.rmi.RemoteException() com.ibm.ejs.EJSException() com.ibm.ejs.container.ContainerException() com.ibm.ejs.container.ContainerObjectNotFoundException()
362
TransactionTest Output: -------Starting Client-demarcated commited transaction Scenario... TransactionTest Output: -------Retrieving initial context... TransactionTest Output: -------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://cobalt:900 TransactionTest Output: -------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory TransactionTest Output: -------Invoke: javax.naming.InitialContext(properties) TransactionTest Output: Retrieving the home interface... TransactionTest Output: Retrieving User Transaction... TransactionTest Output: Transaction Status after mySessionCtx.getUserTransaction() is: 6 TransactionTest Output: ******************* TransactionTest: afterBegin() **************88 TransactionTest Output: Transaction Status after myTransaction.begin() is: 0 TransactionTest Output: CMPSample1 Object... TransactionTest Output: Enter key value: TransactionTest Output: Enter state value: TransactionTest Output: Searching for existing object with this key: q TransactionTest Output: Object not found. Creating a new instance... TransactionTest Output: New Object instance created! CMPSample1 Output: ******************* CMPSample1: afterBegin() **************88 044.000 000058bd Transactional > lock com.transarc.encina.jts.CoordinatorImpl@26444#tid=3 IWRITE 044.051 000058bd Mutex E Mutex aquired forThread[Thread-10,5,main] 044.054 000058bd Transactional > conflict com.transarc.encina.jts.CoordinatorImpl@26444#tid=3 IWRITE 044.075 000058bd Transactional < conflict, true 044.077 000058bd Transactional > addWaiter, com.transarc.jmon.lock.Locker@7315 044.078 000058bd Transactional > isHolder 044.081 000058bd Transactional < isHolder, false, com.transarc.encina.jts.CoordinatorImpl@26444#tid=3 044.083 000058bd Transactional < addWaiter 044.084 000058bd Mutex E Mutex released 044.085 000058bd Transactional E Waiting for lock
363
TransactionTest Output: -------Starting Client-demarcated commited transaction Scenario... TransactionTest Output: -------Retrieving initial context... TransactionTest Output: -------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://cobalt:900 TransactionTest Output: -------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory TransactionTest Output: -------Invoke: javax.naming.InitialContext(properties) TransactionTest Output: Retrieving the home interface... TransactionTest Output: Retrieving User Transaction... TransactionTest Output: Transaction Status after mySessionCtx.getUserTransaction() is: 6 TransactionTest Output: ******************* TransactionTest: afterBegin() **************88 TransactionTest Output: Transaction Status after myTransaction.begin() is: 0 TransactionTest Output: CMPSample1 Object... TransactionTest Output: Enter key value: TransactionTest Output: Enter state value: TransactionTest Output: Searching for existing object with this key: qaz TransactionTest Output: Object not found. Creating a new instance... TransactionTest Output: New Object instance created! CMPSample1 Output: Enter key value for CMP2 Entity Bean: CMPSample1 Output: Enter state value: CMPSample1 Output: -------Retrieving initial context... CMPSample1 Output: -------Set properties to: javax.naming.Context.PROVIDER_URL, iiop://cobalt:900 CMPSample1 Output: -------Set properties to: com.ibm.jndi.CosNaming.CNInitialContextFactory CMPSample1 Output: -------Invoke: javax.naming.InitialContext(properties) CMPSample1 Output: CMPSample2Bean CMPSample1 Output: Retrieving the home interface... CMPSample1 Output: Searching for existing object with this key: qaz CMPSample1 Output: New Object instance created! CMPSample2 Output: ******************* CMPSample2: afterBegin() **************88 056.593 00002ccc Transactional > lock com.transarc.encina.jts.CoordinatorImpl@20391#tid=3 IWRITE 056.597 00002ccc Mutex E Mutex aquired forThread[Thread-14,5,main] 056.599 00002ccc Transactional > conflict com.transarc.encina.jts.CoordinatorImpl@20391#tid=3 IWRITE 056.724 00002ccc Transactional < conflict, true 056.727 00002ccc Transactional > addWaiter, com.transarc.jmon.lock.Locker@6c5f 056.729 00002ccc Transactional > isHolder 056.731 00002ccc Transactional < isHolder, false, com.transarc.encina.jts.CoordinatorImpl@20391#tid=3 056.733 00002ccc Transactional < addWaiter 056.735 00002ccc Mutex E Mutex released 056.748 00002ccc Transactional E Waiting for lock
364
C ITSOBANK database
C.1 database Definition DDL
We use te command line processor commands and SQL statements to create the database and the information within it. Figure 155 and Figure 156 show the definitions of the tables. Figure 157 shows the foreign key relationships and the grant statements.
365
echo --- create the ITSOBANK database --echo CREATE DATABASE ITSOBANK echo --- connect to ITSOBANK database --CONNECT TO ITSOBANK echo --- drop all tables --DROP TABLE ITSO.BANK DROP TABLE ITSO.CUSTOMER DROP TABLE ITSO.CARD DROP TABLE ITSO.POLICY DROP TABLE ITSO.ACCOUNT DROP TABLE ITSO.SAVINGS DROP TABLE ITSO.CHECKING DROP TABLE ITSO.PAYEE DROP TABLE ITSO.TRANSRECORD DROP TABLE ITSO.CARDACCOUNT DROP SYNONYM ITSO.TRANS echo --- creating tables --CREATE TABLE ITSO.BANK ( bankid CHAR( 4) NOT NULL, bankname CHAR(30) NOT NULL, PRIMARY KEY (BANKID) ) CREATE TABLE ITSO.CUSTOMER ( custid CHAR( 4) NOT NULL, title CHAR( 3) NOT NULL, fname CHAR(30) NOT NULL, lname CHAR(30) NOT NULL, userid CHAR( 8), password CHAR( 8), bankid CHAR( 4) NOT NULL, PRIMARY KEY (CUSTID) )
\ \ \ \
\ \ \ \ \ \ \ \ \
366
CREATE TABLE ITSO.ACCOUNT ( accid CHAR( 8) NOT NULL, bankid CHAR( 4), custid CHAR( 4) NOT NULL, acctype CHAR(10) NOT NULL, balance DEC(8,2) NOT NULL, PRIMARY KEY (ACCID) ) CREATE TABLE ITSO.SAVINGS ( accid CHAR(8) NOT NULL, minamt DECIMAL(8,2) NOT NULL, PRIMARY KEY (accid) ) CREATE TABLE ITSO.PAYEE ( accid CHAR(8) NOT NULL, title CHAR(20), PRIMARY KEY (accid) ) CREATE TABLE ITSO.CHECKING ( accid CHAR(8) NOT NULL, overdraf DECIMAL(8,2) NOT NULL, PRIMARY KEY (accid) ) CREATE TABLE ITSO.TRANSRECORD ( transid TIMESTAMP NOT NULL, accid CHAR( 8) NOT NULL, transtype CHAR( 1) NOT NULL, transamt DEC(8,2) NOT NULL, traccid CHAR( 8), PRIMARY KEY (TRANSID) )
\ \ \ \ \ \ \
\ \ \ \
\ \ \ \
\ \ \ \
\ \ \ \ \ \ \
ITSOBANK database
367
CREATE SYNONYM ITSO.TRANS FOR ITSO.TRANSRECORD echo --- referential integrity --ALTER TABLE ITSO.TRANSRECORD \ ADD CONSTRAINT "AccountTransrecord" FOREIGN KEY (ACCID) \ REFERENCES ITSO.ACCOUNT ON DELETE RESTRICT ALTER TABLE ITSO.ACCOUNT \ ADD CONSTRAINT "CustomerAccount" FOREIGN KEY (CUSTID) \ REFERENCES ITSO.CUSTOMER ON DELETE RESTRICT ALTER TABLE ITSO.ACCOUNT \ ADD CONSTRAINT "BankAccount" FOREIGN KEY (BANKID) REFERENCES ITSO.BANK ALTER TABLE ITSO.CUSTOMER \ ADD CONSTRAINT "BankCustomer" FOREIGN KEY (BANKID) REFERENCES ITSO.BANK ON DELETE RESTRICT
echo --- execute GRANT statements --GRANT BINDADD ON DATABASE GRANT CONNECT ON DATABASE GRANT ALL ON ITSO.BANK GRANT ALL ON ITSO.CUSTOMER GRANT ALL ON ITSO.ACCOUNT GRANT ALL ON ITSO.SAVINGS GRANT ALL ON ITSO.CHECKING GRANT ALL ON ITSO.PAYEE GRANT ALL ON ITSO.TRANSRECORD GRANT ALL ON ITSO.TRANS echo --- connect reset --CONNECT RESET
TO PUBLIC TO PUBLIC TO PUBLIC TO PUBLIC TO PUBLIC TO PUBLIC TO PUBLIC TO PUBLIC TO PUBLIC TO PUBLIC
368
You can either create the file itsobank.ddl from the above tables or get it from the CDROM or zip file that you can download from the ITSO web site in the subdirectory:
CdRom\Part2BankApplication
connect to ITSOBANK echo --- insert into BANK table --INSERT INTO ITSO.BANK (bankid, bankname ) VALUES (ITSO,THE ITSO BANK) echo --- insert into CUSTOMER table --INSERT INTO ITSO.CUSTOMER (custid, title, fname, lname, userid, password, bankid) VALUES (101, Mr., John, Akerley, cust101, JA, ITSO), (102, Mr., Pat, McCarthy, cust102, PM, ITSO), (103, Mr., Markus, Muetschard, cust103, MM, ITSO), (104, Mr., Joaquin, Picon, cust104, JP, ITSO), (105, Ms., Unknown, Lady, null, null, ITSO), (106, Mr., Ueli, Wahli, cust106, UW, ITSO), (901, THE, XYZ, CORPORATION, null, null, ITSO) \ \ \ \ \ \ \ \ \ \
ITSOBANK database
369
echo --- insert into ACCOUNT table --INSERT INTO ITSO.ACCOUNT (accid, bankid, custid, acctype, balance) VALUES (101-1001, ITSO, 101, CHECKING, 80.00), (101-1002, ITSO, 101, SAVINGS, 375.26), (102-2001, ITSO, 102, SAVINGS, 9375.26), (102-2002, ITSO, 102, CHECKING, 75.50), (103-3001, ITSO, 103, SAVINGS, 100.00), (103-3002, ITSO, 103, CHECKING, 222.22), (104-4001, ITSO, 104, CHECKING, 362.00), (104-4002, ITSO, 104, CHECKING, 5.00), (105-5001, ITSO, 105, CHECKING, 0.00), (106-6001, ITSO, 106, CHECKING, 1000.00), (106-6002, ITSO, 106, SAVINGS, 2000.00), (106-6003, ITSO, 106, SAVINGS, 3000.00), (106-6004, ITSO, 106, CHECKING, 4000.00), (901-9001, ITSO, 901, PAYEE, 4000.00) \ \ \ \ \ \ \ \ \ \ \ \ \ \
echo --- insert into SAVINGS table --INSERT INTO ITSO.SAVINGS (accid, minamt) VALUES (101-1002, 100.00), (102-2001, 100.00), (103-3001, 100.00), (106-6002, 100.00), (106-6003, 100.00) \ \ \ \ \
370
echo --- insert into CHECKING table --INSERT INTO ITSO.CHECKING (accid, overdraf) VALUES (101-1001, 200.00), (102-2002, 200.00), (103-3002, 200.00), (104-4001, 200.00), (104-4002, 200.00), (105-5001, 200.00), (106-6001, 200.00), (106-6004, 200.00) echo --- insert into PAYEE table --INSERT INTO ITSO.PAYEE (accid, title ) VALUES (901-9001, XYZ VISA) \ \ \ \ \ \ \ \ \ \ \
ITSOBANK database
371
echo --- insert into TRANSRECORD table --INSERT INTO ITSO.TRANSRECORD (transid, accid, transtype, transamt) VALUES (CURRENT TIMESTAMP, 101-1001, C, 80.00 ) INSERT INTO ITSO.TRANSRECORD (transid, accid, transtype, transamt) VALUES (CURRENT TIMESTAMP, 101-1002, C, 200.00 ) INSERT INTO ITSO.TRANSRECORD (transid, accid, transtype, transamt) VALUES (CURRENT TIMESTAMP, 102-2002, C, 75.50 ) INSERT INTO ITSO.TRANSRECORD (transid, accid, transtype, transamt) VALUES (CURRENT TIMESTAMP, 103-3001, C, 100.00 ) INSERT INTO ITSO.TRANSRECORD (transid, accid, transtype, transamt) VALUES (CURRENT TIMESTAMP, 104-4001, C, 200.00 ) INSERT INTO ITSO.TRANSRECORD (transid, accid, transtype, transamt) VALUES (CURRENT TIMESTAMP, 106-6001, D, 250.00 ) INSERT INTO ITSO.TRANSRECORD (transid, accid, transtype, transamt) VALUES (CURRENT TIMESTAMP, 106-6002, C, 400.00 ) INSERT INTO ITSO.TRANSRECORD (transid, accid, transtype, transamt) VALUES (CURRENT TIMESTAMP, 106-6003, C, 350.00 ) INSERT INTO ITSO.TRANSRECORD (transid, accid, transtype, transamt) VALUES (CURRENT TIMESTAMP, 106-6004, D, 100.00 ) INSERT INTO ITSO.TRANSRECORD (transid, accid, transtype, transamt, traccid) VALUES (CURRENT TIMESTAMP, 106-6001, T, 66.66, 106-6002 ) INSERT INTO ITSO.TRANSRECORD (transid, accid, transtype, transamt, traccid) VALUES (CURRENT TIMESTAMP, 106-6002, F, 66.66, 106-6001 ) \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \
372
373
We provide hereafter a complete list of packages, interfaces and classes created and generated by VisualAge for Java for the bank application:
u package ITSOBankEJBReserved
classes: AdminSB Bank BankAccount CheckingAccount CorporateAccount Customer SavingsAccount TransactionRecord UserSB
u package com.ibm.CORBA.java.Exception.itso.bank.ejb
BankTransactionExceptionValue
u package itso.bank.ejb
Interfaces: Bank BankAccount BankAccountBeanFinderHelper BankAccountHome BankBeanFinderHelper BankHome CheckingAccount CheckingAccountBeanFinderHelper CheckingAccountHome CorporateAccount CorporateAccountBeanFinderHelper CorporateAccountHome Customer CustomerBeanFinderHelper CustomerHome EJSFinderBankAccountBean EJSFinderBankBean EJSFinderCheckingAccountBean EJSFinderCorporateAccountBean EJSFinderCustomerBean EJSFinderSavingsAccountBean EJSFinderTransactionRecordBean SavingsAccount SavingsAccountBeanFinderHelper SavingsAccountHome
374
TransactionRecord TransactionRecordBeanFinderHelper TransactionRecordHome classes: BankAccountBean BankAccountHelper BankAccountHolder BankAccountHomeHelper BankAccountHomeHolder BankAccountKey BankAccountProxy BankAccountTestClient BankBean BankHelper BankHolder BankHomeHelper BankHomeHolder BankKey BankTestClient CheckingAccountBean CheckingAccountHelper CheckingAccountHolder CheckingAccountHomeHelper CheckingAccountHomeHolder CheckingAccountTestClient CorporateAccountBean CorporateAccountHelper CorporateAccountHolder CorporateAccountHomeHelper CorporateAccountHomeHolder CorporateAccountTestClient CustomerBean CustomerHelper CustomerHolder CustomerHomeHelper CustomerHomeHolder CustomerKey CustomerTestClient EJSBankAccountHome EJSBankHome EJSCheckingAccountHome EJSCorporateAccountHome EJSCustomerHome EJSJDBCFinderBankAccountBean EJSJDBCFinderBankBean
375
EJSJDBCFinderCheckingAccountBean EJSJDBCFinderCorporateAccountBean EJSJDBCFinderCustomerBean EJSJDBCFinderSavingsAccountBean EJSJDBCFinderTransactionRecordBean EJSJDBCPersisterBankAccountBean EJSJDBCPersisterBankBean EJSJDBCPersisterCheckingAccountBean EJSJDBCPersisterCorporateAccountBean EJSJDBCPersisterCustomerBean EJSJDBCPersisterSavingsAccountBean EJSJDBCPersisterTransactionRecordBean EJSRemoteBank EJSRemoteBankAccount EJSRemoteCheckingAccount EJSRemoteCorporateAccount EJSRemoteCustomer EJSRemoteSavingsAccount EJSRemoteTransactionRecord EJSSavingsAccountHome EJSTransactionRecordHome SavingsAccountBean SavingsAccountHelper SavingsAccountHolder SavingsAccountHomeHelper SavingsAccountHomeHolder SavingsAccountTestClient TransactionRecordBean TransactionRecordHelper TransactionRecordHolder TransactionRecordHomeHelper TransactionRecordHomeHolder TransactionRecordKey TransactionRecordTestClient _BankAccountHomeSkeleton _BankAccountHomeStub _BankAccountSkeleton _BankAccountStub _BankHomeSkeleton _BankHomeStub _BankSkeleton _BankStub _CheckingAccountHomeSkeleton _CheckingAccountHomeStub _CheckingAccountSkeleton
376
_CheckingAccountStub _CorporateAccountHomeSkeleton _CorporateAccountHomeStub _CorporateAccountSkeleton _CorporateAccountStub _CustomerHomeSkeleton _CustomerHomeStub _CustomerSkeleton _CustomerStub _SavingsAccountHomeSkeleton _SavingsAccountHomeStub _SavingsAccountSkeleton _SavingsAccountStub _TransactionRecordHomeSkeleton _TransactionRecordHomeStub _TransactionRecordSkeleton _TransactionRecordStub
upackage itso.bank.ejb.base
377
SingleLink
u package itso.bank.ejb.sb.admin
interfaces: AdminSB AdminSBHome classes: AdminSBBean AdminSBHelper AdminSBHolder AdminSBHomeHelper AdminSBHomeHolder AdminSBTestClient EJSAdminSBHome EJSRemoteAdminSB _AdminSBHomeSkeleton _AdminSBHomeStub _AdminSBSkeleton _AdminSBStub
u package itso.bank.ejb.sb.user
interfaces: UserSB UserSBHome classes: EJSRemoteUserSB EJSUserSBHome UserSBBean UserSBHelper UserSBHolder UserSBHomeHelper UserSBHomeHolder UserSBTestClient _UserSBHomeSkeleton _UserSBHomeStub _UserSBSkeleton _UserSBStub
u package itso.bank.ejb.sb.user.UserSBPackage.java.lang
378
E Special Notices
This publication is intended to help application developers using VisualAge for Java to create distributed objects applications based on Enterprise JavaBeans.The information in this publication is not intended as the specification of any programming interfaces that are provided by VisualAge for Java enterprise Edition. See the PUBLICATIONS section of the IBM Programming Announcement for VisualAge for Java Enterprise Edition for more information about what publications are considered to be product documentation. References in this publication to IBM products, programs or services do not imply that IBM intends to make these available in all countries in which IBM operates. Any reference to an IBM product, program, or service is not intended to state or imply that only IBMs product, program, or service may be used. Any functionally equivalent program that does not infringe any of IBMs intellectual property rights may be used instead of the IBM product, program or service. Information in this book was developed in conjunction with use of the equipment specified, and is limited in application to those specific hardware and software products and levels. IBM may have patents or pending patent applications covering subject matter in this document. The furnishing of this document does not give you
379
any license to these patents. You can send license inquiries, in writing, to the IBM Director of Licensing, IBM Corporation, 500 Columbus Avenue, Thornwood, NY 10594 USA. Licensees of this program who wish to have information about it for the purpose of enabling: (i) the exchange of information between independently created programs and other programs (including this one) and (ii) the mutual use of the information which has been exchanged, should contact IBM Corporation, Dept. 600A, Mail Drop 1329, Somers, NY 10589 USA. Such information may be available, subject to appropriate terms and conditions, including in some cases, payment of a fee. The information contained in this document has not been submitted to any formal IBM test and is distributed AS IS. The use of this information or the implementation of any of these techniques is a customer responsibility and depends on the customers ability to evaluate and integrate them into the customers operational environment. While each item may have been reviewed by IBM for accuracy in a specific situation, there is no guarantee that the same or similar results will be obtained elsewhere. Customers attempting to adapt these techniques to their own environments do so at their own risk. Any pointers in this publication to external Web sites are provided for convenience only and do not in any manner serve as an endorsement of these Web sites. The following terms are trademarks of the International Business Machines Corporation in the United States and/or other countries:
IBM DB2 S/390 ThinkPad MVS OS/390 VisualAge
The following terms are trademarks of other companies: C-bus is a trademark of Corollary, Inc. in the United States and/or other countries. Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and/or other countries. Microsoft, Windows, Windows NT, and the Windows logo are trademarks of
380
Microsoft Corporation in the United States and/or other countries. PC Direct is a trademark of Ziff Communications Company in the United States and/or other countries and is used by IBM Corporation under license. ActionMedia, LANDesk, MMX, Pentium and ProShare are trademarks of Intel Corporation in the United States and/or other countries. (For a complete list of Intel trademarks see www.intel.com/dradmarx.htm) UNIX is a registered trademark in the United States and/or other countries licensed exclusively through X/Open Company Limited. Other company, product, and service names may be trademarks or service marks of others.
Special Notices
381
382
F Related Publications
The publications listed in this section are considered particularly suitable for a more detailed discussion of the topics covered in this redbook.
Collection:
CBConnector
Bank
u Application Development with VisualAge for Java Enterprise, SG24-5081 u VisualAge for Java Enterprise Version 2 Team Support, SG24-5245 u Programming with VisualAge for Java, published by Prentice Hall,
383
SG24-5246
u Factoring JavaBeans in the Enterprise, SG24-5051 u From Client/Server to Network Computing, A Migration to Java,
SG24-2247
u JavaBeans by Example: Cooking with Beans in the Enterprise,
SG24-2035
u VisualAge for Java Enterprise Version 2
384
5429ord.fm
PUBORDER to order hardcopies in the United States Tools Disks To get LIST3820s of redbooks, type one of the following commands:
TOOLCAT REDPRINT TOOLS SENDTO EHONE4 TOOLS2 REDPRINT GET SG24xxxx PACKAGE TOOLS SENDTO CANVM2 TOOLS REDPRINT GET SG24xxxx PACKAGE (Canadian users only)
To register for information on workshops, residencies, and redbooks, type the following command:
TOOLS SENDTO WTSCPOK TOOLS ZDISK GET ITSOREGI 1998
REDBOOKS Category on INEWS Online send orders to: USIB6FPL at IBMMAIL or DKIBMBSH at IBMMAIL Redpieces For information so current it is still in the process of being written, look at "Redpieces" on the Redbooks Web Site (http://www.redbooks.ibm.com/redpieces.html). Redpieces are redbooks in progress; not all redbooks become redpieces, and sometimes just a few chapters will be published this way. The intent is to get the information out much quicker than the formal publishing process allows.
385
5429ord.fm
1-800-IBM-4FAX (United States) or (+1) 408 256 5422 (Outside USA) ask for: Index # 4421 Abstracts of new redbooks Index # 4422 IBM redbooks Index # 4420 Redbooks for last six months On the World Wide Web Redbooks Web Site IBM Direct Publications Catalog http://www.redbooks.ibm.com http://www.elink.ibmlink.ibm.com/pbl/pbl
386
5429ord.fm
Redpieces For information so current it is still in the process of being written, look at "Redpieces" on the Redbooks Web Site (http://www.redbooks.ibm.com/redpieces.html). Redpieces are redbooks in progress; not all redbooks become redpieces, and sometimes just a few chapters will be published this way. The intent is to get the information out much quicker than the formal publishing process allows.
387
5429ord.fm
First name Company Address City Telephone number Invoice to customer number Credit card number
Last name
Card issued to
Signature
We accept American Express, Diners, Eurocard, Master Card, and Visa. Payment by credit card not available in all countries. Signature mandatory for credit card payment.
388
5429glos.fm
Glossary
This glossary defines terms and abbreviations that are used in this book. If you do not find the term you are looking for, refer to the IBM Dictionary of Computing, New York: McGraw-Hill, 1994. This glossary includes terms and definitions from the American National Standard Dictionary for Information Systems, ANSI X3.172-1990, copyright 1990 by the American National Standards Institute (ANSI). Copies may be purchased from the American National Standards Institute, 1430 Broadway, New York, New York 10018. can be remotely invoked, usually by some for of remote object method call. argument. A data element, or value, included as a bean in a method call. Arguments provide additional information that the called method can use to perform the requested operation. attribute. A specification of a property of a bean. For example, a customer bean could have a name attribute and an address attribute. An attribute can itself be a bean with its own behavior and attributes. In the Data Access Builder, the aspect of a schema mapping that represents a column in a database table.
A
abstract class. A class that provides common behavior across a set of subclasses but is not itself designed to have instances that work. An abstract class represents a concept; classes derived from it represent implementations of the concept. See also base class. access application. Generated by the Data Access Builder for each schema mapping, an executable GUI that provides access to the database using the other classes generated for the mapping. accessor methods. Methods that an object provides to define the interface to its instance variables. The accessor method to return the value of an instance variable is called a get method or getter method, and the accessor method to assign a value to an instance variable is called a set method or setter method. applet. A Java program designed to run within a Web browser. Contrast with application. application. In Java programming, a self-contained, stand-alone Java program that includes a main() method. Contrast with applet. application server. A server program that allows the installation of application specific software components, in a manner so that they
B
base class. A class from which other classes or beans are derived. A base class may itself be derived from another base class. See also abstract class. bean. A definition or instance of a JavaBeans component. See also JavaBeans. BeanInfo. (1) A companion class for a bean that defines a set of methods that can be accessed to retrieve information on the beans properties, events, and methods. (2) In the VisualAge for Java IDE, a page in the class browser that provides bean information. Bean-managed persistence. When an Enterprise JavaBeans performs its own long-term state management. beans palette. In the Visual Composition Editor, a two-column pane that contains prefabricated beans that you can select and manipulate to create programs. The left column contains categories of beans, and the right column contains beans for the selected category. The default set of beans generally represents JDK AWT components. You can add your own categories and beans to the beans palette. break point. A point in a computer program where the execution can be halted.
389
5429glos.fm
browser. (1) In VisualAge for Java, a window that provides information on program elements. There are browsers for projects, packages, classes, methods, and interfaces. (2) An Internet-based tool that lets users browse Web sites.
another location and awaits a response. The requesting program is called a client, and the answering program is called a server. client-side server proxy. Generated by the RMI Access Builder, a local representative of a remote bean. This proxy provides access to the operations of the server bean, allowing a Java client to work with it as if it were the server bean. See also proxy bean and server-side server proxy. Class Browser. In the VisualAge for Java IDE, a tool used to browse the classes loaded in the workspace. collection. A set of features in which each feature is an object. commit. The operation that ends a unit of work and updates the database such that other processes can access any changes made. Common Object Request Broker Architecture (CORBA). A middleware specification which defines a software busthe Object Request Broker (ORB)that provides the infrastructure. communications area (COMMAREA). In a CICS transaction program, a group of records that describes both the format and volume of data used. component model. An architecture and an API that allows developers to define reusable segments of code that can be combined to create a program. VisualAge for Java uses the JavaBeans component model. composite bean. A bean that is composed of a bean and one or more subbeans. A composite bean can contain visual beans, nonvisual beans, or both. See also nonvisual bean, bean, and visual bean. concrete class. A subclass of an abstract class that is a specialization of the abstract class. connection. In the Visual Composition Editor, a visual link between two components that represents the relationship between the components. Each connection has a source, a target, and other properties. See also
C
C++ Access Builder. A VisualAge for Java Enterprise tool that generates beans to access C and C++ DLLs. category. In the Visual Composition Editor, a selectable grouping of beans represented by an icon in the left-most column. Selecting a category displays the beans belonging to that category in the next column. See also beans palette. CICS Access Builder. A VisualAge for Java Enterprise tool that generates beans to access CICS transactions through the CICS Gateway for Java and CICS Client. CICS Client. A server program that processes CICS ECI calls, forwarding transaction requests to a CICS program running on a host. CICS ECI. An API that provides C and C++ programs with procedural access to transactions. CICS Gateway for Java. A server program that processes Java ECI calls and forwards CICS ECI calls to the CICS Client. class. An aggregate that defines properties, operations, and behavior for all instances of that aggregate. class hierarchy. The relationships between classes that share a single inheritance. All Java classes inherit from the Object class. class library. A collection of classes. class method. See method. CLASSPATH. In your deployment environment, the environment variable that specifies the directories in which to look for class and resource files. client/server. The model of interaction in distributed data processing where a program at one location sends a request to a program at
390
5429glos.fm
DB2 for MVS/ESA. An IBM relational database management system for the MVS operating system. double-byte character set (DBCS). A set of characters in which each character is represented by 2 bytes. Languages such as Japanese, Chinese, and Korean, which contain more symbols than can be represented by 256 code points, require double-byte character sets. Compare with single-byte character set. Distributed Computing Environment (DCE). Adopted by the computer industry as a de facto standard for distributed computing. DCE allows computers from a variety of vendors to communicate transparently and share resources such as computing power, files, printers, and other objects in the network. Distributed Component Object Model (DCOM). A protocol that enables software components to communicate directly over a network in a reliable, secure, and efficient manner. Previously called "Network OLE," DCOM is designed for use across multiple network transports, including Internet protocols such as HTTP. DCOM is based on the Open Software Foundation's DCE-RPC specification and works with both Java applets and ActiveX components through its use of the Component Object Model (COM). dynamic link library (DLL). A file containing executable code and data bound to a program at run time rather than at link time. The C++ Access Builder generates beans and C++ wrappers that let your Java programs access C++ DLLs.
event-to-method connection, event-to-property connection, parameter connection, property-to-method connection, and property-to-property connection. console. In VisualAge for Java, the window that acts as the standard input (System.in) and standard output (System.out) device for programs running in the VisualAge for Java IDE. Container-managed persistence. When an Enterprise JavaBeans server manages a beans long term state. construction from parts. A software development technology in which applications are assembled from existing and reusable software components, known as parts. In VisualAge for Java, parts are called beans. constructor. A special class method that has the same name as the class and is used to construct and possibly initialize objects of its class type. container. A component that can hold other components. In Java, examples of containers include applets, frames, and dialogs. In the Visual Composition Editor, containers can be graphically represented and generated. current edition. The edition of a program element that is currently in the workspace. See also open edition. cursor. A database control structure used by the Data Access Builder to point to a specific row within some ordered set of rows and to retrieve rows from a set, possibly making updates or deletions.
D
data abstraction. A data type with a private representation and a public set of operations. The Java language uses the concept of classes to implement data abstraction. Data Access Builder. A VisualAge for Java Enterprise tool that generates beans to access and manipulate the content of JDBC/ODBC-compliant relational databases.
E
edition. A specific cut of a program element. VisualAge for Java supports multiple editions of program elements. See also current edition, open edition, and versioned edition. encapsulation. The hiding of a software objects internal representation. The object provides an interface that queries and manipulates the data without exposing its underlying structure.
391
5429glos.fm
enterprise access builders. In VisualAge for Java Enterprise, a set of code-generation tools. See also C++ Access Builder, CICS Access Builder, Data Access Builder, and RMI Access Builder. Enterprise JavaBeans. A server component developed by SUN Microsystems. event. An action by a user program, or a specification of a notification that may trigger specific behavior. In JDK 1.1, events notify the relevant listener classes to take appropriate actions. event-to-method connection. A connection from an event generated by a bean to a method of another bean. When the connected event occurs, the method is executed. See also connection. event-to-property connection. A connection that changes the value of a property when a certain event occurs. See also connection.
G
garbage collection. A Smalltalk process for periodically identifying unreferenced objects and deallocating their memory. gateway. A host computer that connects networks that communicate in different languages. For example, a gateway connects a companys LAN to the Internet. graphical user interface (GUI). A type of interface that enables users to communicate with a program by manipulating graphical features, rather than by entering commands. Typically, a graphical user interface includes a combination of graphics, pointing devices, menu bars and other menus, overlapping windows, and icons.
H
hypertext. Text in a document that contains a hidden link to other text. You can click a mouse on a hypertext word and it will take you to the text designated in the link. Hypertext is used in Windows help programs and CD encyclopedias to jump to related references elsewhere within the same document. Hypertext can linkusing HTTP over the Webto any Web document in the world, with only a single mouse click. Hypertext Markup Language (HTML). The basic language that is used to build hypertext documents on the World Wide Web. It is used in basic, plain ASCII-text documents, but when those documents are interpreted (rendered) by a Web browser such as Netscape, the document can display formatted text, color, a variety of fonts, graphics images, special effects, hypertext jumps to other Internet locations, and information forms. Hypertext Transfer Protocol (HTTP). The protocol for moving hypertext files across the Internet. Requires an HTTP client program on one end, and an HTTP server program on the other end.
F
feature. (1) A major component of a software product that can be installed separately. (2) In VisualAge for Java, a method, field, or event that is available from a beans interface and to which other beans can connect. field. A data object in a class. For example, a customer class could have a name field and an address field. A field can itself be an object with its own behavior and fields. By default, a field, in contrast to a property, does not support event notification. free-form surface. The large open area of the Visual Composition Editor where you can work with visual and nonvisual beans. You add, remove, and connect beans on the free-form surface. framework. A set of cooperative classes with strong connections that provide a template for development.
392
5429glos.fm
I
inheritance. (1) A mechanism by which an object class can use the attributes, relationships, and methods defined in more abstract classes related to it (its base classes). (2) An object-oriented programming technique that allows you to use existing classes as bases for creating other classes. instance. Synonym for object, a particular instantiation of a data type. Integrated Development Environment (IDE). In VisualAge for Java, the set of windows that provide the user with access to development tools. The primary windows are Workbench, Log, Console, Debugger, and Repository Explorer. interchange file. A file that you can export from VisualAge for Java that contains information about selected projects or packages. This file can then be imported into any VisualAge for Java session. interface. A set of methods that can be accessed by any class in the class hierarchy. The Interface page in the Workbench lists all interfaces in the workspace. Internet. The vast collection of interconnected networks that use TCP/IP and evolved from the ARPANET of the late 1960s and early 1970s. intranet. A private network, inside a company or organization, that uses the same kinds of software that you would find on the public Internet. Many of the tools used on the Internet are being used in private networks; for example, many companies have Web servers that are available only to employees. Internet Protocol (IP). The rules that provide basic Internet functions. See Transmission Control Protocol/Internet Protocol. IP number. An Internet address that is a unique number consisting of four parts separated by dots, sometimes called a dotted quad (for example: 198.204.112.1). Every Internet computer has an IP number, and most computers also have one or more domain names that are plain language substitutes for the dotted quad.
J
Java. A programming language invented by Sun Microsystems that is specifically designed for writing programs that can be safely downloaded to your computer through the Internet and immediately run without fear of viruses or other harm to your computer or files. Using small Java programs (called applets), Web pages can include functions such as animation, calculators, and other fancy tricks. We can expect to see a huge variety of features added to the Web through Java, because you can write a Java program to do almost anything a regular computer program can do and then include that Java program in a Web page. Java archive (JAR). A platform-independent file format that groups many files into one. JAR files are used for compression, reduced download time, and security. Because the JAR format is written in Java, JAR files are fully extensible. JavaBeans. In JDK 1.1, the specification that defines the platform-neutral component model used to represent parts. Instances of JavaBeans (often called beans) may have methods, properties, and events. Java Database Connectivity (JDBC). In JDK 1.1, the specification that defines an API that enables programs to access databases that comply with this standard. Java Naming and Directory Interace. The Java standard API for accessing directory services, such as LDAP, COS Naming, and others. Java Native Interface (JNI). In JDK 1.1, the specification that defines a standard naming and calling convention so that the Java virtual machine can locate and invoke methods written in a language different from Java. See also native method. JTA. Java transaction API. JTS. The Java Transaction Service based on the CORBA Transaction Service which provides a way for middleware vendors to build interoperable transactional middleware.
393
5429glos.fm
K
keyword. A predefined word, reserved for Java, that cannot be used as an identifier.
L
LDAP. Lightweight Directory Access Protocol for accessing X.500 directories. legacy code. Existing code that a user might have. Legacy applications often have character-based, nongraphical user interfaces. Usually they are written in a non-object-oriented language, such as C or COBOL. listener. In JDK 1.1, a class that receives and handles events. local area network (LAN). A computer network located on a users establishment within a limited geographical area. A LAN typically consists of one or more server machines providing services to a number of client workstations. log. In VisualAge for Java, the window that displays messages and warnings during development.
message. A request from one object that the receiving object implement a method. Because data is encapsulated and not directly accessible, a message is the only way to send data from one object to another. Each message specifies the name of the receiving object, the method to be implemented, and any arguments the method needs for implementation. Synonym for method call. model. A nonvisual bean that represents the state and behavior of an object, such as a customer or an account. Contrast with view.
N
native method. Method written in a language other than Java that can be called by a Java object through the JNI specification. named package. In the VisualAge for Java IDE, a package that has been explicitly named and created. nonvisual bean. In the Visual Composition Editor, a bean that has no visual representation at run time. A nonvisual bean typically represents some real-world object that exists in the business environment. Compare with model. Contrast with view and visual bean. notification framework. In JDK 1.1, a set of classes that implement the notifier/listener protocol. The notification framework is the base of the construction from beans technology (Visual Composition Editor).
M
mapping. See schema mapping. member. (1) A data object in a structure or a union. (2) In Java, classes and structures can also contain functions and types as members. method. A fragment of Java code within a class that can be invoked and passed a set of parameters to perform a specific task. method call. A communication from one object to another that requests the receiving object to execute a method. A method call consists of a method name that indicates the requested method and the arguments to be used in executing the method. The method call always returns some object to the requesting object as the result of performing the method. Synonym for message.
O
object. (1) A computer representation of something that a user can work with to perform a task. An object can appear as text or an icon. (2) A collection of data and methods that operate on that data, which together represent a logical entity in the system. In object-oriented programming, objects are grouped into classes that share common data definitions and methods. Each object in the class is said to be an instance of the class. (3) An instance of an object class consisting of attributes, a data structure, and operational methods. It can represent a
394
5429glos.fm
operation. A method or service that can be requested of an object. overloading. An object-oriented programming technique that allows redefinition of methods when the methods are used with class types.
person, place, thing, event, or concept. Each instance has the same properties, attributes, and methods as other instances of the object class, although it has unique values assigned to its attributes. object class. A template for defining the attributes and methods of an object. An object class can contain other object classes. An individual representation of an object class is called an object. object factory. A nonvisual bean capable of dynamically creating new instances of a specified bean. For example, during the execution of an application, an object factory can create instances of a new class to collect the data being generated. object-oriented programming (OOP). A programming approach based on the concepts of data abstraction and inheritance. Unlike procedural programming techniques, object-oriented programming concentrates on those data objects that constitute the problem and how they are manipulated, not on how something is accomplished. Object Request Broker (ORB). A CORBA term designating the means by which objects transparently make requests and receive responses from objects, whether they are local or remote. ODBC driver. A DLL that implements ODBC function calls and interacts with a data source. Open Database Connectivity (ODBC). A Microsoft developed C database API that allows access to database management systems calling callable SQL, which does not require the use of an SQL preprocessor. In addition, ODBC provides an architecture that allows users to add modules (database drivers) that link the application to their choice of database management systems at run time. Applications no longer need to be directly linked to the modules of all the database management systems that are supported. open edition. An edition of a program element that can still be modified; that is, the edition has not been versioned. An open edition may reside in the workspace as well as in the repository.
P
package. A program element that contains related classes and interfaces. palette. See beans palette. parameter connection. A connection that satisfies a parameter of an action or method by supplying either a propertys value or the return value of an action, method, or script. The parameter is always the source of the connection. See also connection. parent class. The class from which another bean or class inherits data, methods, or both. part. An existing, reusable software component. In VisualAge for Java, all parts created with the Visual Composition Editor conform to the JavaBeans component model and are referred to as beans. See also nonvisual bean and visual bean. Compare with Class Editor and Composition Editor. primitive bean. A basic building block of other beans. A primitive bean can be relatively complex in terms of the function it provides. private. In Java, an access modifier associated with a class member. It allows only the class itself to access the member. process. A collection of code, data, and other system resources, including at least one thread of execution, that performs a data processing task. program. In VisualAge for Java, a term that refers to both Java applets and applications. project. In VisualAge for Java, the topmost kind of program element. A project contains Java packages. promote features. Make features of a subbean available to be used for making connections. This applies to subbeans that are to be included in other beans, for example, a subbean consisting of
395
5429glos.fm
three push buttons on a panel. If this sample subbean is placed in a frame, the features of the push buttons would have to be promoted to make them available from within the frame. property. An initial setting or characteristic of a bean; for example, a name, font, text, or positional characteristic. property sheet. In the Visual Composition Editor, a set of name-value pairs that specify the initial appearance and other bean characteristics. A beans property sheet can be viewed from the Properties secondary window. property-to-method connection. A connection that calls a method whenever a propertys value changes. It is similar to an event-to-method connection because the propertys event ID is used to notify the method when the value of the property changes. See also connection. property-to-property connection. A connection from a property of one bean to a property of another bean. When one property is updated, the other property is updated automatically. See also connection. property-to-method connection. A connection from a property of a bean to a method. When the property undergoes a state change, the method is called. See also connection. protected. In Java, an access modifier associated with a class member. It allows the class itself, subclasses, and all classes in the same package to access the member. protocol. (1) The set of all messages to which an object will respond. (2) Specification of the structure and meaning (the semantics) of messages that are exchanged between a client and a server. (3) Computer rules that provide uniform specifications so that computer hardware and operating systems can communicate. It is similar to the way that mail, in countries around the world, is addressed in the same basic format so that postal workers know where to find the recipients address, the senders return address, and the postage stamp. Regardless of the underlying language, the basic protocols remain the same.
prototype. A method declaration or definition that includes both the return type of the method and the types of its arguments. proxy bean. A group of client-side and server-side objects that represent a remote server bean. The top-level class that implements the proxy bean is the client-side server proxy. See also client-side server proxy and server-side server proxy.
R
Remote Method Invocation (RMI). In JDK 1.1, the API that enables you to write distributed Java programs, allowing methods of remote Java objects to be accessed from other Java virtual machines. remote object instance manager. Creates and manages instances of RMI server beans through their associated server-side server proxies. repository. In VisualAge for Java, the storage area, separate from the workspace, that contains all editions (both open and versioned) of all program elements that have ever been in the workspace, including the current editions that are in the workspace. You can add editions of program elements to the workspace from the repository. Repository Explorer. In VisualAge for Java, the window from which you can view and compare editions of program elements that are in the repository. resource file. A noncode file that can be referred to from your Java program in VisualAge for Java. Examples include graphics and audio files. RMI Access Builder. A VisualAge for Java Enterprise tool that generates proxy beans and associated classes and interfaces so you can distribute code for remote access, enabling Java-to-Java solutions. RMI compiler. The compiler that generates stub and skeleton files that facilitate RMI communication. This compiler can be automatically invoked by the RMI Access Builder or from the Tools menu item.
396
5429glos.fm
add multiple beans of the same class (for example, three push buttons) without going back and forth between the beans palette and the free-form surface. stored procedure. A procedure that is part of a relational database. The Data Access Builder can generate Java code that accesses stored procedures. superclass. See abstract class and base class.
RMI registry. A server program that allows remote clients to get a reference to a server bean. roll back. The process of restoring data changed by SQL statements to the state at its last commit point.
S
schema. In the Data Access Builder, the representation of the database that will be mapped. schema mapping. In the Data Access Builder, a set of definitions for all attributes matching all columns for your database table, view, or SQL statement. The mapping contains the information required by the Data Access Builder to generate Java classes. Scrapbook. In VisualAge for Java, the window from which you can write and test fragments of code, without having to define an encompassing class or method. server. A computer that provides services to multiple users or workstations in a network; for example, a file server, a print server, or a mail server. server bean. The bean that is distributed using RMI services and deployed on a server. server-side server proxy. Generated by the RMI Access Builder, a companion class to the client-side server proxy, facilitating client-side server proxy communication over RMI. See also client-side server proxy and proxy bean. service. A specific behavior that an object is responsible for exhibiting. single-byte character set. A set of characters in which each character is represented by a 1byte code. SmartGuide. In IBM software products, an interface that guides you through performing common tasks. SQL predicate. The conditional part of an SQL statement. sticky. In the Visual Composition Editor, the mode that enables an application developer to
T
Transmission Control Protocol/Internet Protocol (TCP/IP). The basic programming foundation that carries computer messages around the globe through the Internet. The suite of protocols that defines the Internet. Originally designed for the UNIX operating system, TCP/IP software is now available for every major kind of computer operating system. To be truly on the Internet, your computer must have TCP/IP software. tear-off property. A property that a developer has exposed to work with as though it were a stand-alone bean. thread. A unit of execution within a process. tool bar. The strip of icons along the top of the free-form surface. The tool bar contains tools to help an application developer construct composite beans. transaction. In a CICS program, an event that queries or modifies a database that resides on a CICS server. type. In VisualAge for Java, a generic term for a class or interface.
U
Unicode. A character coding system designed to support the interchange, processing, and display of the written texts of the diverse languages of the modern world. Unicode characters are normally encoded using 16-bit integral unsigned numbers.
397
5429glos.fm
uniform resource locator (URL). A standard identifier for a resource on the World Wide Web, used by Web browsers to initiate a connection. The URL includes the communications protocol to use, the name of the server, and path information identifying the objects to be retrieved on the server. A URL looks like this: http://www.matisse.net/seminars.html or telnet://well.sf.ca.us.br or news:new.newusers.question.br
visual programming tool. A tool that provides a means for specifying programs graphically. Application programmers write applications by manipulating graphical representations of components. Visual Composition Editor. In VisualAge for Java, the tool where you can create graphical user interfaces from prefabricated beans and define relationships (connections) between both visual and nonvisual beans. The Visual Composition Editor is a page in the class browser.
user interface (UI). (1) The hardware, software, or both that enables a user to interact with a computer. (2) The visual presentation and its underlying software with which a user interacts.
W
Workbench. In VisualAge for Java, the main window from which you can manage the workspace, create and modify code, and open browsers and other tools. workspace. The work area that contains all the code you are currently working on (that is, current editions). The workspace also contains the standard Java class libraries and other class libraries. Your glossary term, acronym or abbreviation. Term definition
V
variable. (1) A storage place within an object for a data feature. The data feature is an object, such as number or date, stored as an attribute of the containing object. (2) A bean that receives an identity at run time. A variable by itself contains no data or program logic; it must be connected such that it receives run-time identity from a bean elsewhere in the application. versioned edition. An edition that has been versioned and can no longer be modified. versioning. The act of making an open edition a versioned edition; that is, making the edition read-only. view. (1) A visual bean, such as a window, push button, or entry field. (2) A visual representation that can display and change the underlying model objects of an application. Views are both the end result of developing an application and the basic unit of composition of user interfaces. Compare with visual bean. Contrast with model. visual bean. In the Visual Composition Editor, a bean that is visible to the end user in the graphical user interface. Compare with view. Contrast with nonvisual bean.
398
5429abrv.fm
List of
IDL
interface definition language Internet Inter-ORB Protocol Information Management System interoperable object reference International Technical Support Organization Java archive Java Database Connectivity Java Developers Kit Java Native Interface Java Virtual Machine local area network managed object framework Multiple Virtual Storage National Language Support new technology Open Database Connectivity Object Management Group object modeling technique object-oriented object-oriented analysis object-oriented design Object Request Broker Operating System/2 object transaction service personal identification number rapid application development relational database management system Remote Method Invocation single-byte character set Software Developers Kit structured query language Transmission Control Protocol/Internet Protocol
Abbreviations
ANSI API ATM AWT CAE CB CICS CLI COM CORBA COS DB2 DBCS DBMS DL/I DLL DNS DRDA ECD ECI FTP GUI HTML HTTP IBM IDE
American National Standards Institute application programming interface automated teller machine Abstract Windowing Toolkit Client Access Enabler Component Broker Customer Information Control System call level interface Component Object Model Common Object Request Broker Architecture CORBA object services DATABASE 2 double-byte character set database management system Data Language/I dynamic link library domain name server Distributed Relational Database Architecture edit-compile-debug external call interface File Transfer Protocol graphical user interface Hypertext Markup Language Hypertext Transfer Protocol International Business Machines Corporation integrated development environment
IIOP IMS IOR ITSO JAR JDBC JDK JNI JVM LAN MOFW MVS NLS NT ODBC OMG OMT OO OOA OOD ORB OS/2 OTS PIN RAD RDBMS RMI SBCS SDK SQL TCP/IP
399
5429abrv.fm
TP UOW URL WWW
transaction processing unit of work uniform resource locator World Wide Web
400
Index
D
DCOM 7 Distributed Component Object Model see DCOM
E
EJB announcement 11 assembler 12 bean-managed persistence 14 components 13 container 13 container-managed persistence 15 deployer 12 Deployment Descriptor 13 entity beans 14 PrimaryKey 15 provider 12 server provider 13 session beans 14 system administrator 13
M
Method
401
V
Visual Composition Editor palette 390
402
_ IBM employee
Please rate your overall satisfaction with this book using the scale: (1 = very good, 2 = good, 3 = average, 4 = poor, 5 = very poor) Overall Satisfaction Please answer the following questions: Was this redbook published in time for your needs? If no, please explain: Yes___ No___ __________
Comments/Suggestions:
403
404
SG24-5429-00
406