Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 111 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
111
Dung lượng
1,04 MB
Nội dung
and the entity element defined as <!ELEMENT entity (description?, display-name?, small-icon?, large-icon?, ejb-name, home?, remote?, local-home?, local?, ejb-class, persistence-type, prim-key-class, reentrant, cmp-version?, abstract-schema-name?, cmp-field*, primkey-field?, env-entry*, ejb-ref*, ejb-local-ref*, security-role-ref*, security-identity?, resource-ref*, resource-env-ref*, query*)> Looking first at the entity element, much of it will be unchanged. What needs to be specified for a CMP entity are • cmp-version Always set to 2.0. The value 1.1 is supported only for legacy CMP Entity beans written to the EJB 1.1 specification. • abstract-schema-name Any unique name, this defines the name used to identify the bean in EJB QL queries. It makes sense to base this on the name of the bean. In the case study, the JobBean bean has a schema with the name of Job. • cmp-field One for each cmp-field (but not cmr-fields). In the Job bean, the cmp-fields are ref, customer, and description. The location and skills fields are cmr-fields representing relations to the Location and Skill beans respective- ly, and so do not appear. • primkey-field This optional field is used when the primkey-class element does not identify a custom primary key class. It is not specified for the Job bean, but for the Location bean, for example, it is specified and is set to name. • query Defines an EJB QL query, associating it with a finder or select method. Listing 7.12 shows the entity element for the Job bean. LISTING 7.12 Job Bean’s entity Element 1: <entity> 2: <display-name>JobBean</display-name> 3: <ejb-name>JobBean</ejb-name> 4: <local-home>data.JobLocalHome</local-home> 5: <local>data.JobLocal</local> 6: <ejb-class>data.JobBean</ejb-class> 7: <persistence-type>Container</persistence-type> 314 Day 7 09 0672323842 CH07 3/20/02 12:20 PM Page 314 CMP and EJB QL 315 7 8: <prim-key-class>data.JobPK</prim-key-class> 9: <reentrant>False</reentrant> 10: <cmp-version>2.x</cmp-version> 11: <abstract-schema-name>Job</abstract-schema-name> 12: <cmp-field> 13: <description>no description</description> 14: <field-name>ref</field-name> 15: </cmp-field> 16: <cmp-field> 17: <description>no description</description> 18: <field-name>description</field-name> 19: </cmp-field> 20: <cmp-field> 21: <description>no description</description> 22: <field-name>customer</field-name> 23: </cmp-field> 24: <ejb-local-ref> 25: <ejb-ref-name>ejb/CustomerLocal</ejb-ref-name> 26: <ejb-ref-type>Entity</ejb-ref-type> 27: <local-home>CustomerLocalHome</local-home> 28: <local>CustomerLocal</local> 29: <ejb-link>data_entity_ejbs.jar#CustomerBean</ejb-link> 30: </ejb-local-ref> 31: <! shouldn’t be needed, but ➥ctx.getEJBHome() returns null in J2EE RI > 32: <ejb-local-ref> 33: <ejb-ref-name>ejb/JobLocal</ejb-ref-name> 34: <ejb-ref-type>Entity</ejb-ref-type> 35: <local-home>JobLocalHome</local-home> 36: <local>JobLocal</local> 37: <ejb-link>data_entity_ejbs.jar#JobBean</ejb-link> 38: </ejb-local-ref> 39: <security-identity> 40: <description></description> 41: <use-caller-identity></use-caller-identity> 42: </security-identity> 43: <query> 44: <description></description> 45: <query-method> 46: <method-name>findByCustomer</method-name> 47: <method-params> 48: <method-param>java.lang.String</method-param> 49: </method-params> 50: </query-method> 51: <ejb-ql>SELECT OBJECT(j) 52: FROM Job AS j 53: WHERE j.customer = ?1</ejb-ql> 54: </query> LISTING 7.12 Continued 09 0672323842 CH07 3/20/02 12:20 PM Page 315 55: <query> 56: <description></description> 57: <query-method> 58: <method-name>findByLocation</method-name> 59: <method-params> 60: <method-param>java.lang.String</method-param> 61: </method-params> 62: </query-method> 63: <ejb-ql>SELECT OBJECT(o) 64: FROM Job o 65: WHERE o.location.name = ?1</ejb-ql> 66: </query> 67: </entity> The definition of the query element is as follows: <!ELEMENT query (description?, query-method, result-type-mapping?, ejb-ql)> You can see from the listing that the query-method element just identifies the name of the finder or select method. Note that if a finder method is being identified, it is the name appearing in the local-home (or home) interface; that is, without the ejb prefix. On the other hand, if a select method is being identified, there will be an ejb prefix, because select methods never appear in the interfaces of the bean. The result-type-mapping element applies only if the method identified by query- method has identified a select method, and only then if the EJB QL string returns Entity bean references (that is, if the SELECT [DISTINCT] OBJECT(x) style of select_clause has been used). The allowable values are Local and Remote, indicating whether the clause should return references through the local or remote interfaces. Obviously, if spec- ified, the bean must provide an interface of the appropriate type; if not specified, the bean must provide a local interface, because this is the implied value for the result- type-mapping element. Of course, all of this deployment information can be entered graphically using the deploytool. Figure 7.8 shows some of the equivalent information for Listing 7.12. 316 Day 7 LISTING 7.12 Continued FIGURE 7.8 deploytool lets CMP deployment informa- tion be defined through a GUI. 09 0672323842 CH07 3/20/02 12:20 PM Page 316 CMP and EJB QL 317 7 The relationships Element The relationships element is defined in the EJB 2.0 DTD as follows: <!ELEMENT relationships (description?, ejb-relation+)> That is, it consists of one or more ejb-relation elements. These in turn are defined as <!ELEMENT ejb-relation (description?, ejb-relation-name?, ejb-relationship-role, ejb-relationship-role)> which is a somewhat curious definition: an optional description, an optional name, and then precisely two ejb-relationship-role elements. Each of these identifies the role that some bean is playing with respect to the relationship. It is possible that the same bean appears in both roles to model recursive relationships. Note The ejb-relationship-role element is defined as follows: <!ELEMENT ejb-relationship-role (description?, ejb-relationship-role-name?, multiplicity, cascade-delete?, relationship-role-source, cmr-field?)> with <!ELEMENT relationship-role-source (description?, ejb-name)> You can see that the relationship-role-source element merely identifies an Entity bean by name. This element’s name is perhaps somewhat misleading, because it is nei- ther a “source” nor (for that matter) a target within the relationship. The navigability of the relationship comes from the presence (or not) of the cmr-field element. Of course, at least one of the ejb-relationship-role elements must have a cmr-field specified, and if both do, the relationship is bi-directional. The choices for the multiplicity element are either One or Many. There will be two such elements in the complete ejb-relation element, so this is what gives one-to-one, one- to-many, many-to-one, or many-to-many. There is also an optional cascade-delete element. Perhaps non-intuitively, this is placed on the “child” (multiplicity = many) side of a relationship. Finally, the cmr-field is defined as follows: <!ELEMENT cmr-field (description?, cmr-field-name, cmr-field-type?)> 09 0672323842 CH07 3/20/02 12:20 PM Page 317 The cmr-field-name element just names the cmr-field (for example, skills or loca- tion for the Job bean). The cmr-field-type element is needed only for multi-valued cmr-fields (for example, skills for the Job bean) and indicates whether the return type is a java.util.Collection or java.util.Set. 318 Day 7 Do not confuse this return type with the allowable return types for select methods. These are unrelated areas that just happen to have the same allowable return types. Caution Okay! Time for an example or two from the case study to see if all that theory makes sense. Listing 7.13 shows the ejb-relation element defining the one-to-many relationship between the Location bean and the Job bean. LISTING 7.13 The Location/Job Relationship 1: <ejb-relation> 2: <ejb-relation-name></ejb-relation-name> 3: <ejb-relationship-role> 4: <ejb-relationship-role-name>JobBean</ejb-relationship-role-name> 5: <multiplicity>Many</multiplicity> 6: <relationship-role-source> 7: <ejb-name>JobBean</ejb-name> 8: </relationship-role-source> 9: <cmr-field> 10: <cmr-field-name>location</cmr-field-name> 11: </cmr-field> 12: </ejb-relationship-role> 13: <ejb-relationship-role> 14: <ejb-relationship-role-name> ➥ LocationBean ➥</ejb-relationship-role-name> 15: <multiplicity>One</multiplicity> 16: <relationship-role-source> 17: <ejb-name>LocationBean</ejb-name> 18: </relationship-role-source> 19: <cmr-field> 20: <cmr-field-name>jobs</cmr-field-name> 21: <cmr-field-type>java.util.Collection</cmr-field-type> 22: </cmr-field> 23: </ejb-relationship-role> 24: </ejb-relation> Figure 7.9 shows this relationship overlaid onto the implied abstract schema. 09 0672323842 CH07 3/20/02 12:20 PM Page 318 CMP and EJB QL 319 7 Another example; Listing 7.14 shows the ejb-relation element defining the many-to- many relationship between the Job bean and the Skill bean. LISTING 7.14 The Job/Skill Relationship 1: <ejb-relation> 2: <ejb-relation-name></ejb-relation-name> 3: <ejb-relationship-role> 4: <ejb-relationship-role-name>JobBean</ejb-relationship-role-name> 5: <multiplicity>Many</multiplicity> 6: <relationship-role-source> 7: <ejb-name>JobBean</ejb-name> 8: </relationship-role-source> 9: <cmr-field> 10: <cmr-field-name>skills</cmr-field-name> 11: <cmr-field-type>java.util.Collection</cmr-field-type> 12: </cmr-field> 13: </ejb-relationship-role> 14: <ejb-relationship-role> 15: <ejb-relationship-role-name> ➥ SkillBean ➥</ejb-relationship-role-name> 16: <multiplicity>Many</multiplicity> FIGURE 7.9 The ejb-relation element describes the characteristics of a one-to-many relation- ship in the abstract schema. name Location description customer ref Job description location Location.name(FK) name Skill description requires jobs jobs location location for skills <ejb-relation-role> <ejb-relationsip-role-name> <multiplicity> <relationship-role-source>/<ejb-name> <cmr-field>/<cmr-field-name> </ejb-relation-role> <ejb-relation-role> <ejb-relationsip-role-name> <multiplicity> <relationship-role-source>/<ejb-name> <cmr-field>/<cmr-field-name> </ejb-relation-role> 09 0672323842 CH07 3/20/02 12:20 PM Page 319 17: <relationship-role-source> 18: <ejb-name>SkillBean</ejb-name> 19: </relationship-role-source> 20: <cmr-field> 21: <cmr-field-name>jobs</cmr-field-name> 22: <cmr-field-type>java.util.Collection</cmr-field-type> 23: </cmr-field> 24: </ejb-relationship-role> 25: </ejb-relation> Figure 7.10 shows these elements overlaid onto the abstract schema. 320 Day 7 LISTING 7.14 Continued FIGURE 7.10 The ejb-relation element describes the characteristics of a many-to-many rela- tionship in the abstract schema. name Location description customer ref Job description location Location.name(FK) name Skill description requires jobs jobs location location for skills <ejb-relation-role> <ejb-relationsip-role-name> <multiplicity> <relationship-role-source>/<ejb-name> <cmr-field>/<cmr-field-name> </ejb-relation-role> <ejb-relation-role> <ejb-relationsip-role-name> <multiplicity> <relationship-role-source>/<ejb-name> <cmr-field>/<cmr-field-name> </ejb-relation-role> As always, configuring these deployment descriptor elements can be done either by edit- ing the deployment descriptors directly or by using the deploytool. Figure 7.11 shows the deploytool for the Job/Skill relationship. To actually deploy the enterprise application, use the buildAll and deploy batch scripts in the day07\build directory, or use buildAll to assemble the enterprise application and deploy from deploytool. 09 0672323842 CH07 3/20/02 12:20 PM Page 320 CMP and EJB QL 321 7 Over the last three days, you have seen Session beans, BMP Entity beans and CMP Entity beans deployed using both the graphical deploytool and then using batch scripts. Clearly, the information held in those deployment descriptors is valuable and should be under source code control. Moreover, the mechanism for building and deploying enter- prise applications should be able to use that information rather than recreate it from scratch. This suggests that, for the production environment, the graphical deploytool should be used only for deploying enterprise applications and for configuring J2EE RI servers. On the other hand, in the development environment, it can be an error-prone task to attempt to write XML deployment descriptors from scratch. If a valid deployment descriptor already exists, modifying it (to add a new ejb-ref element or something simi- lar) can often be accomplished, but larger changes (such as adding a completely new bean) will be more difficult without much practice. Here, deploytool comes into its own to modify the enterprise application as required (or indeed, to create an enterprise appli- cation from scratch). When you are happy that the beans and clients in your enterprise application are correct- ly configured, deploytool allows the XML deployment descriptor to be saved, for checking into source code control. This is shown in Figure 7.12. F IGURE 7.11 deploytool can be used to configure rela- tionships through its GUI. FIGURE 7.12 deploytool allows deployment descriptors to be saved as XML files. 09 0672323842 CH07 3/20/02 12:20 PM Page 321 The Tools, Descriptor Viewer menu option brings up a dialog box displaying the XML deployment descriptor; from there, the data can be saved as a file. This menu option is context sensitive, so what it shows will depend on the node selected in the explorer on the left pane in the GUI. The descriptor viewer dialog should be brought up for each node under the enterprise application node, and for the enterprise application node itself. In the case study, this means for each of the clients, for the data Entity EJBs, for the agency Session EJBs, and for the agency application node. Deploying a CMP Entity Bean The enterprise application can be deployed either from the command line (deploy script in the build directory) or using deploytool itself. However, before an enterprise application containing CMP Entity beans can be deployed, the default SQL must be generated by using the Deployment Settings dialog box. This is performed once for each CMP Entity bean, as shown in Figure 7.13. 322 Day 7 F IGURE 7.13 deploytool allows SQL to create the database schema to be generated. You can see from the figure that J2EE RI generates default SQL. It allows the SQL query for the finder and select methods to be tuned, and also (the container methods radio button) allows the actual SQL to create the tables, insert rows, and so on to be modified also. The case study does not change any of this default SQL. Right at the beginning of today’s chapter, it was noted that the schema of the database for the case study had changed from that of Day 6. If one want- ed to use the exact schema from Day 6, it could have been entered here. Note 09 0672323842 CH07 3/20/02 12:20 PM Page 322 CMP and EJB QL 323 7 Also, the dialog allows the underlying tables to be created and deleted on deploy/unde- ploy. This obviously isn’t appropriate for a production environment, because it would delete any data already there. It also is not appropriate for the case study, because there is example data. The CreateCMPAgency script (provided in the day07\Database directory) cre- ates exactly the same schema as that generated by default by J2EE RI. It also populates that schema with the same data as in Day 6 and creates views for backwards compatibility. Note You will recall that the auxiliary deployment descriptor agency_ea-sun-j2ee-ri.xml contains all the mappings of the logical dependencies of the EJBs to the physical runtime environment. This includes all of the SQL specified in Figure 7.13. It was noted earlier that when creating a new CMP Entity bean, it is often easiest to load the enterprise application into deploytool and then save the XML deployment descriptor using the Tools, Descriptor Viewer menu option/dialog. Unfortunately, deploytool does not provide any easy way to write out the auxiliary deployment descriptor, and it is required for the command line approach. The buildAll script calls the addJ2eeRiToEar script that does precisely this. The only real option is to save the agency.ear file once modified, and then use a tool, such as WinZip, to load up the EAR file. The auxiliary deployment descriptor can be extracted from that. Patterns and Idioms This section presents some patterns and idioms that relate to CMP Entity beans. You’ll recognize some of the points made here; they were made earlier in the “Container Managed Relationships” section. Normalize/Denormalize Data in ejbLoad()/ejbStore() Under CMP, the ejbLoad() and ejbStore() methods don’t have very much (or indeed anything) to do; the interactions with the persistent data store are done by the EJB con- tainer. However, it may be that the physical schema of the persistent data store (especially if that persistent data store is an RDBMS) does not correspond exactly with the logical schema of the Entity bean. 09 0672323842 CH07 3/20/02 12:20 PM Page 323 [...]... +getEJBObject():EJBObject +STATUS_ACTIVE:int +STATUS_MARKED_ROLLBACK:int +STATUS_PREPARED:int +STATUS_COMMITTED:int +STATUS_ROLLEDBACK:int +STATUS_UNKNOWN:int +STATUS_NO_TRANSACTION:int +STATUS_PREPARING:int +STATUS_COMMITTING:int +STATUS_ROLLING_BACK:int ! To cause the transaction to be aborted, the CMTD bean can call setRollbackOnly() This instructs the EJB container to prevent the transaction from being committed The... String[0]; } List skillList; try { skillList = skillHome.lookup(Arrays.asList(skillNames)); } catch(FinderException ex) { error(“Invalid skill”, ex, initialTranStatus); ➥ // throws an exception return; } 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40 : 41 : 42 : 43 : 44 : 45 : 347 LocationLocal location=null; if (locationName != null) { try { location = locationHome.findByPrimaryKey(locationName);... (simulates trans-attribute of REQUIRED) int initialTranStatus; 8 11 0672323 842 CH08 3/20/02 9:29 AM Page 348 348 Day 8 LISTING 8.3 Continued 46 : 47 : 48 : 49 : 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: try { initialTranStatus = tran.getStatus(); switch(initialTranStatus) { case Status.STATUS_ACTIVE: // just use break; case Status.STATUS_NO_TRANSACTION: // create try { tran.begin(); } catch(NotSupportedException... JTA API 345 8 11 0672323 842 CH08 3/20/02 9:29 AM Page 346 346 Day 8 The Java 2 Platform Enterprise Edition Specification, the document that defines the interoperability of all the technologies that make up the J2EE platform, only discusses transaction interoperability in the context of the JTA API Note If nothing else, the semantics of intermixing JDBC and JTA calls are not exhaustively defined, so... be started using the begin() method The transaction can then be completed using either the commit() or the rollback() method The current status can also be obtained using getStatus() This returns an int whose meaning is defined by the constants in the javax.transaction.Status interface Some of the most common status values are shown in Table 8.2 TABLE 8.2 Some of the Constants Defined in javax.transaction.Status... transaction manager To understand and process the remaining lines, it is acting as a resource manager In the EJB specification, these two responsibilities are split In principle, you can think of the EJB container as acting as the transaction manager, and the persistent data store acting only as the resource manager The term transaction coordinator is sometimes used instead of transaction manager because there... The Solar System (line (line (line (line (line (line 1) 2) 3) 4) 5) 6, and so on …) Because the ejbLoad() method is called after the EJB container has loaded the data, it may renormalize the data In other words, the data in the two cmp-fields of address1 and address2 can be converted into the String[] address field The bean’s clients’ view (as presented by the methods of the local interface) is that... implemented using servlets and JSPs For either of these clients, the EJB architecture requires that a UserTransaction context can be obtained via JNDI, bound under the name of java:comp/UserTransaction So the code fragment shown in Listing 8 .4 will do the trick LISTING 8 .4 Obtaining a UserTransaction Object from JNDI 1: 2: 3: 4: 5: // assuming: // import javax.naming.*; // import javax.transaction.*; InitialContext... A working example can be found in day07\agency 7 09 0672323 842 CH07 3/20/02 12:20 PM Page 332 10 0672323 842 Week2 3/20/02 9:27 AM Page 333 WEEK 2 Developing J2EE Applications 8 9 8 Transactions and Persistence 9 Java Messaging Service 10 10 Message-Driven Beans 11 JavaMail 12 Servlets 11 13 JavaServer Pages 14 JSP Tag Libraries 12 13 14 10 0672323 842 Week2 3/20/02 9:27 AM Page 3 34 11 0672323 842 CH08... Entity bean, this will be the javax.ejb.EntityContext passed in through setEntityContext() To remind you, Figure 8.3 shows a UML class diagram illustrating the methods provided by these interfaces 11 0672323 842 CH08 3/20/02 9:29 AM Page 344 344 Day 8 FIGURE 8.3 The EJBContext provides access to the current transaction interface EJBContext interface javax.transaction.UserTransaction +getEJBHome():EJBHome . </security-identity> 43 : <query> 44 : <description></description> 45 : <query-method> 46 : <method-name>findByCustomer</method-name> 47 : <method-params> 48 : <method-param>java.lang.String</method-param> 49 :. Square (line 1) Christmas Town (line 2) North Pole (line 3) The World (line 4) Earth (line 5) The Solar System (line 6, and so on …) Because the ejbLoad() method is called after the EJB container. corresponding finder or select method to be bound in more than once. • When comparing strings in EJB QL, the strings must be identical to be equal. (This is different from SQL where trailing whitespace