Beautiful Code [244]
The client tier consists mostly of standalone GUI-based Java applications implemented with Swing components and a few web-based applications. A J2EE-compliant application server runs in the middleware and hosts all the services that respond to requests from the client applications. We implemented the services using Enterprise JavaBeans (EJBs). The data tier consists of the data sources and data utility programs. Also written in Java, these utilities monitor the file server for the processed data and image files. The utilities generate metadata for the files as soon as they're released by the mission managers.
Figure 20-2. CIP's three-tiered service-oriented architecture
Using an SOA based on J2EE gave us the option to use these well-defined beans (and others) wherever appropriate in the design of a large enterprise application. Stateless session beans handle service requests without remembering any state from one request to the next. On the other hand, stateful session beans maintain state information for clients and typically manage persisted information that the beans read from and write to a data store. Having multiple options in any design situation is important when developing large complex applications.
In the middleware, we implemented a stateless session bean as a service provider for each service. This was the facade from which we generated a web service that the client applications use to make service requests and get back responses. Each service may also access one or more stateful session beans that are business objects supplying any necessary logic that must maintain state between service requests, such as where to read the next block of information from a database in response to a data request. In effect, the stateless beans are often the service dispatchers for the stateful beans that do the actual work.
There is much beauty in this type of architecture! The architecture embodies some key design principles:
Standards-based
Especially at a research institution (like the NASA Ames Research Center, where we designed and developed CIP), there is always a strong temptation to invent something new, even if the result is reinventing the wheel. The MER mission afforded the CIP development team neither the time nor the resources, and our goal was to develop production-quality code for the mission, not necessarily to do research.
In any large application, the key to success is integration, not coding. The beauty behind adhering to industry standards and best practices is that we did less coding by using COTS components, and because of common interfaces, these components were able to work well with each other. This enabled us to make guarantees to the mission managers that we would deliver functional and reliable code on time.
Loose coupling
We loosely coupled the client applications and the middleware services. This meant that once the application programmer and the service programmer agreed on an interface between the two, they could develop their respective code in parallel. Any changes on one side didn't affect the other as long as the interface remained stable. Loose coupling was another major factor that allowed us to complete a large multitiered SOA application on time.
Language independence
The client applications and the middleware services used web services to communicate with each other. The web services protocol is an industry standard that is language independent. Most of the CIP client applications were written in Java, but the middleware also served some C++ and C# applications. Once we got a service to work with a Java client, it was relatively simple to get it to work with another client written in any language that supported web services. This greatly expanded the usefulness and usability of CIP with little extra cost in time or resources.