Errata

Building Java Enterprise Applications

Errata for Building Java Enterprise Applications

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.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
Printed Page 24
Figure 2-2

It appears that in the figure 2-2, the communication between the Business
layer and the Data layer is marked incorrectly. It shows this as RMI,
RMI/IIOP where I believe it was intended to show JDBC/JNDI similar to the
figure 2-4 shown on p.26. There just seems to be an inconsistency...or
did I miss something?

Anonymous   
Printed Page 35
figure 3-2

if i understand the dots and diamonds correctly, they are backwards for
the link between ROLE_PERMISSIONS and PERMISSIONS. i take it that the
"dotted side" has a foreign key reference to the "diamind side".

Anonymous   
Printed Page 38
Figure 3-5

The relationship between the Roles table and the User_Roles table is not
shown in the diagram Figure 3-5

Anonymous   
Printed Page 38
figure 3-5

someone already pointed out the "missing link" (heh heh) between ROLES and
USER_ROLES. there is also one missing between OFFICES and USERS, and the
one between OFFICES and ACCOUNT_TYPES doesn't need to be there.

Anonymous   
Printed Page 45
Figure 3-7

The ER diagram in Fig 3-7 shows incorrect table schemas (structures) based
on the SQL statements (on pp. 44-45) which used to create (define) the
tables - specifically the table ACCOUNT_TYPES and the table ACCOUNTS do
not appear to be correct. The ACCOUNT_TYPES table is shown having columns
defined in the USER_TYPES table defined in the preceding section.

Anonymous   
Printed Page 45
Figure 3-7

The relationship between the Investments and Funds table is the wrong way
around.

I'm not exactly sure about what the dot and diamond mean, but from the
other examples in the book, it seems that the table on the dotted end has
a foreign key that references a primary key on the diamond end.

The Investments table has the foreign key (Fund_ID) which references the
primary key in the Funds table, which is why I think the dot and diamond
are the wrong way round.

This also applies to Figure 3-9 on page 47.

Anonymous   
Printed Page 51
Second drawing

The most left node on the second level is labeled "u=People".
It probably should be labeled "ou=People"

Anonymous   
Printed Page 51
Figure 3-11

"0=forethought.com" should read "o=forethought.com"

Anonymous   
Printed Page 56
Figure 3-13

"group of Forethougt names" should read "group of Forethought names"

Anonymous   
Printed Page 56
1st para

In reference to defining the group object class. On page 56 of the book
you state "You then need to add the custom attribute, uniquePermission,
to the set of required attributes for the new object class." The key word
here being "required".

The addGroup() method doesn't deal with this required attribute
uniquePermission and results in the error "LDAP: error code 65 - Object
Class Violation".

Redefining the groupOfForethoughName object such that uniquePermission
is not required but allowed "fixes" the problem, *but* what side effects
will be brought out by this change?

Anonymous   
Printed Page 64
bottom

The argumentatation that the method name should be getId and the field should
be OFFICE_ID seems to be inconsistent. If the SQL example is changed to:

SELECT FIRST_NAME, LAST_NAME, CITY, STATE
FROM USERS users, OFFICES offices
WHERE users.OFFICE_ID = offices.ID

Then the same arguments apply for the SQL code as do for the Java code. I think
consistency is more important than making these kind of optimizations. These
are the kind of incosistencies that drive you nuts when you have to analyze a
big system.Pick OFFICE_ID/getOfficeId or ID/getId ...

Anonymous   
Printed Page 67
Example 4-3

need to import javax.ejb.EJBException

Anonymous   
Printed Page 69
Example 4-6 ejbPostCreate method

The line:
public void ejbPostCreate(int id, String city, String state)

needs to be:
public void ejbPostCreate(Integer id, String city, String state)

the ejbCreate and ejbPostCreate need to take the exact same arguments

Anonymous   
Printed Page 74
Figure 4-2

The wrong icon was used for the Office*.java files and the last four files should not
be represented as a sub-tree of Office.java.

Anonymous   
Printed Page 84
1st paragraph

JDNI context

should be:

JNDI context

Anonymous   
Printed Page 90
Code segment in middle of the page

I believe that the line:

setId(new Integer(officeInfo.getId()));

should be removed. It should prove unnecessary since you shouldn't be
given the chance of modifying the primary key and when trying to use on
JBoss the following error occurs:
IllegalStateException - A field that is a member of the primary key can
only be set in ejbCreate.

Anonymous   
Printed Page 93
constructor for OfficeInfo

On page 94 in the last paragraph it explains that the contructor in the
code example on page 93 is package-protected, however this isn't true.
To make this true the code on page 93 should list:

protected OfficeInfo(int id, String city, String state) {

The author's logic is sound, however this typo should be corrected.
Thank you for considering this.

Anonymous   
Printed Page 100
Entire LDAPManager discussion

I question the use of LDAPManager as the class to encapsulate the logic
for Users, Groups and Permissions. Although they share the use of LDAP
as a data storage technology, this seriously violates the integrity of
the interface to the data layer as representative of business entities.
Additionally, this inhibits the future flexibility of the system by
combining multiple entities into a single object and by binding them
name-wise to the storage medium. The methods that server the business
entity interactions don't require this combination of entities. The LDAP
connection pooling through the singleton pattern suggests a singleton
commonality, but that can be handles with an LDAP interface layer behind
the business entity interfaces.

Anonymous   
Printed Page 113
Footnote

I think the author utterly confuses the issues of repeatedly appending to the same
string versus making a constant string. The StringBuffer/append code is EXACTLY the
kind of code that would have been made by the compiler. This extra unnecessary code
just makes it hard to read. Actually, '+' example compiles to a smaller class.

public class T1 {

private String getUserDN( String username ) {
return new StringBuffer()
.append("uid=")
.append(username)
.append(",")
.append("ou=People,o=forethought.com")
.toString();
}
}

public class T2 {
private String getUserDN( String username ) {
return "uid=" + username + "," + "ou=People,o=forethought.com";
}
}

This kind of silly "optimizations" kill compiler optimizations (something that
will happen to Java one day as well) and makes code harder to read.

It is true that StringBuffer/append is better when a string is appended in a
loop or in different places in the program, however, an author of this book
should not make such a mistake imho.

Anonymous   
Printed Page 119
Code for addGroup() method

Under OpenLDAP v2.0.19 the attribute uniqueMember is defined as MUST in
groupOfUniqueNames from which groupOfForethoughtNames inherits.

This causes addGroup to fail for not supplying a mandatory attribute.

Netscape's LDAP server defines uniqueMember as a MAY attribute of groupOfUniqueNames
which is probably the right thing as you should be able to have group with no members
:-)

Editing core.schema to set uniqueMember as a MAY attribute makes the program work
correctly.

Anonymous   
Printed Page 126
Top of page

In the source code, there is an extra ')' at the end of the line beginning -
getUserUID((String)vals.nextElement())));
should be - getUserUID((String)vals.nextElement()));

Anonymous   
Printed Page 133
Connection Sharing discussion

Although the basic justification for the connection sharing discussion is
correct, it omits the fact that the singleton pattern still only creates
a singleton *per JVM*. If multiple EJB containers are used, either for
deployment purposes or through redundant configuration as the application
grows, multiple connections will still result. The application will still
scale far better than the non-singleton approach, but not quite as well as
one might believe without this information. I specifically don't mention
servlet engines/containers or standalone clients, as they should not be
accessing the data layer entities directly anyway.

Anonymous   
Printed Page 134
2nd code fragment

What is the motivation for making the LDAPManager constructor protected instead of
private. No indication has been given that there is any design intent to sub-class
the LDAPManager class and the getInstance method can't be over-ridden and shouldn't
be circumvented.

Anonymous   
Printed Page 139
Error Reporting discussion

It may be worth commenting that adding the UserNotFoundException is acceptable as
part of the data layer interface providing adequate measures are taken to control
access to the data layer, but is a security risk if reflected in the business or
presentation layers. It allows discovery of valid user names without having to know
passwords, simplifying the hacking process.

Anonymous   
Printed Page 140
Example 7-1, both constructors.

Earlier in the book, Brett mentioned that one should NEVER use '+' for String
concatenation. However, in these constructors, they both use '+' for String
concatenation. This should change to follow the spirit of your directive.

Anonymous   
Printed Page 140
Example 7-1

The second constructor, UserNotFoundException(String firstName, String lastName) has
a line which sets this.username = username.

This will compile, however, is not the intention. It will set username to it's
current setting. We've all been there before at some time. ;-)

What is intended IMHO, is the setting of both the first and last name values, i.e.

this.firstName = firstName;
this.lastName = lastName;

Anonymous   
Printed Page 140
9 th line from the bottom

The line:
} catch (javax.naming.NameNotFoundException) {

will give the error:
<identifier> expected

should be:
} catch (NameNotFoundException e) {

Anonymous   
Printed Page 142-3
Figure 7-3 and 7-4

Both figures omit the LDAPManager files despite the text stating that they should be
included.

Anonymous   
Printed Page 144
last code block

commodoties

Should be:

commodities

Anonymous   
Printed Page 147
Middle of page

While creating the user entries, double quotes are placed around the data for
the userDN field.

This represents that the information in the LDAP storage (the DN of the entry)
would be of the following format:

uid="shirlbg",ou="People",o="forethought.com"

This does not match other examples in the book, and under my OpenLDAP
installation (OpenLDAP 2.0.25) does not work. It causes the findByUserDN
finder method to not find the entry since it looks for

uid=shirlbg,ou=People,o=forethought.com generated by
LDAPManager.getUserDN(username);

I'm not sure whether the double quotes should be considered the same as an
entry without them; my experience says it's not.

Therefore, these entries should remove the double quotes and then the finder
findByUserDN would find the entry correctly in the database.

Anonymous   
Printed Page 165
7th line

The line of code:
User user = userHome.create(LDAPManager.getUserDN(username),
userType, firstName, lastName,
officeInfo);

will generate an error because there is no create constructer for the User that
accepts "OfficeInfo". Either Office type needs to be use or a constructer created
that will take a type of OfficeInfo

Anonymous   
Printed Page 167
delete(User user) block

This will delete the user from the database. However, code needs to be added to
remove user from the LDAP. Probably could change arguments to allow for
delete(username, user)

and user LDAPManager to delete the user. Other changes in other files would need to
bechange for this to be effective. (Maybe a more eleant solution is available)

Anonymous   
Printed Page 219
Entire Primary Keys section (example A-21 through example A-25 on page 222)

In each example the table created is called PRIMARY_KEYS, however all of the insert
statements refer to a table called SEQUENCES.

Anonymous   
Printed Page 243
under 2nd paragraph

When using OpenLDAP I needed to add the line:

EQUALITY distinguishedNameMatch

to make the code work. The attribute looked like the following:

attributetype ( 2.1.1.1.2 NAME 'uniquePermission'
DESC 'Link to a forethoughtPermission object'
EQUALITY distinguishedNameMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )

Anonymous   
Printed Page 247
3rd paragraph

I could not find the deployment descriptors for WebLogic 6.x on your Web site
"newInstance.com"

Anonymous