Package com.objectwave.appArch

An attempt to capture some common application architecture related code, such as: Screen Flow, Security, and application initialization.


Interface Summary
PresentationModelIF A presentation model is both a producer of and consumer of events.

Class Summary
AsynchStatusManager Set the default status manager to be an instance of this class if you wish to support asynchronous events.
ConfigurationProperties A utility class that will load property information in from a property file.
EventPool Any events generated by any of the Producers will be passed on to all PresentationModel consumers.
EventSupport Used to facilitate Events.
Queue An event queue.
UIManager This class actually handles the frame/dialog opening, frame/dialog closing, and system exit functions of the application.
WindowModel A window model is different from a presentation model in that it holds the common event pool.

Package com.objectwave.appArch Description

An attempt to capture some common application architecture related code, such as: Screen Flow, Security, and application initialization.

Application Launch

When an application begins, there are set of core initialization routines that may need execution. After we initialize all aspects of our application, we typically need to Logon to our system. Once we have sucessfully logged into our system, we open the main screen of the application. Application is launched!


Many of the initialization routines are quite common. There exists a class that contains the common functions necessary at startup. Here are the functions most commonly used:
setLookAndFeel() is used to set the look and feel of the application to WindowLookAndFeel. This method exists to provide compatability between different Swing versions. Eventually, this will no longer be needed.
loadDefaults(Object) will load in a properties resource. This properties resource will be obtained with the java.lang.Class>>getResourceAsStream(String) method, hence the reason it takes an argument. The Object argument should either be a class or an object, and this argument will be used when locating the resource. The String is the ini file name. You can also call the loadDefaults(Object, String) method to both load the speficied resource and set the static StartupRoutine variable 'ini'. This variable is the initialization file name.
initPersistence(String []) is a common way to setup all of the necessary persistence related information. If the parameter is empty, then there is nothing special about the persistence. If the parameter contains at least one value, that value is expected to the name of a serialized object pool. If the object pool is located, then we will NOT connect to the database. Our default Broker will be the ObjectPoolBroker. If object pool is not found, we connect to the database and begin using the object pool support. When the application is exited, the object pool is written to the provided file name.
logExceptionsToFile(String fileName). The name of this method says it all. Write any exceptions that occur in the named file.
manageTransactionWithScreenActivation() This call will cause our setContext method to be called on the TransactionLog with a parameter of what every screen is activated. This can be VERY useful if screens define the beginning and end of a Transaction.

Logging into an application

This process is mix of custom application specific code, and some generic Logon support. The com.objectwave.uiWidget.LoginDialog contains a UserName and Password text fields. When the Dialog is closed, it fires a com.objectwave.uiWidget.LoginEvent. Every associated com.objectwave.uiWidget.LoginListener receives this event, however, what is done with the event is application specific. This class validates the login in some manor, and in some way communicates the success or failure of the login with the launching application class.

Opening the first screen

To open a screen that is adhering to the PresentationModel design approach, requires some setup.

Presentation Model

We have implemented an Event based approach for all interaction between various screens. This minimized coupling between our screens and our various panels allowing the developer to use those screens and sub panels that accomplish what is needed. This eliminated many dependencies of one screen upon another, and allows the developer to change the look and feel of the application, without impact on the behavior. To fully understand the presentation model you need a firm grasp of Java's AWT event model, since our event approach is very similar. The com.objectwave.appArch.PresentationModel for a given class can also be referred to as the 'controller' object, since it manages the interaction between the business model and the User Interface.

Let's look at an example.
Every PresentationModel(PM) can produce events (fireEvents) or consume events (respond to packetAvailable method calls). It is with these events that a PM interacts with the rest of the system. A PM may have 1, many, or no consumers attached to it. And a given PM may or may not be a producer to any other PM. This is the loose coupling that our Event model provides. Hence, if we wish to change the system, or reuse a component in a another part of the system, we merely need to hook up the PMs and fire the appropriate events.

( a java.awt.Component )



-- has a -> PresentationModel --> has many > Consumers

{ (a Custom UI) }


has many >



implements ModelSupport





Upon the creation of a composite component (one that has many components implementing ModelSupport) the code would typically go like this.

comp = new SubComponet();
ModelSupport supp = (ModelSupport)comp;
PresenationModel pm = supp.getPresentationModel();

When using the 'PresentationModel>>addPresentationModel(PresenationModel pm)' method the parameter 'pm' is added as both a consumer and a producer to the receiving presentation model. If you wish to 'hear' events from another presentation model, but not allow the other presentation model to 'hear' your events, use the PresentationModel>>addProducer(PresenationModel pm) method.
The PresentationModel>>addConsumer(PresenationModel pm) method would allow the parameter 'pm' to hear my events, but I won't hear any of the parameter's events.

Since many objects may produce and consume the same events, it is important that the objects are 'hooked' up correctly. Strange, or inconsistent, behavior may occur if your events are delivered to listeners that you may not suspect.

Most of our Composite Components may wish to avoid connecting one PM to another PM and instead place all PMs into a common pool. The com.objectwave.appArch.EventPool class provides this behavior. Any event generated from one of the PMs in the event pool will be delivered to each and every PM in the pool (other than the source PM). Since this is common situation when creating Frames we have specialized PresentationModel that automatically places elements into the Pool called com.objectwave.appArch.WindowModel. In addition to providing pool support, the WindowModel class provides listeners to handle the open(), and closing() of a frame.

The actual setVisible(true) call comes from the com.objectwave.appArch.UIManager class. All windows (be them Dialogs or Frames) should be opened with the UIManager. Failure to do so eliminates our ability to actively manage screen navigation and controlled system exits.
To exit the application our code will do something like the following
try {
} catch (PropertyVetoException e)
{ System.out.println("Exit was vetoed for some reason!");

By using the UIManager to exit the application, you are giving all of the registered PropertyVetoListeners a chance to Veto the system exit. The property name will be SystemExit when the firePropertyVetoChange method is called.