Enterprise JavaBeans

Errata for Enterprise JavaBeans

Submit your own errata for this product.


The errata list is a list of errors and their corrections that were found after the product was released. If the error was corrected in a later version or reprint the date of the correction will be displayed in the column titled "Date Corrected".

The following errata were submitted by our customers and approved as valid errors by the author or editor.

Color Key: Serious Technical Mistake Minor Technical Mistake Language or formatting error Typo Question Note Update



Version Location Description Submitted By Date Submitted Date Corrected
Printed
Page ix
The following entry has been added to the Table of Contents

D. EJB 1.1: The Next Version

Anonymous    Aug 01, 1999
Printed
Page xiv
Added this description of Appendix D

Appendix D, EJB 1.1: The Next Version This appendix provides a summary of changes between EJB 1.0 to EJB 1.1 and a strategy for mitigating portability problems between versions.

Anonymous    Jan 01, 2000
Printed
Page 8
In about the middle of the page, changed

"In a read application, we would..." To: "In a real application, we would "

Anonymous    Dec 01, 1999
Printed
Page 25
Line 6 of the second paragraph read

An entity bean must extend javax.ejb.EntityBean; a session bean must extend javax.ejb.SessionBean. It now reads: An entity bean must implement javax.ejb.EntityBean; a session bean must implement javax.ejb.SessionBean.

Anonymous    Aug 01, 1999
Printed
Page 28
Toward the bottom of the page, changed

"notify the bean class that it is about activated " to: "notify the bean instance that it is about to be activated "

Anonymous    Dec 01, 1999
Printed
Page 59
The example read

public HypotheticalBean extends EntityBean { public int x; public double foo() { int i = this.getX( ); return this.bar( ); } public int getX(){ return x; } private double boo(int i){ double value = x * x; return x; } } It now reads: public HypotheticalBean extends EntityBean { public int x; public double foo() { int i = this.getX(); return this.boo(i); } public int getX(){ return x; } private double boo(int i){ double value = i * Math.PI; return value; } }

Anonymous    Dec 01, 1999
Printed
Page 73
In the lowest boxin the figure, the method name now reads

"setDeckLevel()" instead of: "setName()".

Anonymous    Dec 01, 1999
Printed
Page 84

The first line of second paragraph started with The CabinBean class extends javax.ejb.EntityBean It now reads: The CabinBean class implements javax.ejb.EntityBean

Anonymous    Dec 01, 1999
Printed
Page 104
The code line

sd.setSessionTimeout(60); Now reads: sd.setSessionTimeout(300);

Anonymous    Dec 01, 1999
Printed
Page 114
The last line of code that read

java.rmi.NoSuchObjectException: Bean has been deleted was deleted.

Anonymous    Dec 01, 1999
Printed
Page 119
The code line

TravelAgent agent = home.fin; Now reads: TravelAgent agent = home.create( );

Anonymous    Dec 01, 1999
Printed
Page 131

Now reads "these method behave" Should be: "these methods behave"

Anonymous   
Printed
Page 151
The following code block

if(result.next()){ name = result.getString("name"); capacity = result.getInt("capacity"); tonnage = result.getDouble("tonnage"); }else{ throw new ObjectNotFoundException( "Cannot find Ship with id = "+id); } Now reads (the new line is: this.id = id;): if(result.next()){ this.id = id; name = result.getString("name"); capacity = result.getInt("capacity"); tonnage = result.getDouble("tonnage"); }else{ throw new ObjectNotFoundException( "Cannot find Ship with id = "+id); }

Anonymous    Dec 01, 1999
Printed
Page 168
Sentence reads

"before making itself available to he client." Should be "before making itself available to the client."

Anonymous   
Printed
Page 170
Title read

Transitioning to the Ready state from the Pooled state via passivation now reads: Transitioning from the Ready state to the Pooled state via passivation

Anonymous    Dec 01, 1999
Printed
Page 170
Title read

Transitioning to the Ready state from the Pooled state via removal It now reads: Transitioning from the Ready state to the Pooled state

Anonymous    Dec 01, 1999
Printed
Page 171
In the third line from the bottom instead of

-just before the container reads the container-managed fields. It should be for more clarity - just before the container reads writes the container-managed fields to the database.

Anonymous   
Printed
Page 179
The third line of code read

"import com.titan.travelagent.CreditCard; It has been deleted.

Anonymous    Dec 01, 1999
Printed
Page 185

The following line of code was deleted Statement stmt = null;

Anonymous    Dec 01, 1999
Printed
Page 185

code fragment // concatenation of strings was required because of margin size in book. ps = con.prepareStatement ("INSERT INTO payment (customer_id, amount, type,"+ check_bar_code,check_number,credit_number, credit_exp_date)"+ VALUES (?,?,?,?,?,?,?)"); now reads (string concatenate fixed): ps = con.prepareStatement ("INSERT INTO payment (customer_id, amount, type,"+ "check_bar_code,check_number,credit_number,"+ "credit_exp_date) VALUES (?,?,?,?,?,?,?)");

Anonymous    Dec 01, 1999
Printed
Page 194 & 195
Replaced

package com.titan.travelagent; import java.rmi.RemoteException; import javax.ejb.FinderException; import com.titan.cruise.Cruise; import com.titan.customer.Customer; public interface TravelAgent extends javax.ejb.EJBObject { public void setCruiseID(int cruise) throws RemoteException; public int getCruiseID() throws RemoteException; public void setCabinID(int cabin) throws RemoteException; public int getCabinID() throws RemoteException; public Ticket bookPassage(CreditCard card, double price) throws RemoteException,IncompleteConversationalState, DoubleBookingException; } ------ with: -------- package com.titan.travelagent; import java.rmi.RemoteException; import javax.ejb.FinderException; import com.titan.cruise.Cruise; import com.titan.customer.Customer; import com.titan.processpayment.CreditCard; public interface TravelAgent extends javax.ejb.EJBObject { public void setCruiseID(int cruise) throws RemoteException, FinderException; public int getCruiseID() throws RemoteException; public void setCabinID(int cabin) throws RemoteException, FinderException; public int getCabinID() throws RemoteException; public int getCustomerID( ) throws RemoteException; public Ticket bookPassage(CreditCard card, double price) throws RemoteException,IncompleteConversationalState, DoubleBookingException; }

Anonymous    Dec 01, 1999
Printed
Page 198
Changed

"double.valueOf(" to: "Double.valueOf("

Anonymous    Dec 01, 1999
Printed
Page 199
The source code read

"public int getCustomerID( )throws RemoteException{ if(cruise == null) throw new RemoteException(); return ((CustomerPK)customer.getPrimaryKey()).id; }" It now reads: "public int getCustomerID( )throws RemoteException{ if(customer == null) throw new RemoteException(); return ((CustomerPK)customer.getPrimaryKey()).id; }"

Anonymous    Dec 01, 1999
Printed
Page 209
Near the bottom of the page, changed

"data, we wou212 ld use the Reservation bean." to: "data, we would use the Reservation bean."

Anonymous    Dec 01, 1999
Printed
Page 209
Replaced

public interface TravelAgent extends javax.ejb.EJBObject { public void setCruiseID(int cruise) throws RemoteException; public int getCruiseID() throws RemoteException; --- with --- public interface TravelAgent extends javax.ejb.EJBObject { public void setCruiseID(int cruise) throws RemoteException, FinderException; public int getCruiseID() throws RemoteException; ---

Anonymous    Dec 01, 1999
Printed
Page 210
Replaced

public void setCabinID(int cabin) throws RemoteException; public int getCabinID() throws RemoteException; public Ticket bookPassage(CreditCard card, double price) throws RemoteException,IncompleteConversationalState, DoubleBookingException; public String [] listAvailableCabins(int bedCount) throws RemoteException, IncompleteConversationalState; } --- with --- public void setCabinID(int cabin) throws RemoteException, FinderException; public int getCabinID() throws RemoteException; public int getCustomerID( ) throws RemoteException; public Ticket bookPassage(CreditCard card, double price) throws RemoteException,IncompleteConversationalState, DoubleBookingException; public String [] listAvailableCabins(int bedCount) throws RemoteException, IncompleteConversationalState; }

Anonymous    Dec 01, 1999
Printed
Page 273
In the first paragraph,

"When the ShipBean is persisted ..." now reads: "When the CabinBean is persisted ..."

Anonymous    Dec 01, 1999
Printed
Page 280
In the footnote, changed

"Version 2.0 of EJB." to: "Version 1.1 of EJB."

Anonymous    Dec 01, 1999
Printed
Page 306-314

A new appendix, Appendix D, EJB 1.1: The Next Version, has been added. It reads as follows: On May 12, 1999 Sun Microsystems released the Enterprise JavaBeans 1.1 draft specification (EJB Moscone), the next version of EJB. Enterprise JavaBeans 1.1 is, in many ways, a point release with corrections and clarifications that will allow vendors and bean developers to create more portable beans. However, EJB 1.1 also includes some fairly important changes that developers will need to understand if they plan to develop EJB 1.1 systems. This appendix discusses some of the changes proposed in the draft EJB 1.1 specification, focusing on the most important and visible modifications since EJB 1.0. The biggest changes between EJB 1.0 and EJB 1.1 include: mandating Entity bean support, the adoption of XML deployment descriptors, the creation of a default JNDI context, and changes to security. Changes to these areas are addressed below, but be warned: This material is based on a draft of EJB 1.1, which is subject to modification before its final release. Entity Beans EJB 1.1 mandates support for the Entity bean type. In EJB 1.0, entity bean support is optional, which means vendors can support them in whole, in part, or not at all. Most EJB server vendors chose to support entity beans in some way; for these vendors, the transition to full support shouldn't be difficult. For most EJB developers, the required support for Entity beans is welcomed, because it provides a more stable platform for portable beans. The Entity bean type itself has undergone some changes. The transaction attribute TX_BEAN_MANAGED has been removed from entity beans. This attribute is difficult to use because it requires explicit transactional control by the developer. Removing it from entity beans simplifies the EJB architecture. Stateful session beans, however, still retain the TX_BEAN_MANAGED option. Another welcome change is the expansion of valid return types from the find methods for entity beans. In EJB 1.0, find methods can return a single entity or a collection of entities. Find methods that return a single entity return the entity's remote interface type; entities that return a collection use java.util.Enumeration. In EJB 1.1 a new return type has been added, java.util.Collection. This addition provides both the vendors and developers with more flexibility in how the find methods are implemented and used. A seemingly minor change to the return value of ejbCreate() may turn out to be a headache when upgrading systems from EJB 1.0 to the EJB 1.1 specification. Because the ejbCreate() method works differently in bean-managed and container-managed beans, EJB 1.0 specified different return values: bean-managed entities return the unique identity of the bean, the primary key; container-managed entities return void. The following code shows the different method signatures used for container-managed and bean-managed ejbCreate() methods in EJB 1.0. // container-managed entity, EJB 1.0 public class AccountCMP implements javax.ejb.EntityBean { public int id; public double balance; public void ejbCreate(int myID) { id = myID; } // more bean code follows } // bean-managed entity, EJB 1.0 public class AccountBMP implements javax.ejb.EntityBean { public int id; public double balance; public AccountPK ejbCreate(int myID){ id = myID; // do a database insert using JDBC AccountPK pk = new AccountPK(myID); return pk; } // more bean code follows } The EJB 1.1 specification changes this, so that both bean-managed and container-managed entities have to return the primary key type from the ejbCreate() methods. However, container-managed beans are required to return null instead of a primary key object. This seemingly bizarre change was made to accommodate EJB vendors who want to support container-managed beans by extending them with generated bean-managed classes. The generated subclasses override the ejbCreate() methods to manually insert a record into the database. In EJB 1.0, the ejbCreate() methods in bean-managed and container-managed entities have different return values, so extending the class and overriding the ejbCreate() methods doesn't work. By specifying that the ejbCreate() methods must always return the primary key class, container-managed beans can be extended to create bean-managed beans. Unfortunately, this change breaks forward compatibility with EJB 1.0 container-managed beans, forcing bean developers to make changes to their existing code if they want to transition to the EJB 1.1 specification. The specification also contains some other changes regarding the primary key class. For bean-managed entity beans, EJB 1.1 states that the primary key class can be any valid Java RMI-IIOP type-a clear indication that IIOP will be the standard distributed object protocol for EJB in the future. In addition, the new specification requires the primary key class to implement the Object.equals() and Object.hashCode() methods to ensure that these methods evaluate properly when comparing keys and storing them in a java.util.Hashtable. The most significant change regarding primary keys is the option to defer their definition until deployment time. In other words, the primary key for an entity bean doesn't have to be defined by the developer, but can be left to the deployer. This is a significant departure from the previous specification, which required the bean developer to define the primary keys. By deferring the definition until deployment, persistence mapping becomes more flexible, allowing beans to become more portable. Although this is a convenient option, it's likely that most bean developers will continue to specify the primary class when they develop the bean. Finally, a change in the EJB 1.1 specification allows entity bean references to be container-managed fields. In container-managed entities the container manages persistence automatically, so it must be told at deployment time which fields are persistent and how to map them to the database. In EJB 1.0, container-managed fields are limited to primitives and java.io.Serializable types. Limiting the container-managed fields to these simple types makes it more difficult to maintain persistent relationships to other entity beans; entity beans are always referenced using their java.rmi.Remote interface type, which is neither a primitive nor Serializable. EJB 1.1 specifies that container managed fields can include references to other entity beans, which makes it much easier for the bean developer to model associations and aggregations of beans. How the container persists the relationships is not specified, but it's likely that options for converting the reference to a primary key will be provided at deployment time. Session Beans Session beans didn't change much from EJB 1.0 to EJB 1.1 because their behavior and functionality was well defined in the original specification. Several clarifications have been added to eliminate inconsistencies between vendors and provide a more predictable bean life cycle for developers. For example, the 1.1 specification requires that the SessionContext be preserved through passivation in non-transitive fields, and clarifies what resources can be accessed in which methods. These clarifications tighten up the specification and make it easier for both vendors and developers. XML Deployment Descriptors In EJB 1.0, the deployment descriptor information is stored in a serializable class defined in the javax.ejb.deployment package. While at first this appeared to be an excellent approach, it has limitations. It isn't clear which deployment information should be set by the bean developer and which by the deployer. In addition, the serializable classes are not very extensible and limit your ability to describe the bean's attributes. To solve these problems, EJB 1.1 replaces the serializable deployment descriptor with an XML-based deployment descriptor. The XML deployment descriptor is defined by an XML DTD (document type definition) that describes the structure that the XML deployment descriptors must have to be considered valid. The XML format is superior to the previous serializable object approach in many ways. First, it's more informative, allowing description tags to be associated with major elements so that the author can describe, in plain language, the purpose and expected behavior of attributes. Second, XML deployment descriptors can be viewed and edited using any text editor; the serializable deployment descriptor used in EJB 1.0 must be manipulated in a Java program (unless you're fluent in byte code!). Third, XML is more extensible and less fragile. In EJB 1.0 there are still problems with inconsistent versions of the deployment descriptor. As the specification evolves, the serializable deployment descriptor package would need to change, which introduces compatibility problems. With XML, new tags can be added without impacting existing deployment descriptor parsers. This makes deployment descriptors in EJB 1.1 more robust. Finally, XML is an industry standard, which means that deployment descriptors will enjoy universal support. EJB 1.1 deployment descriptors also add some new declarative attributes and eliminate some old ones (like Isolation levels!). Security, transactions, and environment properties change in EJB 1.1, necessitating changes in the type of information stored in the deployment descriptor. New features like bean and resource factory references were added, and the scope of the deployment descriptor was broadened to cover several beans for assembly. The division of labor for creating the deployment descriptor is better defined in EJB 1.1 as well. EJB 1.1 added new roles defining the development, assembly, deployment, and administration of beans. Contributions made by these roles to the deployment descriptor are well defined in EJB 1.1. The Default JNDI context Environment variables have undergone a fairly radical change. Environment properties in EJB 1.0 are a powerful mechanism for modifying the behavior of a component without changing the component's code. In EJB 1.0, the environment properties are accessible to the bean through the EJBContext.getEnvironment() method, are set by the bean developer, and can be modified by the deployer. In EJB 1.0 the environment variables might, for example, be used to set a maximum withdraw amount for an account bean, as in the following code: // EJB 1.0 public class AccountBean implements javax.ejb.EntityBean { public EntityContext context; public void withdraw(double amount) throws MaximumLimitException { try { Properties environment = context.getEnvironment(); String value = environment.getProperty("withdraw_limit"); Double limit = new Double(value); if ( amount > limit.doubleValue()){ throw new MaximumLimitException(); else { // continue processing } } } } EJB 1.1 changes the environment properties from the java.util.Properties class, used in EJB 1.0, to a set of JNDI entries that exist in a name space called the environment naming context. All deployed beans in EJB 1.1 have an environment naming context (default JNDI context) that can be accessed using the JNDI API. This default JNDI context provides a set of immutable JNDI entries specific to each type of bean. The default JNDI context provides the bean with access to environment variables which can be of type String or one of several primitive wrappers including Double, Float, Integer, or Boolean. The entries are defined in the XML deployment descriptor using special tags specific to the environment naming context. Here is an example of how the default JNDI context is used at run time by an EJB 1.1 bean: // EJB 1.1 public class AccountBean implements javax.ejb.EntityBean { public EntityContext context; public void withdraw(double amount) throws MaximumLimitException { try { InitialContext initCxt = InitialContext(); Context defaultCxt = (Context)initCxt.lookup("java:comp/env"); Double limit = (Double) defaultCxt.lookup("withdraw_limit"); if ( amount > limit.doubleValue() ){ throw new MaximumLimitException(); else { // continue processing } } } } EJB 1.1 compliant servers are not required to support the EJB 1.0 environment properties, which are available through the EJBContext. The getEnvironment() method has been deprecated and will throw a run time exception for EJB 1.1 servers that don't support backward compatibility. Environment properties are only one of three sets of values that can be accessed through the default JNDI context. The default JNDI context is also used as a repository for linking to predefined resources and beans. When developing a bean, the bean developer can identify the types of resources and enterprise beans that will be referenced in the bean and bind them to the default JNDI context. This simplifies the process of looking up and obtaining bean references within beans, as well as locating and using resources like a JDBC database connection. The bean developer defines the types of beans and resources associated with the default JNDI entries in the XML deployment descriptor. The following code shows how a bean uses its default JNDI context to look up a bean and a JDBC DataSource. // EJB 1.1 public class TellerBean implements javax.ejb.SessionBean { public void transfer(int sourceID, int targetID, double amount){ InitialContext initCtx = new InitialContext( ); // look up up the Account home AccountHome acctHome = (AccountHome)initCtx.lookup("java:comp/env/ejb/AccountHome"); // transfer the money Account source = acctHome.findByPrimaryKey( new AccountKey(sourceID)); Account target = acctHome.findByPrimaryKey( new AccountKey(targetID); source.withdraw(amount); target.deposit(amount); // Look up a the JDBC data source for recording transactions javax.sql.DataSource dataSource = (javax.sql.DataSource)initCtx.lookup("java:comp/env/jdbc/log"); java.sql.Connection con = dataSource.getConnection(); // continue processing: insert a log recording the transaction } } EJB 1.1 standardizes on the use of resource factories to access resources such as a JDBC connection. A resource factory provides access to resources in a manner that allows the container to manage the use of the resource. The use of the javax.sql.DataSource is a perfect example. It provides the bean with a JDBC connection that is managed transactionally and securely by the EJB container. In addition to JDBC, resource factories for the Java Messaging Service can also be used to obtain and managed access to an asynchronous message service. The default JNDI context provides a powerful mechanism for obtaining predefined environment properties, bean references, and resource factories. It standardizes access to enterprise bean's environment through JNDI and lays the groundwork for future enhancements. As new facilities and services are made available to beans, they too can be accessed through the default JNDI context. A good example is the plan to provide a "connector" service that will allow beans to connect to legacy or "back-end" systems using standard resource factories. RMI over IIOP Narrowing If the EJB server uses native Java RMI, the bean reference can be cast into its remote interface as shown in the previous example. If, however, the EJB client needs to be compatible with EJB servers that use RMI over IIOP, EJB 1.1 requires that the home reference be explicitly narrowed before it's returned from the JNDI context. Explicitly narrowing a remote reference is required because CORBA doesn't support casting. To support RMI over IIOP we would change the line that obtains a reference to the AccountHome so that it looks as follows: // EJB 1.1 using RMI over IIOP InitialContext initCtx = new InitialContext(); Object obj = initCtx.lookup("java:comp/env/ejb/AccountHome"); AccountHome acctHome = (AccountHome) javax.rmi.PortableRemoteObject.narrow(obj, AccountHome.class); The javax.rmi.PortableRemoteObject class is part of the RMI-IIOP extension package. Security EJB specifies declarative attributes for security authorization. Once a user has been authenticated (logged in), access to enterprise beans can be monitored and controlled. The declarative authorization attributes allows the container to control which users can access which methods on specific bean types. In EJB 1.0 individual methods on a bean are associated with Identity objects that represent individual users or groups of users called roles. Only users that are associated with the correct Identity objects can access the bean's methods. Using this approach, bean methods can be mapped to a set of identities in the serializable deployment descriptor. When a bean method is invoked at run time, the container examines the Identity of the caller and compares it to the list of Identity objects associated with that method. If the caller's identity matches or is a member of one of the identities associated with the method, the method can be invoked. Although this authentication model works well-it allows fine-grained functional authentication without requiring any code in the bean itself-it also has some problems. In an operational environment that supports ACL-based security, all the identities and roles in an enterprise are part of the operational environment. To choose Identity objects to associate with bean methods, you must have access to the ACL repository of the environment that the bean will be deployed in. For this reason, it is normally assumed that the deployer in EJB 1.0 will map the bean's methods to the security domain. Unfortunately, deployer may not have a good understanding of the purpose and function of the bean methods. This makes it difficult for the deployer to determine what identities and roles should be mapped to which methods-a problem that is compounded in beans that have numerous methods. In recognition of the authentication problems in EJB 1.0, EJB 1.1 has changed authentication security significantly. In EJB 1.1, the authentication service remains implicit and fine grained, but it's role driven rather than method driven. In EJB 1.1 the bean provider and the application assembler (the same person in many cases) defines logical roles in the XML deployment descriptor. Each role has a list of methods it is authorized to access. The roles are logical and have only semantic meaning. They are not obtained from a specific operational environment; they simply describe the type of user who can access a set of methods. The bean developer can provide additional information about the logical roles by attaching description tags to roles with comments. The bean deployer, who works in the operational environment, maps the logical roles defined by the bean developer and application assembler to real roles in the environment's security system. In this way, the bean developer and application assembler can define the type of roles that have access to methods without having to know anything about the operational environment in which the bean will be deployed. Similarly, the bean deployer can map roles in the operational environment to the logical roles in the deployment descriptor, based on semantic meaning of the logical roles and their attached descriptions, without having to understand the purpose or function of the methods involved. In fact, the deployer need not be concerned with the methods at all since she is only concerned with roles and the methods with which they are associated. Looking Ahead to EJB 2.0 Enterprise JavaBeans 2.0 is likely to be the next release of the EJB specification, which we can expect to be finalized some time after the year 2000. It will include the definition of a connector interface that will allow legacy and ERP systems to be accessed by beans through resource factories. The Java Messaging Service will be integrated into the EJB architecture, which will probably require the creation of a new bean type or modification of the stateless session type. The definition of a standard Object-to-Relational mapping interface is possible, although this may not be included because of the difficulty in defining a standard. Finally, a container interface will be defined that will allow containers and EJB servers to be clearly delineated and therefor interchangeable.

Anonymous    Aug 01, 1999
Printed
Page 312

line 7 was missing parenthesis. It read "new AccountKey(targetID);" It now reads: "new AccountKey(targetID));

Anonymous    Dec 01, 1999
Printed
Page 315-325

The page numbers in the index have changed due to the addition of Appendix D.

Anonymous    Aug 01, 1999