Level: Intermediate Harini Srinivasan (harini@us.ibm.com), Software Engineer, IBM Jim Conallen (jconallen@us.ibm.com), Senior Software Engineer, IBM Dr. Eoin Lane (eoinlane@us.ibm.com), Senior Software Engineer, IBM Corporation
22 Nov 2006 This series explores reusable assets such as recipes, software patterns, and models and how they can accelerate the development of SOA solutions. This fourth article explores the requester-side caching pattern to address performance nonfunctional requirements when implementing reusable services. The requester-side caching pattern was harvested from a real SOA engagement and has been reused in a number of other SOA applications and engagements. An aspect logging feature pattern will be used to address the traceability nonfunctional requirement. The article also demonstrates how a Rational® Software Architect™ implementation of this pattern can be used in a model-driven development environment for service implementation optimization.
Introduction
The previous articles of this series introduced the SOA implementation and optimization services recipe as well as an accompanying reference example. This recipe, available as a reusable asset, provides prescriptive guidance on how to use nonfunctional requirements to determine which architectural patterns are needed to build architecturally consistent applications and to provide architectural traceability and accountability. The recipe contains a reference example that shows how to use a model-driven development (MDD) approach that leverages the modeling capabilities of IBM Rational Software Architect (RSA) to develop use-case, analysis, design, and services models.
Part 3 of this series also showed how a legacy application can be surfaced using a top-down approach. The reference example accompanying the SOA implementation and optimization services recipe detailed how a reusable catalog service model was identified and specified using domain decomposition of the "lookup item" business process. The WS response template pattern was then applied to the catalog service model to provide a more flexible service model by allowing the requester fine-grained access to a course-grained interface. The pattern was used because it matched the nonfunctional requirements of flexibility and interoperability required for this service implementation. The controller (used to implement the service business logic) of the catalog service implementation was then used to connect to the legacy catalog application. This is a classic example of a legacy application, and it provides the core functionality necessary to provision a service. However, this application must now be surfaced as a service, and it will need to adhere to a different set of nonfunctional requirements that existed when the original application was created.
This article focuses on satisfying other nonfunctional requirements for this new catalog service. These nonfunctional requirements are around service performance, service scalability, and traceability. In a service-oriented architecture, where the number of users of the service is often not known at the time the service is created, the nonfunctional requirements of performance and scalability are often commonplace. A well-known pattern to address performance nonfunctional requirements is a caching pattern. This article details the requester-side caching pattern, which addresses caching on the requester side.
We also provide an example of how an aspect can be applied in a model-driven development environment. The particular aspect we consider is a logging aspect, used to satisfy a service traceability nonfunctional requirement.
Apply the appropriate patterns
SOA is about business agility, and one way to achieve agility is to identify the core business components. Once the components have been identified, the business processes and services associated with them can be identified and specified. Business process decomposition can reveal the reusable IT services needed to provision these business processes and services. The input and output messages of the IT services and the domain objects that these services manipulate also need to be specified. From an IT perspective, these services can be modeled as use cases, and the functional and nonfunctional requirements of the use cases can be traced (in a tool like Requisite Pro). With all these moving parts, how can the complexity of this environment be managed? In particular, how can we build out these services to ensure that their nonfunctional requirements are satisfied?
Patterns are one way to manage this complexity. Patterns are a repeatable solution to a problem in context, and typically are described by a pattern specification. Pattern specifications include a forces section that outlines when the pattern should be used. Feasibility for a solution is ultimately determined by nonfunctional requirements such as scalability, performance, security, transactionality, maintainability, and interoperability. By mapping these nonfunctional requirements to the forces section in the pattern specification, we achieve traceability and accountability in architectural decisions.
This series of articles addresses four SOA patterns. Each pattern satisfies certain nonfunctional requirements typical to an SOA application. Following is a list of the patterns and a brief description of the nonfunctional requirements they each address (see Resources for a full description of the pattern specification):
- The WS response template pattern provides service interface flexibility, interoperability, and maintainability. See Resources for the WS response template pattern specification.
- The requestor-side caching pattern specification improves service performance. See Resources for the requester-side caching pattern specification.
- The preferred data source pattern is a microflow pattern for service aggregation.
- The logging pattern provides service invocation traceability. See Resources for more on model-driven development and aspects.
Before we examine these patterns in detail, it is helpful to consider an n-tier architecture as outlined below. A three-tier architecture has a presentation tier, a business tier, and persistence tier. In an SOA environment, when we are dealing with the implementation of reusable IT services, we can separate the business tier further into a service layer, a controller layer, and an entity/object management layer (see Figure 1). It helps to think about layering in the context of an application server container.
The service layer is responsible for specifying the operation used in that service and the content of the message used by these operations. It is also responsible for serializing and deserializing messages in and out of the container. The controller layer is responsible for implementing the business logic of the service, achieved by invoking other services, other controllers, or an entity management layer. The entity management layer is responsible for entity management and ensuring the transaction integrity of that object within the container.
The WS response template we examined in Part 3 of this series can be applied to the service layer. (0ther patterns -- such as a WS-security pattern -- that directly impact the service definition would be applied at this layer.) The requester-side caching pattern is applied at the controller layer. The aspect logging pattern will also be applied at the controller layer. And the preferred data source pattern, which we will examine in greater detail in the next articles, can be applied in the controller layer. The session facade, message facade, and the business delegate core Enterprise Java™Beans patterns belong in the controller tier. But the data management pattern of the entity, and Data Access Object (DAO) core Enterprise JavaBeans patterns belong in the entity layer. Figure 1 shows the n-tier layered architecture for service implementation and where these patterns are applied.
Figure 1. n-tier layered architecture for service implementation
Performance, performance, performance...
In Part 3 of this series, we applied the WS response template pattern to a UML model of the catalog service. This created a new and more flexible model of the catalog service. The new catalog service model was then transformed using a UML-to-WSDL and a UML-to-XSD transformation to produce the corresponding stub and skeleton code. The catalog service was then implemented by a service controller, and this controller accessed the legacy catalog application to provision the catalog data required by the catalog service. Figure 2. shows this sequence of events.
Figure 2. getCatalog() WS response template sequence diagram
The sequence diagram shows that every time the catalog service is called (looks for an SKU from a particular catalog), the entire catalog must be retrieved from the legacy catalog application before being sent to the navigator. Since the existing catalog application is immutable, and the catalog items are largely read-only, this is an ideal candidate for the requester-side caching pattern. The requester-side caching pattern will cache the requested catalogs on the requester side so that the particular catalog remains cached for further queries. Before looking at the requester-side caching pattern in more detail, we'll digress a little to understand how this pattern might have been harvested from a real engagement. The customer here is ficticious, but the scenario by which the pattern was harvested is very real.
Field-based development of the requester-side caching pattern
This pattern is an example of field-based development where an application/architectural pattern was harvested from a real customer engagement. The customer name has been changed but the technical details of the problem and the solution are accurate.
Consider a fictional state agency called HIPPO that manages and processes health care claims and other social services. HIPPO has a number of business processes around claims management such as "process new claim." Each of these business processes consists of a number of tasks that need to be completed to finish a particular business process. A typical HIPPO business process is a long-running, interruptible business process that, on average, makes up about 10 business tasks. Some of these tasks can be automated, such as retrieving a claim, and some require human intervention, such as approving/rejecting a claim. HIPPO typically deals with about 3,000 active claims a day. In order for HIPPO to operate more effectively, they decided to move toward a call-center design to centralize processing of claims. HIPPO has functional requirements around automating these business processes and also has a number of nonfunctional requirements around performance, transactionality, data integrity, and more.
To achieve these functional requirements, HIPPO modeled their business processes using WebSphere® Business Integration (WBI) Modeler. WBI Modeler was then used to generate Business Process Execution Language (BPEL) so the business processes could be hosted inside WebSphere Process Server, and multiple instances of a business process could be instantiated. Each process can have multiple instances in the system at any time. Each instance of a process has a number of human tasks, and WebSphere Portal Server was used to query WPS and to display these human tasks. The task could then be managed by a call center where a HIPPO employee could log onto the system and see what task she has been assigned to. These tasks could then be sorted by priority, due date, and other task metadata. A manager could also log onto the system and assign new tasks to an employee or view the task status of a particular employee.
Performance was a key nonfunctional requirement from HIPPO for the portal application. This required the portal application to be able to display the task list within a specified time limit, perhaps two seconds. However, every time the user asked for a system refresh by sorting her tasks by due date, for example, the portal application had to issue a new query to WPS to repopulate the task list. As the number of active process instances increased, the system's performance degraded significantly.
After much consideration, the solution was to create a requester-side cache on the portal side to cache the human task information. As the portal application received tasks from WPS, they were cached locally. On a task list refresh, the portal application would first check to see if the items where in the cache and if not, would query WPS. This solution satisfied the performance nonfunctional requirements.
The requester-side caching pattern can often provide an effective solution to a performance problem, but the architect needs to carefully consider a number of factors. These factors include the nonfunctional requirements of the data to be cached, such as the volatility of the data, the latency of the cache, and whether the cache should be prepopulated or not. The next section examines the forces behind considering the requester-side caching pattern as a solution. Let's look at the pattern in more detail.
The requester-side caching pattern
The requester-side caching pattern mediates the interaction between one or more clients and one or more data providers. The mediation consists of holding data items produced by the provider(s) and using them to support requests from the client(s). The purpose of the mediation is to speed up and/or reduce the cost of accessing data. This very general pattern has many variations to meet different design goals. The pattern should make it easy for you to make design decisions and to document the decisions made around the cache and policies.
Class diagram
Figure 3. Requester-side caching pattern class diagram
The class diagram (Figure 3) shows the decorator (Gang of Four design patterns) nature of the pattern. The provider is the ServiceImpl class, which implements the IService interface. This interface typically has operations like getItem() and getItems() where the item is some entity. The getItem() operation takes a primary key to identify the item, whereas the getItemKeys() typically takes a selection criteria that can be converted to a set of primary keys using the getItemKeys() operation. The IService interface may also have a changeItem() operation which, by definition, causes a change to the internal structure of an item. The decorator is then the CacheServiceImpl class. The CacheServiceImpl implements the IService interface and wraps the ServiceImpl by providing caching capabilities to the getItem() and getItems() operations.
Sequence diagram
Figure 4. Requester-side caching pattern sequence diagram
The sequence diagram in Figure 4 shows the requester using the CacheServiceImpl client-side proxy to call getItems(). The getItems() implementation will first check the cache to see if the items can be found there. Failing to find the items in the cache, the getItems() will then get the items from the provider. The items will then be stored in the cache for future use. The getItems() method uses the getItemKeys() operation to get a unique set of primary keys and then sequentially calls the getItem() operation with each of those keys.
The requester-side caching pattern implementation
Numerous requester-side caching pattern implementations can now be created based on the pattern specification. (See the sidebar in Part 3 in the series to understand the difference between a pattern specification and a pattern implementation.) Typically, any implementation would provide some level of automation for applying the pattern. The implementations we examine will use the model-driven development environment of Rational Software Architect. (See the sidebar for more information on modeling with aspects-based implementation of this pattern specification.) For the purposes of this section, we will examine an implementation of the requester-side caching pattern using the RSA patterns engine.
This RSA patterns engine implementation assumes a UML model representation of the service or interface that needs to be accelerated. The approach to using this pattern follows the model-driven development approach of instantiating the pattern parameters to specific UML model elements of the service or interface. Once the pattern parameters are bound, additional UML elements such as the cache and the cache-aware service proxy are automatically created. A UML-to-Java transformation, invoked on the resulting model, will generate the resulting Java implementation artifacts. This implementation also allows the user to chose between a custom (in memory) user-defined cache or the WebSphere Platform dynamic cache. If the user chooses the latter, the pattern transformation will automatically generate configuration files to be used with dynacache.
This implementation of the requester-side caching pattern is created using the RSA patterns engine. Authoring a pattern with the RSA patterns engine results in a Eclipse plug-in that can be packaged as a reusable asset using the Reusable Asset Specification (RAS). (See Resources to learn more about the Reusable Asset Specification, and also refer back to Part 1 of this series to understand more about patterns and reusable assets.) The result of this packaging is an RAS asset. The RAS asset, along with its associated metadata, can then be deployed to a RAS server such as the developerWorks RAS repository. In the next section, we'll show you how to access this pattern asset from the developerWorks RAS repository using an RAS client. This pattern asset will be imported in RSA, and RSA functionality can be extended to allow a user to apply the requester-side caching pattern to a model.
Applying the requester-side caching pattern
The requester-side caching pattern implementation can be imported into RSA using the recipe. First navigate to the "Apply patterns to a service implementation" section in the recipe and expand the section titled "Applying the requester-side caching pattern." Locate the asset in this step and select Import (see Figure 5).
Figure 5. Import the requester-side caching pattern implementation
This will install the requester-side caching pattern implementation into RSA. Once the pattern has been installed, it will appear in the Pattern Explorer as shown in Figure 6.
Figure 6. Pattern Explorer showing the requester-side caching pattern
Note: This article continues from Part 3. If you want to start from a clean workspace, import the WS response template final interchange project. See Downloads for the RSA project, packaged as a project interchange file. (To import into RSA, choose File>Import>Project Interchange.)
The following steps show how to navigate the recipe and import the legacy catalog model into RSA. The requester-side caching pattern is then applied to this model and the corresponding cache-aware code is generated in a UML-to-Java transformation.
- Open up the SOA Catalog Entity Design Model. Figure 7 shows the internal structure of the SOA Legacy Catalog Application Design Model.
Figure 7. Import SOA Catalog Legacy Design Model
- Navigate to the com.ibm.retail.catalog package and open the UML class diagram there. Figure 9[The text is missing a reference to Figure 8. -ec] shows the UML class diagram for the back end Catalog service. The model shows an interface and an implementation for the catalog service. There are three operations here:
-
getCatalog(): Used to get a whole catalog
-
getCatalogs(): Used to get a series of catalogs based on selection criteria
-
getCatalogKey(): Used to convert the selection criteria to a set of unique keys
Figure 8. SOA Catalog Legacy Design Model outline
Figure 9. SOA Catalog Legacy Design Model UML class diagram
- In the modeling perspective, drag the requester-side caching pattern to the open UML class diagram. Figure 10 shows the catalog entity design model before applying the requester-side caching pattern.
Figure 10. SOA Catalog Legacy Design Model before applying the requester-side caching pattern
The requester-side caching pattern takes the following parameters:
-
Service: The interface/class that contains the operation we want to accelerate via caching (the CatalogService interface).
-
getItem: The operation on the service interface/class used to get a single item given an item key (the getCatalog() operation).
-
getItemKeys: The operation on the service interface/class used to get keys given a set of criteria (the getCatalogKeys() operation).
-
getItems: The operation on the service interface/class used to get items given a set of criteria (the getCatalogs() operation.
-
changeItemKey: The parameter in the change item operation that corresponds to the key of the item (for example, setItem()).
-
Cache size: The size of the cache.
-
Clustering: A boolean value where true implies the underlying topology is clustered, and false implies the underlying topology is not clustered. (Set to false because we want to use in-memory cache, but set to true if you want to leverage WebSphere dynacache capabilities.)
-
Timeout: The value (measured in milliseconds) after which an item has to be evicted from cache.
Figure 11. SOA Catalog Legacy Design Model after applying the requester-side caching pattern
The output of applying this pattern is a number of UML class artifacts, as follows:
- An
AcceleratedCatalogService class is created. This class implements the CatalogService interface and encapsulates an implementation of it. This is a classic GoF decorator pattern design pattern. The AcceleratedCatalogService also has a reference to a Cache class.
- An in-memory cache implementation is also produced. If the clustering attribute was set to true, the
AcceleratedCatalogService would instead have a reference to a the WebSphere dynacache proxy.
- The
AcceleratedCatalogService and the Cache class are transformed into the corresponding Java classes using the UML-to-Java transformation (as shown in Figure 12). Both classes are generated into the RetailWeb folder (see Figure 13). The AcceleratedCatalogService and the in-memory Cache Java files produced from the UML-to-Java transformation can be found in the project interchange ZIP file (see the Downloads section).
Figure 12. UML-to-Java transformation
Figure 13. UML-to-Java transformation dialog box
- The catalog controller can now use the
AcceleratedCatalogService instead of the CatalogService to access the legacy catalog application. With one line of code, the catalog controller can now use the requester-side caching capabilities for caching the catalogs returned from the legacy catalog application.
Listing 1. AcceleratedCatalogService
**
public javax.xml.soap.SOAPElement getCatalog(
javax.xml.soap.SOAPElement key,
javax.xml.soap.SOAPElement requestTemplate)
throws InvokerException, WriterException {
Object catalog = null;
String keystr = ((javax.xml.soap.Node) key.getChildElements().next()).getValue();
System.out.println(keystr);
// Get a refer to the backend catalog service
com.ibm.retail.entity.catalog.CatalogService catalogImpl =
new com.ibm.retail.entity.catalog.CatalogServiceImpl();
// Use the generated Accelerated Catalog service
com.ibm.retail.entity.catalog.CatalogService cachedCatalogImpl =
new com.ibm.retail.entity.catalog.AcceleratedCatalogService(catalogImpl);
catalog = cachedCatalogImpl.getCatalog(keystr);
// Navigate the catalog to return a response template
return Navigator.navigate(requestTemplate, catalog, context);
} |
- Test the implementation with the Web Services Explorer. Figure 14 shows the an invocation of "Catalog A," where the client is only interested in the name, the description, and the start date of the catalog.
Figure14. Test with the Web Services Explorer
If the monitor Web service check box was checked during the WSDL-to-Java generation, the SOAP invocation request should appear in the TCP/IP tunneller with an empty SOAP response (see Figure 15). The two parameters in this request are as follows:
- The primary key for the catalog in this case catalog "A."
- The request template indicating that only the name, description, and start-date data should be returned.
Figure 15. TCP/IP tunneller
Do this invocation twice and watch the output console. The first time you will see an out from the legacy catalog application saying the following (see Figure 16):
This took a very very long time
Figure 16. WebSphere console output
On the second invocation, this message disappears as catalog A is now cached on the requester side. You can play with the request parameters being sent to the WS response template-aware catalog service.
- See the Downloads for the final RSA project, packaged as a project interchange file. (To import into RSA, choose File>Import>Project Interchange.
What has been accomplished?
Figure 17 shows the sequence diagram after having applied the requester-side caching pattern. The catalog controller always accesses the cache proxy first. Only after failing to find the items in the cache will the controller access the legacy catalog application and update the cache with the results. Applying the requester-side cache to the legacy catalog service has the following benefits:
- It provides guidance on how to correctly implement the caching solution on the requester side
- The WS response template-aware catalog controller can now make a caching-aware proxy using one line of code.
Figure 17. getCatalog() requester-side caching sequence diagram
The fundamental change to the catalog controller was changing to cached proxy from the legacy catalog implementation, as follows:
Listing 2. Legacy catalog implementation
com.ibm.retail.entity.catalog.CatalogService catalogImpl =
new com.ibm.retail.entity.catalog.CatalogServiceImpl();
catalog = catalogImpl.getCatalog(keystr);
|
to:
Listing 3. Cached proxy
com.ibm.retail.entity.catalog.CatalogService catalogImpl =
new com.ibm.retail.entity.catalog.CatalogServiceImpl();
com.ibm.retail.entity.catalog.CatalogService cachedCatalogImpl =
new com.ibm.retail.entity.catalog.AcceleratedCatalogService(catalogImpl);
catalog = cachedCatalogImpl.getCatalog(keystr);
|
The aspect logging pattern
 | |
Modeling with aspects
The version of the model-based AspectJ feature shown here is an early example of how AspectJ technology can be managed and delivered in a UML modeling environment. Since this initial version, the functionality has improved to appeal more to senior developers and architects responsible for specifying and configuring the development environment for a larger team of developers. See Resources for an introduction to the next version of Aspects for MDD in the article "Modeling with Aspects."
Aspects in this framework are compiled and deployed as Eclipse plug-ins, which are responsible for including the runtime component as a compiled JAR file. While this approach requires more work for simple aspects like the logging aspect discussed earlier, it's better for larger and more sophisticated aspects, like the First Failure Data Capture Aspect (see Resources). Not only is deployment to large teams easier, but it's less likely that the aspects can get accidentally modified.
|
|
Part of the goal of this pattern discussion is to include some way to log usage of the service and the cache. The logs can be used in a run-time environment to evaluate the real benefit of caching, and during development time, can be an additional tool for debugging. Since logging is not a direct part of the service or cache functionality, it can't really be considered part of the core design of the pattern. Instead, such a feature is best considered as orthogonal to the cache and pattern design, and ideally should be created and applied in such a way as to be unnoticeable in the design and implementation of the cache and service.
AspectJ rises to the occasion as an excellent architectural mechanism that can weave functionality like logging into an already compiled feature like the cache and service under development here. The Eclipse organization provides plenty of documentation describing AspectJ technology.
Because AspectJ is new and includes yet another programming language (a variant of the Java language), many have turned away from this potentially useful technology, fearful of an unknown learning curve. To make this technology more consumable across the larger development organization, we have provided a means to leverage predefined aspects at the modeling level. That is, architects and individuals knowledgeable in AspectJ can author and deploy AspectJ-based code to designers and implementers, allowing them to target and apply the aspect via the modeling abstractions. Everything else is handled behind the scenes.
Setting up the aspects
The aspect logging pattern implementation can be imported into Rational Software Architect using the recipe. First navigate to the "Apply patterns to a service implementation" section in the recipe and expand the section "Applying the aspect logging pattern." Locate the asset under this step and select import (see Figure 18).
Figure 18. Import the aspect logging pattern implementation
Importing the aspect logging pattern implementation will install the requester-side caching pattern implementation into RSA.
For this functionality to work, the RSA Eclipse shell must have the optional AspectJ developer tools installed, along with the aspect logging pattern. This feature includes a new preference page (Windows>Preferences>SOA IF>AspectJ Model-Based Logging). You can define AspectJ templates (AspectJ code that is generated and included in a compiled aspect) on this page (see Figure 19). The Add Default Templates button will add a couple of simple aspects for logging, but you can create any aspect code to associate with Java methods.
Figure 19. Setting up aspects using AspectJ inside RSA
Defining aspects this way allows you to modify the aspect code over time so that subsequent generations will result in new and improved logging code. This functionality does not have to stop at logging. It is perfectly reasonable to change the aspect code to not only log service and cache invocations, but to perform other operations, like computing statistics, or even invoking some Web service when an alarm condition is detected. Your needs and your imagination are the only limits to such a technology.
Applying the aspect logging feature
One of the nonfunctional requirements for the catalog service is traceability of every invocation of the legacy catalog application. The aspect logging feature is an ideal candidate to provide this cross-cutting concern in a noninvasive manner. The following sections illustrate how the aspect logging pattern can be applied in a model-driven development environment of Rational Software Architect to the catalog controller.
- Reopen the SOA Catalog Entity Design Model. Figure 9 shows the internal structure of the SOA legacy catalog application design model.
- Locate the
AcceleratedCatalogService class and right-click on getCatalog(). Figure 20 shows how to annotate the getCatalog() operation with the <<Log>> keyword.
Figure 20. Applying the aspect logging feature to the Accelerated getCatalog() operation
Figure 21. Selecting the specific aspect
- Select the
AcceleratedCatalogService class and repeat the UML-to-Java transformation. This time an extra AcceleratedCatalogServiceLogger aj file will be created. The following code shows the generated aj file:
Listing 4. Generated aj file
package com.ibm.retail.entity.catalog;
public aspect AcceleratedCatalogServiceLogger {
pointcut SimpleConsoleOut (AcceleratedCatalogService cls) : target(cls) && (
call( * getCatalog(String) )
);
before(AcceleratedCatalogService cls) : SimpleConsoleOut (cls) {
String op = thisJoinPointStaticPart.getSignature().getName();
String cl = thisJoinPointStaticPart.getSignature().getDeclaringType().getName();
System.out.println("Entering " + cl + "->" + op);
}
after(AcceleratedCatalogService cls) : SimpleConsoleOut (cls) {
String op = thisJoinPointStaticPart.getSignature().getName();
String cl = thisJoinPointStaticPart.getSignature().getDeclaringType().getName();
System.out.println("Exiting " + cl + "->" + op);
}
}
|
Now every time the AcceleratedCatalogService.getCatalog() operation is entered and exited in an AspectJ-aware project, a simple message is generated to the console.
-
Test the implementation with the Web Service Explorer. Figure 22 shows the invocation of "Catalog A," where the client is only interested in the name, the description, and the start date of the catalog.
Figure 22. Test with the Web Service Explorer
If the monitor Web Service box was checked during the WSDL-to-Java generation, the SOAP invocation request should appear in the TCP/IP tunneller with an empty SOAP response (see Figure 23). There are two parameters in this request.
- The primary key for the catalog is catalog "A."
- The request template will indicate that only the name, description, and start-date data should be returned.
Figure 23. TCP/IP tunneller
Figure 24 shows the logging of messages to the console.
Figure 24. WebSphere console output
See a larger image of the WebSphere console output.
Again, see Downloads for the final RSA project, packaged as a project interchange file. (To import into RSA, choose File>Import>Project Interchange.)
What's been accomplished?
We have realized the following benefits by using the aspect logging feature:
- We applied an MDD approach to the application of aspects.
- The architect/developer is no longer burdened with learning aspect semantics. Instead, thinking in terms of cross-cutting concerns such as logging can now be applied to operations on a model.
- For a particular project, aspects can now be identified and developed by the architecture team and the resulting aspect libraries distributed to the development teams for import into RSA.
- A logging aspect for the
AcceleratedCatalogService.getCatalog() operation can be created with a couple of mouse clicks.
Notes on pattern composability
The important lesson in the examples of the three usage patterns shown (WS response template, requester-side cache, and aspect logging) is that they can be applied to roughly the same application/services design and implementation area without adversely affecting each other. The pattern composability concept is an extremely important one for those hoping to harvest and develop rich libraries of patterns based on successes in working designs and implementations.
The three patterns discussed here were carefully designed to ensure that they focused on the specific problem they were addressing without making assumptions about other possible aspects of the design. For example, the WS response template pattern does not address or try to implement caching or logging. The caching pattern doesn't require the service its caching to implement additional interfaces like the map interface.
A good pattern implementation's concerns and contributions to the application design/implementation are limited strictly to the semantics of the pattern and no more. By limiting the effect of a pattern to only those aspects to which it is directly related, it is more likely to be composable with other existing and future patterns.
Conclusion
The catalog service examined in this article shows how a top-down approach to SOA service identification can lead to the discovery of reusable IT services that are usually provisioned by legacy applications. However, the reusable IT services often have radically different nonfunctional requirements (interoperability, performance, transactionality, traceability) to deal with a demanding SOA architecture than was considered with the legacy application.
This article addressed the nonfunctional requirements for performance and traceability of the catalog service. The requester-side caching pattern was applied to the catalog service controller in a model-driven development environment to optimize the catalog service implementation. This particular pattern has been harvested from another SOA context using field-based development, and has been reused in other SOA applications and engagements. The aspect logging pattern was also applied to the catalog service controller in a model-driven development environment to provide noninvasive traceability of catalog service invocations.
This article shows how patterns can be used to satisfy nonfunctional requirements for optimizing reusable service implementations. By carefully matching these nonfunctional requirements to the context, problem, and forces section of a pattern, their usage can also help reduce complexity and provide architectural traceability and accountability in constructing an enterprise architecture.
Animated demos
If this is your first encounter with a developerWorks tutorial that includes demos, here are a few things you might want to know:
Demos are an optional way to see the same steps described in the tutorial. To see an animated demo, click the Show me link. The demo opens in a new browser window.
Each demo contains a navigation bar at the bottom of the screen. Use the navigation bar to to pause, exit, rewind, or fast forward portions of the demo.
The demos are 800 x 600 pixels. If this is the maximum resolution of your screen or if your resolution is lower than this, you will have to scroll to see some areas of the demo.
JavaScript must be enabled in your browser and Macromedia Flash Player 6 or higher must be installed.
Download Adobe Flash Player.
Downloads | Description | Name | Size | Download method |
|---|
| Final Interchange Project from Part 3 | wsrt-catapp.zip | 10KB | HTTP |
|---|
| Legacy Catalog Application | LegacyCatalogApp.zip | 50KB | HTTP |
|---|
Resources Learn
- Learn more about the OMG standard for Reusable Asset Specification, version 2.2
by reading the specification.
- Learn more about modeling in RSA/RSM by reading "Model Structure Guidelines for Rational Software Modeler and Rational Software Architect" (Bill Smith, developerWorks, June 2005).
- Get details about IBM's Service Modeling Profile in "UML 2.0 Profile for Software Services" (Simon Johnston, developerWorks, April 2005).
- Read "Modeling with Aspects: An introduction to modeling with aspects" (Jim Conallen and
Eoin Lane, developerWorks, June 2006).
- Learn about the new aspect framework in "Aspects for MDD: Aspect-Based Tracing and First Failure Data Capture in Rational Software Architect" (Helen Hawkins and Sian January, developerWorks, July 2006).
-
"Web services response template pattern: a specification" (Eoin Lane, developerWorks, February 2006) examines the WSRT pattern specification and the solutions it offers to improve service interfaces.
-
"The requester side caching pattern specification: An overview"" (Harini Srinivasan, James Conallen, and Eoin Lane, developerWorks, October 2005)examines the requester-side caching pattern specification in detail.
-
Read about J2EE, RUP, and RSA in the article, "Developing a J2EE Architecture with Rational Software Architect Using the Rational Unified Process" (Jean-Louis Marechaux, developerWorks, August 2005).
- Visit the SOA and Web services zone on developerWorks to learn more about SOA.
- Stay current with developerWorks technical events and webcasts.
Get products and technologies
Discuss
About the authors  | 
|  | Harini Srinivasan is a member of the SOA Design Requirements team in IBM's Enterprise Integration Group. Her interests are in Web and SOA application performance analysis, model-driven development approach for building SOA solutions, the design and optimization of applications and runtimes. Before joining the EIS team in IBM Software Group she served as a Research Staff Member in the Software Technology department at the IBM T.J Watson Research Center.
|
 | 
|  | Jim Conallen is a software engineer in IBM Software Group's Rational Model-Driven Development Strategy team, where he is actively involved in applying the Object Management Group's (OMG) Model-Driven Architecture (MDA) initiative to IBM's Rational model tooling. Jim is a frequent conference speaker and article writer. His areas of expertise include Web application development, where he developed the Web Application Extension for UML (WAE), an extension to the UML that lets developers model web-centric architectures with UML at appropriate levels of abstraction and detail. This work served as the basis for IBM Rational Rose and IBM Rational XDE Web Modeling functionality. |
 | 
|  | Dr. Eoin Lane, senior solution engineer, is the lead for harvesting and developing of application pattern from key IBM SOA engagements and driving those patterns through IBM pattern governance process to accelerate adoption. Eoin also specializes in Model Driven Development (MDD), asset based development and Reusable Asset Specification (RAS) to facilitate SOA development. |
Rate this page
|