As discussed in Chapter 11, both the J2EE and the B2B architectures have strengths and weaknesses but are not mutually exclusive. The B2B architecture supports widely distributed business objects. The J2EE architecture supports transaction systems. Common sense dictates using the B2B architecture for interaction between business objects and decomposing each business object using the J2EE architecture. Bass, Clements, and Kazman [Bass 98] refer to this as hierarchical heterogeneous architecture styles: A component of one style, when decomposed, is structured according to the rules of a different style. The question now becomes, "How can RSS be described within this architecture?" RSS, as we have already stated, is a very large system encompassing a wide range of functionality that will be distributed across multiple business objects in the B2B architecture. However, RSS, which has historically been a transactional system, is being modernized by a single development team and will be deployed on a single platform or collection of platforms connected by a high-speed LAN. Therefore, does it really make sense to implement this system as a collection of business objects communicating asynchronously without the support of a transaction manager? On the one hand, building the system as a collection of business components would allow business objects to be easily shared/integrated with other systems within the enterprise. The overall system configuration would be highly configurable. Business objects could be easily relocated to a remote site running on a low-bandwidth WAN connection or replaced with a COTS product. On the other hand, system performance might suffer. This interesting question is not easily solved without modeling the multiple-business object approach to determine whether performance will be adequate. In the end, we decided to decompose the system into multiple J2EE-based business objects and to provide a common BSR interface to each business object for ease of integration with external systems. Business objects on the same platform or LAN communicate directly using the transactional-based method invocations, whereas business objects on remote systems or systems accessible only through low-bandwidth WANs are integrated using OAGIS BSRs. The identified business objects include [1]
Figure 12-2 shows the relationship of these business objects in RSS. Figure 12-2. RSS high-level architecture
Business objects on a single platform or LAN communicate using EJB- based transactional method invocation (RMI/IIOP). These J2EE-based business objects exchange BSRs with external systems over MQSeries. Business objects communicate with the RSS operational database to perform operations on behalf of applications. The data warehouse synchronizes as required with the operational database to update data values. Data for each business object is stored in a single operational database because we have already selected performance over modifiability as the critical attribute driver for the architecture. It is our decision to allow a high degree of coupling between business objects running on the same platform. In essence, the RSS architecture is a three-tier layered architecture. The application components represent the presentation tier, the business objects represent the business logic tier, and the database represents the data tier . A simplified view of an application is shown in Figure 12-3. RMI is used to communicate between application components and business objects. SQL is used as an interface between business objects and the database. A more detailed view of the architecture is shown in Figure 12-4 and is discussed in the following sections. Figure 12-3. Simplified view of an RSS application
Figure 12-4. Detailed view of the RSS architecture
Application ComponentsApplication components are responsible for providing information from the user to the computer system and for presenting information from the computer system to the user. Application components include user interfaces, reports , query building, and application-specific work flows. The structure of an application component is shown in Figure 12-5. The application component contains the following elements:
Figure 12-5. Application component structure
Application components can communicate with business objects by using BSRs, nonstandard component APIs, or a combination of both. Using BSRs maintains a greater degree of independence between applications and business objects. In particular, using nonstandard interfaces to business objects can create a dependency on a particular implementation of a business object for the application component. However, the granularity and performance of BSR-based communication may be inadequate to support user interactions. As a result, it is acceptable to use non-BSR communication with business objects in this situation. The architecture uses RMI to communicate between application components and business objects. Application components access data through the business objects, except for reports and ad hoc queries. Database access for reports is done through a reporting layer, whereas ad hoc queries access the database directly. Business ObjectsBusiness objects encapsulate the business logic and data of a business entity. Business objects communicate internally using RMI, externally using BSRs, and with the database layer using SQL. Each business object defines one or more service components, one or more data components, and wrapper components as required. A service component provides the functionality of a business object. A data component encapsulates data elements maintained in the RDBMS. A wrapper component is used for communication with legacy systems that do not have a BSR interface. Service ComponentsService components provide the business logic for a business object. Service components communicate with one or more data components to obtain required information, to respond to a call from another service component or application, to respond to a BSR, or to generate a BSR. Service components must use the BSR interface to communicate with external business objects and systems. Service components also provide interfaces for use by application components, other service components within the business object, and other local business objects. Service components do not access the database directly; they access it through data components. Service components perform bulk operations on data components on behalf of Java servlets in application components. The Session Entity Faade pattern [J2EE 01a] provides functionality similar to that provided by a service component. The service component acts as a faadea unified, simple interface to all the service's clients. Those clients use the service component as one-stop shopping for functionality and data access. Service components are implemented as EJB session beans. Session beans act as agents for clients and are typically instantiated for each client session. Order placement is a good example of functionality that would be implemented as a session bean. Accessing data components through service components also simplifies transaction management. For example, if the session bean implementing the service component specifies transactions as required, all entity beans invoked by the session bean will run in the same transaction context as the session bean. EJB defines stateless and stateful session beans. Stateless session beans are components that model business processes performed in a single method call. These beans hold no conversational state on behalf of clients, meaning that they are free of a client-specific state after each method call. For a stateless session bean to be useful, the client must pass all client data that the bean needs as parameters to business logic methods . Because they can support multiple clients, stateless session beans can offer better scalability for applications with a large number of clients. Typically, an application requires fewer stateless session beans than stateful session beans to support the same number of clients. Stateful session beans hold conversations with clients that span multiple method invocations. Stateful session beans store a conversational state within the bean. This state must be available for that same client's next method request. The RSS architecture uses stateless session beans to provide generic services to multiple clients. For example, a service that manipulates multiple rows in a database and represents a shared view of the data can be modeled as a stateless session bean. One example of such service is a catalog listing products and associated prices. Because all users are interested in this information, the stateless session bean can be easily shared. Stateless session beans are the best choice for implementing behavior to visit multiple rows in a database and presenting a read-only view of data. Session beans encapsulate a business task. As a result, there is typically a strong correlation between service components and system use cases. In RSS, examples include order placement, requisition, and delivery. Often, use cases contain steps that are common to other use cases, such as obtaining a list of items. These steps are usually extracted from the use case and modeled as use cases themselves . They are associated to the original use case with the include relationship. These steps may be modeled as session beans or simply as reusable Java classes. Data ComponentsData components provide encapsulation. They communicate with the database to obtain or update information. In this architecture, data components are implemented as entity beans. Data components represent data in a database and add behavior to that data. Instead of writing database logic in an application, the application accesses data through the remote interface to the entity bean. Data components can use either bean-managed or container-managed persistence. With bean-managed persistence (BMP), database calls are implemented within the bean, using, for example, JDBC. With container-managed persistence (CMP), there is no persistence logic inside the bean; rather, the EJB container manages data persistence based on information provided in the deployment descriptor. Even though container-managed persistence allows beans to be smaller and eliminates the need to develop data-access logic, bean-managed persistence proves to be better in large and complex systems, for three reasons
Data components should represent coarse-grained objects, such as those that provide complex behavior beyond simply getting and setting field values. These coarse-grained objects typically have dependent objects with real domain meaning only when they are associated with their coarse-grained parents. These finer-grained, dependent-data subcomponents can be implemented as Java classes. Data components apply the Aggregate Entity pattern. This pattern uses an aggregate entity bean to model, represent, and manage a set of interrelated persistent objects rather than representing them as individual fine-grained entity beans [Larman 00]. An aggregate entity bean consists of a tree of objects. For example, an invoice can be represented as a coarse-grained entity bean. The lines in the invoice are dependent objects. This representation avoids the problems that emerge when the entity bean schema matches the relational schema. To use the same invoice example, this would mean defining a separate entity bean for each invoice header and for each line in the invoice. Examples of problems that could emerge include
Figure 12-6 shows the Aggregate Entity pattern, in which entity beans represent independent objects with associated sets of dependent objects, or subcomponents, thus providing a coarse-grained, entity bean schema. The Aggregate Entity pattern states:
Figure 12-6. Data component internals: Aggregate Entity pattern
This form of aggregation requires access to subcomponents always to be performed through the entity bean. One way to reduce the overhead of having to go through the entity bean is to have group operations. In Figure 12-6, for example, Entity Bean 1 could have a method SetSubentity1() that sets all the attributes in Subentity 1 without having to call an individual set method for every attribute. Elements identified as data components have common qualities. In particular, they
Wrapper ComponentsA wrapper component is an adapter that allows a service component to communicate with an external system that does not have a BSR interface. Figure 12-7 illustrates how to use BSR-to-API and API-to-API wrappers. Use a BSR-to-API wrapper to communicate with an external legacy system that may eventually become a business object of its own. Use an API-to-Native-API wrapper when a component communicates with an external legacy system that is accessed only by components in the same business object or that will eventually become a part of the same business object when modernized. Figure 12-7. Types of wrapper components
BSR InterfaceThe BSR interface provides service for communication between business objects. This interface can be constructed using a layered architecture:
The BSR interface package must receive BSRs, parse the BODs contained in the BSRs, and translate the BODs into calls to service components. The BSR interface package also must generate BODs and send BSRs when requested from a service component or as a confirmation/reply to a BSR. Figure 12-8 shows the parts of a BSR interface:
Figure 12-8. Elements of a BSR interface package
Figure 12-9 illustrates the operations that take place when the BSR interface receives a BSR.
Figure 12-9. Processing an incoming BSR
Figure 12-10 shows the operations that take place when a service component invokes the service of a BSR interface.
Figure 12-10. Processing an outgoing BSR
If a BSR is required as a reply to an incoming BSR, the BSR interpreter requests the services of the BSR constructor, and the operations in steps 2 through 5 take place. The BSR interface receives incoming messages from MQSeries and sends the BSRs to the interpreter. The BSR interface also accepts outgoing BSRs and sends them to the MQSeries queue of the intended recipient system. Alternatively, the BSR constructor can communicate with the external BSR directly. The problem with this approach is that two components must now interact directly with MQSeries instead of isolating this interface to a single component. |