• No results found

WSAD Development Process

8.3.1 Architecture Summary

For this implementation the team decided to keep things simple and straightforward. They used only standard J2EE APIs according to established best practices.

8.3.1.1 Overall Shape of the Code

The team chose an architectural framework based on lessons learned from prior development experience and performance research. Here’s a tier-specific breakdown:

Database access. As with the RRD implementation, again the team avoided putting database logic in the database itself via stored procedures, favoring explicit SQL statements in the Java code. In this more standard J2EE environment, where they would have to write the database logic either way, several factors led to this conclusion:

For a single database action, a prepared statement invoked via JDBC performs at least as well as a stored procedure.

Prepared statements are easier to write than PL/SQL stored procedures.

Having the SQL in the application code rather than in the database simplifies code maintenance.

Along the way the team discovered that this choice gave them even greater flexibility than first thought: They could invoke complete PL/SQL statements as JDBC prepared statements, letting them combine multiple database actions into one. More on this below under Section 10.5.4, Optimizing Queries.

The persistence tier. Having chosen persistence logic within the application itself, the team then had to choose how to organize that logic, whether in EJB entity beans, another O/R mapping layer such as Hibernate or JDO, or POJOs with straight JDBC. Again, from past experience they decide that entity beans were too expensive. They considered Hibernate, but rejected it; it might provide a significant productivity gain only if the entity model were extensive, and the team wasn’t certain it would scale. So instead they settled on POJOs.

To centralize all common aspects of JDBC operations, the team created a simple framework based on the Command pattern. A central JdbcHelper class was responsible for getting a connection, executing a statement, getting and returning the results of that statement (if the SQL was a query), and handling errors. It obtained the SQL statement and the actual query results from a case-specific “callback object” (the command object).

The callback classes themselves were organized as inner classes of entity-specific JDBC helper classes, such as CustomerJdbcHelper for customer activity. Each class had methods representing individual database actions, such as updateCustomer(). Each method would create or obtain7 the proper callback object and invoke the central JdbcHelper logic to execute the database action.

This framework proved very effective in minimizing repetitive code, reducing bugs and easing maintenance.

The business tier. For the business façade the team considered EJB session beans but rejected it as too expensive. Instead they created a simple framework based on the Façade pattern. Each application had a single façade class with stateless methods representing every action required by that application’s front end. Most of these methods simply called a method of the appropriate JDBC helper class. Each façade class also created a single instance of itself of each JDBC helper class it used to eliminate unnecessary object creation.

The Web tier. The team used JSPs for Web pages and servlets to tie those pages to business logic. They decided against using an MVC framework (Struts was the prime candidate)

because it would add runtime overhead. Nevertheless, they did create a simple “controller”

servlet that reproduced some of Struts’ conveniences:

form field validation

message handling (informational and error)

request forwarding

This servlet became the ancestor class to all servlets in the two ITS Web applications.

The team also did not use any custom tag libraries. This choice meant that their JSPs

contained significant amounts of Java code. For a comparatively short project such as this, the additional code was acceptable; but in a longer, more enduring project the team would probably have refactored their JSPs to use Struts or JSTL libraries.

Message consumption. As with the RRD implementation, the team saw no reason to deviate from using EJB message-driven beans (MDBs).

8.3.1.2 Distributed Transactions

To handle distributed transactions, the team used the same solution with the WSAD

implementation as they did with RRD: They set up two JDBC data sources to each database:

one using an ordinary driver for simple transactions, the other using an XA -capable driver for distributed transactions. See Section 8.2.1.4 for details.

8.3.1.3 Organization of Applications in WSAD

WSAD proved very flexible in letting the team organize their code into projects and

applications. The team organized their work into ten projects comprising three applications and two external libraries:

7 Callback classes representing actions with no parameters (such as get all customers) could be treated as singletons.

Project Produced Description

itsCustServ itsCustServ.ear Umbrella project for Customer Service Web

app

+ itsCustServWeb itsCustServWeb.war Web app for Customer Service

itsWorkOrder itsWorkOrder.ear Umbrella project for Work Order Web app

+ itsWorkOrderWeb itsWorkOrderWeb.war Web app for Work Order

itsWorkOrderConsole itsWorkOrderConsole.ear Non-Web functionality on Work Order side + itsWorkOrderConsoleMdbs itsWorkOrderConsoleMdbs.jar Message beans to process customer and

ticket messages

+ itsWorkOrderConsoleWeb itsWorkOrderConsoleWeb.war Web front end for Web service

+ itsWorkOrderConsoleCommon itsWorkOrderConsoleCommon.jar Common logic for message beans and Web service

common common.jar External library containing generic logic,

e.g. JdbcHelper class

itsCommon itsCommon.jar External library containing ITS-wide logic,

e.g. DTO classes

8.3.2 What Went Well

Some aspects of development (especially page design and coding) were more tedious in WSAD than in RRD. Still, overall WSAD proved easier to use than RRD, for two reasons:

It was a straightforward tool that facilitated access to J2EE rather than hiding it. This appealed to the J2EE developers on the team.

It was dedicated to WebSphere.

Several aspects of working with WSAD were particularly easy:

8.3.2.1 Navigating the IDE

While far from simple, WSAD seems to be a better organized IDE than RRD. The flow from one type of task to another is simpler and easier. WSAD’s navigational structure is flatter and allows you to maintain parallel threads of activity simultaneously, such as editing source code, setting project properties and configuring servers. In RRD, often pursuing one thread of activity takes you to a place from which it is more difficult to return to your starting point.

8.3.2.2 Building for Deployment

Rebuilding applications in RRD often took many minutes. WSAD’s build process was much faster. Given how often the process took place, this small savings per build added up to significant time savings over the life of the project.

8.3.2.3 Testing in WebSphere

WSAD’s lightweight WebSphere test environment proved extremely useful. It started and stopped much more quickly than WebSphere running on the local development machines and worked seamlessly with the WSAD development environment.

8.3.2.4 Common Logic in JSPs

Because the team was creating explicit JSPs for this implementation, they could take

advantage of the JSP @include directive to put common logic in a central JSP and import into

every page that needed it. The team used this technique for two common aspects of their pages:

The page header, including the navigation bar (links to other pages)

The page authentication logic to verify that the user is logged in before displaying the page The only tricky part to using @include was the declaration and use of variables in scriptlets. A variable used in any JSP had to be declared in the same JSP. This restriction complicated the design a bit but not significantly.

8.3.3 Signficant Technical Roadblocks 8.3.3.1 XA Recovery Errors from Server

At one point in development testing, Developer B got an unusual error from the WebSphere test server. The error had a long output trace that pointed to one of the XA datasources and began with

The transaction service encountered an error on an xa_recover operation.

The error appeared shortly after a test of a distributed transaction had failed and the server was bounced. It seemed the server was trying unsuccessfully to recover from the failure. The problem was that the server tried again every minute or so, pumping output into the stdout log.

While not a show-stopper, this problem was annoying, especially because it later also appeared in the live WebSphere instances. Bouncing WebSphere and Oracle had no effect, and the team could not find any WebSphere configuration settings that helped. Moreover, the problem had not appeared during the RRD round.

Eventually a Google search found the answer at an IBM devWorks forum: The datasource user must have SELECT rights to the Oracle table PUBLIC.DBA_PENDING_TRANSACTIONS. In the RRD round the team had set up the datasources to log in as SYSTEM, which had that right.

In the WSAD round, they configured the datasource to log in as ITSUSER (the ITS schema user), which didn’t.8 When they granted that right to ITSUSER and restarted the servers, the problem disappeared.

8.3.3.2 Miscellaneous WSAD Headaches

Along the way WSAD posed a handful of smaller challenges. Among the more interesting:

TODOs in JSPs. WSAD has a nice facility for marking “to do” tasks in your Java code. It displays any comment beginning with // TODO in a special “To Do” list and lets you easily jump to that comment from the list. However, this facility does not work for comments in JSPs.

Code completion inside JSPs. WSAD has a nice code completion tool, but it is very slow for Java code inside JSP scriptlets.

Copying a servlet. One developer discovered that when he created a new servlet by copying an existing one, WSAD did not automatically add the new servlet to the web deployment descriptor; because of that he got “page not found” errors when invoking that servlet. The Web descriptor editor has a Servlets page that should have allowed him to add existing servlets to the list, but it didn’t point to the right, and the developer didn’t see how to make it do so. So he had to manually edit the descriptor source.

Sharing source code. Because the team chose not to use source control software, they shared code by zipping up their workspace. After a couple of false starts they learned which files not to share.

8 Why the change? Having the application log in as SYSTEM meant that at least some SQL table references had to be qualified with the schema name. Logging in as ITSUSER eliminated that problem.

Related documents