Designing the Rental Swing Application


Two design constraints dictate some of the choices in the architecture of the rental Swing application. The use of Swing is a given. The use of JDO is also a given. The use of JDO implies two design tasks: one, to define the classes of persistent objects, and two, to define the service that will use JDO to find, store, create, and delete these persistent objects.

The Application Data Classes of the Rental Swing Application

To build the prototype reservation system for the Maine Lighthouse Rental Company, four application data classes are needed.

  • Customer

  • Week

  • Lighthouse

  • Rental

Since development is in the prototype stage, the classes are simple, but it is anticipated that the classes will continue to exist and become more complex as the application evolves.

The Customer Class

Figure 9-5 shows the UML class diagram for the Customer class. Notice that this UML diagram shows the private persistent attribute called name. The private attributes are shown in the application data classes because they are used in queries. Following the normal UML convention, the leading hyphen indicates a private access level. As mentioned in the introduction, this book uses the convention that the access level of attributes and operations is public when the class diagram does not indicate the access level. For the Customer class, there is one public operation, the constructor, and one public, read-only, property called Name. To avoid issues of mixed case in query filters, the Customer class forces customer names to uppercase.


Figure 9-5: The class diagram of the prototype Customer class

The Week Class

The Week class, as shown in Figure 9-6, is also a simple class. It has two private and persistent attributes, and three public and read-only properties. Not shown are factory methods used to construct the testing population of Week objects.


Figure 9-6: The class diagram of the prototype Week class

The Lighthouse Class

The Lighthouse class shown in Figure 9-7 has five private persistent attributes, and the same number of properties. A lighthouse has a name, a description, a name of the image file for its picture, a rate for the high season, and a rate for the off-season.

click to expand
Figure 9-7: The class diagram of the prototype Lighthouse class

All of the Lighthouse properties are read-only except ImageName, which is read-write. The properties in the prototype application data classes often end up read-only because the prototype application is not complicated enough to require that the attributes change after the persistent objects are created. As the application evolves, it is anticipated that many of the read-only properties will become read-write. The use of JDO does not impose a tax on this evolution. The only work required to convert a read-only property to a read-write property is to add the mutator method.

The Rental Class

The Rental class, which is shown in Figure 9-8, aggregates the various pieces of information. It has four private, persistent attributes, and six public properties. The Lighthouse, Week, and Customer properties hold references to the various objects that a Rental object ties together. The Price property is the rental rate for the week. The Available property is a convenience property that holds true if the Customer property is null. The Dirty property is a convenience property that checks with the isDirty method in JDOHelper and returns true if the Rental object has been changed but not yet committed to the datastore.

click to expand
Figure 9-8: The class diagram of the prototype Rental class

In addition to a constructor, the Rental class has two operations: makeReservation and cancelReservation. Both operations require a Customer object. The operation to cancel a reservation requires a Customer object as an invariant check on the action. The customer passed should be the customer who holds the reservation. Both operations throw a ReservationException when difficulties are encountered.

The Application Data Service in the Rental Swing Application

After defining the application data classes, the next step is to define an application data service. Unlike objects that exist only in memory, the state of persistent objects is permanently kept in the datastore. These objects are found, updated, created, and deleted by explicit actions on the service that synchronizes their existence and state in memory with their persistent state in the datastore. JDO is the generic service for this purpose, but each application usually needs a service configured to its particular concerns, objects, and tasks.

Design Choices for Transactions

The design for the rental Swing application must decide what to do with transactions. In order to store new or updated persistent information in the datastore, the data service must start and complete transactions. The fundamental question is this: Should transaction handling be encapsulated in the data service and to what extent? A variety of answers can work.

Transactions can be encapsulated within data service calls. One data service method may start a transaction, make some changes, and commit the transaction. Another data service method may not use a transaction at all, or perform read-only operations that do not change the persistent information. The client for a data service designed in this fashion has no control over transactions. The client may not know that transactions even exist, since they are completely hidden within the service.

A second approach allows a transaction started in one method to be completed in another method. The transactional boundaries are hidden within service methods that perform other work, but the transaction can span two or more service method invocations. This approach can be confusing unless the usage patterns for the service are limited and well documented.

A third approach is to simply expose control of the transactional boundaries as additional service methods. This approach gives the client layer both the responsibility for transactions and the ability to control them.

In the case of the rental Swing application, it makes sense to take the third approach, which exposes the transactional boundaries in the data service. Use cases 6, 8, and 9 describe the user as confirming, i.e. committing, reservation changes. For this reason, rather than encapsulate the transactions in the data service, it makes more sense to expose the transactional boundaries to the next level of the software, which will be closer to the user's click of the Confirm button.

Although the client of the ReservationService controls the transactional boundaries, the service configures the transaction. The service has made the decision that the transaction will be an optimistic transaction. This makes sense because transactional boundaries are controlled outside of the service and are therefore very likely to be long-running transactions that involve user input. Likewise, the factory.properties file, which configures the JDO factory, turns on the transaction's RetainValues property for better performance. It also turns off RestoreValues to ensure eviction of any transactional objects that cause an optimistic lock exception. In essence, the service encapsulates the configuration of the transaction and exposes the transactional boundaries.

The ReservationService Class

Figure 9-9 shows the operations of the ReservationService. The three transactional methods, beginTransaction, rollbackTransaction, and commitTransaction, control the transactional boundaries.

click to expand
Figure 9-9: The class diagram of the ReservationService

In the example, the reservation system needs to make three different queries:

  • Find all available rentals (use case 5).

  • Find all rentals that have been reserved by a particular customer (use case 7).

  • Find all rentals that are either available or reserved by a particular customer (use case 9).

Three methods in the service, getAvailableRentals, getCustomerRentals, and getCustomerAndAvailableRentals, provide a convenient way to obtain the Rental objects found by each query filter.

In a similar manner, the remaining methods in the application data service arise from analyzing the use cases and from implementing behavior whose desirability becomes evident during coding. The evictAll method handles the need, mentioned in use case 10, to refresh all information. The two getCustomers methods arise from use case 3 and also from the desire that becomes evident during coding to provide a reasonable way for the user to identify himself from a list of known customers. The need for the getLighthouses method becomes obvious as the code is written to handle the JTable headers. In short, the service methods in the application data service tailor the explicit services available in JDO to the specific needs of the application.

As the UML class diagram in Figure 9-9 shows, most of the service methods of the ReservationService throw some type of JDOException. Since JDOException is derived from RuntimeException, the possibility does not need to be mentioned explicitly in a throws clause in the code. The UML class diagram mentions the possibility of throwing this exception since it must be accounted for in the design. In addition, as described in Chapter 7, the possibility exists that JDO exceptions will occur when persistent objects are used or modified. Live persistent objects can always throw JDO exceptions that arise from operational circumstances.

The Application Data Model in the Rental Swing Application

The ReservationService throws JDO exceptions, but the Swing client classes, which mostly execute code in the Swing libraries, cannot handle exceptions. The data model that the Swing widgets use must isolate the possibility of runtime exceptions. In addition, each widget has its own particular data structure that works best for it. For this reason, a third layer is introduced called the application data model. The application data model for the rental Swing application is found in the ReservationClientModel class.

As the UML class diagram in Figure 9-10 shows, the ReservationClientModel has methods to service the widgets of the application's Swing user interface. This class has five groups of operations and nine properties.

click to expand
Figure 9-10: The class diagram of the ReservationClientModel

In their implementation, the methods of the ReservationClientModel follow several design strategies to satisfy the client's requests. First, they convert, when necessary, between the logical view used by the widgets to the logical view used by the service. This is particularly evident in converting between the row and column indices used by the JTable to the Collection used by the data service. Second, the operations in the ReservationClientModel delegate to the ReservationService to get the relevant persistent objects. Finally, the operations in the ReservationClientModel completely encapsulate the live persistent objects and all JDO exceptions. If the model encounters a JDO exception, it displays the error message to the user. After the user has clicked the OK button on the error report window, the ReservationClientModel either returns a reasonable default value to its client widget, or when no return value is required, it performs a no-op.

The operations in the first group shown in Figure 9-10 construct the model and connect it to a persistence manager. They also commit a transaction, roll back a transaction, and refresh all persistent objects. In the case of a Swing application, it is essential that the model can respond to service calls even when there is no connection to live data through an open persistence manager. Without a connection, the rental Swing application is not useful, but at least it is visible, ready to respond to a user request to connect, and able to display any difficulties in making or keeping a connection.

The second group of operations inform the model of the view desired by the client widgets. For some applications, it makes sense to have the ability to support all views simultaneously. For the rental Swing application, it is sufficient that the model supports one view at a time.

The third group of operations provides information that the widgets need in response to the requests that the widgets can formulate. Many of the widgets, such as the JTable used to present the rental information, use indices to refer to the information needed. The application data model accommodates the logical model of the widget.

The fourth group of operations provides for cleaning and populating the datastore with the testing data. The fifth group of operations supports listeners who need to be notified when the model changes. The listeners, of course, are Swing widgets that need to change what they display if the model changes information or changes the view.

The properties of the ReservationClientModel all derive from either the operations of the class or the properties of persistent objects or collections of persistent objects that the model manages.

As Figure 9-10 indicates, no method or property in the ReservationClientModel throws a checked exception or a JDO exception. This is important because the Swing widgets are not equipped to handle exceptions thrown from the application client model.

Overall Architecture of the Rental Swing Application

By this point, the architecture of the rental Swing application has become clear. Although some three dozen classes make up the application, the architecture is summarized by the relationships between the four key architectural elements shown in Figure 9-11.

click to expand
Figure 9-11: The architecture of the rental Swing application

As shown in Figure 9-11, various classes called Swing widgets use the ReservationClientModel, which in turn uses the ReservationService. Both the ReservationClientModel and the ReservationService use the application data classes. The ReservationClientModel encapsulates JDO, the application data objects, and JDO exceptions. Thereby, it isolates objects in these classes from the Swing widgets. In addition, the ReservationClientModel converts from the logical view of information needed by the Swing widgets to the persistent object model found in the application data classes and used by the ReservationService.




Using and Understanding Java Data Objects
Using and Understanding Java Data Objects
ISBN: 1590590430
EAN: 2147483647
Year: 2005
Pages: 156
Authors: David Ezzio

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net