Hi,
I've always been puzzled by the fact that the tutorials that Sun and
others release to teach new developers the ins and outs of J2EE
technologies are very often implemented in ways that could not even be
considered in real world applications. To illustrate my point, I would
point to the 'getAccountsOfCustomer' method on
com.sun.ebank.ejb.account.AccountControllerBean in the 'Bank' example
in the J2EE 1.4 tutorial.
For the default four account list for customer 200, the original
version executes five EJB Home calls (1 to load the Customer and 1 to
lead each Account) and executes 6 SQL statements (1 to load the
Customer, one to load the set of Customer/Account relations and 1 to
load each Account). My modified version executes 1 SQL statement and
makes no EJB Home calls at all. Measuring wall clock time shows that
the original version takes at LEAST 10 times as long as my modified
version and ignores the extra contention caused by all theat extra EJB
container and SQL activity in the execution environment.
Is it too much to say that you can't even consider an implementation
strategy that imposed an order of magnitude decrease in performace when
implementing real world applications? In my experience, no. You can't
consider the CMP based implementation strategy illustrated in the
original version of this method because no rational IT organization or
customer is going to invest an order of magnitude more in server
hardware to support a development strategy. If I'm right, then why
would we illustrate the use such an important technology with such a
terrible example? If I'm wrong, what benifit of the original
implementation of this method justifies the order of magnitude decrease
in performance?
The problem from my perspective is that developers learn the techniques
they see used in the tutorials and then try to apply them at work.
When they do that, they often run into someone like me who makes them
alter their approach. At that point, the best possible outcome is that
they learn a new development approach without the support of published
tutorials. A more typical outcome is a period of time when they think
I'm out of my mind.
What is everyone elses experience? This is not to say that CMP is not
relevant to enterprise application development, we may just need a
realistic example.
Thanks,
Jim Harrington
Slightly Modified Original Version:
// getters
public ArrayList getAccountsOfCustomer(String customerId)
throws InvalidParameterException, CustomerNotFoundException {
long start = System.currentTimeMillis();
// returns an ArrayList of AccountDetails
// that correspond to the accounts for the specified
// customer
Debug.print("AccountControllerBean getAccountsOfCustomer");
Collection accounts = null;
LocalCustomer customer = null;
if (customerId == null) {
throw new InvalidParameterException("null customerId");
}
try {
customer = customerHome.findByPrimaryKey(customerId);
accounts = customer.getAccounts();
} catch (FinderException ex) {
throw new CustomerNotFoundException();
} catch (Exception ex) {
throw new EJBException(ex.getMessage());
}
ArrayList rtn = copyAccountsToDetails(accounts);
long stop = System.currentTimeMillis();
System.out.println( "EJB Duration: " + (stop - start));
return rtn;
}
My Highly Altered Version:
private static final String ACCT_LIST =
"SELECT A.ACCOUNT_ID, A.TYPE, A.DESCRIPTION, \n" +
" A.BALANCE, A.CREDIT_LINE, A.BEGIN_BALANCE, \n" +
" A.BEGIN_BALANCE_TIME_STAMP \n" +
"FROM ACCOUNT A \n" +
" INNER JOIN CUSTOMER_ACCOUNT_XREF C \n" +
" ON ( C.ACCOUNT_ID = A.ACCOUNT_ID ) \n" +
"WHERE C.CUSTOMER_ID = ?";
// getters
public ArrayList getAccountsOfCustomer(String customerId)
throws InvalidParameterException, CustomerNotFoundException
{
// returns an ArrayList of AccountDetails
// that correspond to the accounts for the specified
// customer
Debug.print("AccountControllerBean getAccountsOfCustomer");
long start = System.currentTimeMillis();
ArrayList accounts = new ArrayList();
if (customerId == null) {
throw new InvalidParameterException("null customerId");
}
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
conn = ConnectionFactory.getConnection();
pstmt = conn.prepareStatement( ACCT_LIST );
pstmt.setString( 1, customerId );
rs = pstmt.executeQuery();
while( rs.next() )
{
AccountDetails details =
new AccountDetails( rs.getString( 1 ),
rs.getString( 2 ),
rs.getString( 3 ),
rs.getBigDecimal( 4 ),
rs.getBigDecimal( 5 ),
rs.getBigDecimal( 6 ),
rs.getDate( 7 ));
accounts.add( details );
}
}
catch( Throwable e )
{
e.printStackTrace();
}
finally
{
DBUtil.close( rs );
DBUtil.close( pstmt );
ConnectionFactory.releaseConnection( conn );
}
long stop = System.currentTimeMillis();
System.out.println( "JDBC Lookup Time: " + (stop - start));
return accounts;
}
jvsoft.org@gmail.com - 15 Aug 2006 13:14 GMT
That's only a tutorials, not a project.
http://www.developerzone.biz/
Patricia Shanahan - 15 Aug 2006 23:26 GMT
I don't know enough about the particular case to comment on it, but
there is a general problem devising tutorial examples for computing
ideas. Often, the situation in which the technique would really be used
is more complicated than is a appropriate in a tutorial.
For example, most tutorials describing recursion use examples that I
would code iteratively. I do use recursion, but not in those very simple
situations.
Bubble sort is used to teach the array and loop concepts that would be
used in a real sort, but is ridiculously inefficient unless the data is
already almost sorted.
Maybe the example is intended only to teach the technique, not as an
indication of how and when to apply it?
Patricia