Application services are the workhorses of SOA. They represent the bottom sub-layer of the composed service layer (Figure 15.10), responsible for carrying out any of the processing demands dictated to them by the business and orchestration layers.
Figure 15.10. Application services establish the bottom sub-layer of the service layer.
Unlike services in business-centric layers, the design of application services does not require business analysis expertise. The application service layer is a pure, service-oriented abstraction of an organization's technical environments, best defined by those who understand these environments the most.
Because of the many real-world and technology-specific considerations that need to be taken into account, application services can be the hardest type of service to design. Further, the context established by these services can be constantly challenged, as technology is upgraded or replaced, and as related application logic is built or altered.
15.3.1. Process description
Figure 15.11 provides a proposed service design process for creating application service interfaces. Note that all references made to "application services" in this and remaining chapters imply that they are reusable utility application services.
Figure 15.11. The application service design process.
When viewing Figure 15.11, you'll notice that this process shares a number of steps with the previous entity-centric business service process. This is because both application and entity-centric services establish reusable service logic and therefore rely on parent controllers to compose them into business process-specific tasks.
However, there are key aspects in how the two processes differ. Note, for example, how the confirmation of the operation grouping context is isolated into a separate step. Establishing context for application services is an important and much less clear-cut part of service design.
Further, there is no step in which processing requirements are defined. This is primarily due to the fact that application services are responsible for implementing the processing details required to carry out the business logic of their parent business services. This, of course, does not mean that processing requirements for application services do not exist. They do, only they are part of the design of the underlying service application logic. Because we are only designing a service interface at this stage, it is not considered part of the process.
Let's begin putting together the application service interface.
We now switch over to the RailCo environment, where the focus is on the design of the Transform Accounting Documents application service candidate (Figure 15.12) that was modeled in Chapter 12.
Figure 15.12. The Transform Accounting Documents Service candidate.
This candidate establishes a "document transformation context," which justifies the grouping of its two very similar operation candidates:
These two lines of information establish a base from which we can derive a physical service design via the steps in the upcoming design process.
Step 1: Review existing services
More so with application services than with other types of reusable services, it is important to ensure that the functionality required, as per the application service candidate, does not, in some way, shape, or form, already exist. So it is very necessary to review your existing inventory of application services in search of anything resembling what you are about to design.
Additionally, because these services provide such generic functionality, it is worth, at this stage, investigating whether the features you require can be purchased or leased from third-party vendors. Because application services should be designed for maximum reusability, third-party Web services (which typically are built to be reusable) can make a great deal of sense, as long as required quality of service levels can be met.
RailCo is delivering this service as part of a solution that is replacing their original hybrid Invoice Submission and Order Fulfillment Services. The only other service that exists within the RailCo environment is the TLS Subscription Service, used to interact with the TLS publishing extension. Therefore, this step is completed rather quickly, as little effort is required to determine that functionality planned for the Transform Accounting Document service will not end up being redundant.
Step 2: Confirm the context
When performing a service-oriented analysis it's natural to be focused on immediate business requirements. As a result, application service candidates produced by this phase will frequently not take the contexts established by existing application services into account.
Therefore, it is important that the operation candidate grouping proposed by service candidates be re-evaluated and compared with existing application service designs. Upon reassessing the service context, you may find that one or more operations actually belong in other application services.
This step was not required as part of the entity-centric business service design, as the context of entity-centric services is predefined by the corresponding entity models.
A review of the one existing RailCo service and the additional services planned as part of this solution confirms that the grouping context proposed for the two operation candidates of the Transform Accounting Documents service candidate is valid.
Step 3: Derive an initial service interface
Analyze the proposed service operation candidates and follow the steps below to define the first cut of the service interface:
Note that as generic units of processing logic, application services will be used by different types of business services. Each business service will be processing a different type of business document (invoice, purchase order, claim, etc.). Therefore, application services need to be designed in such a manner that they can process multiple document types. Depending on the nature of the information being processed, there are several design options.
RailCo begins by deriving the two operation names shown in Figure 15.13.
Figure 15.13. The first cut of the Transform Accounting Documents Service.
It then moves on to define the types construct of its service definition to formalize the message structures. First, it tackles the request and response messages for the TransformToNative operation.
Example 15.9. The XSD schema types required by the TransformToNative operation.
Upon assessing the message requirements of the TransformToXML operation, RailCo discovers that the required types are identical. Streamlining the schema design with shared complex types is considered, but RailCo decides against it. It chooses instead to create a second set of elements with redundant complex types because it would like the freedom to change these types independently in the future.
Example 15.10. The additional tpes for use by the TransformToXML operation.
Next, the initial version of the abstract service definition for the RailCo Transform Account Documents Service is completed by providing the remaining message and portType constructs.
Example 15.11. The message and portType constructs of the abstract Transform Accounting Documents Service definition.
RailCo is mandated by TLS to build services that are WS-I Basic Profile 1.1 compliant. This requires RailCo to use the WSDL 1.1 specification to build service interfaces. This suits RailCo fine, as none of its middleware supports newer versions of WSDL anyway.
Step 4: Apply principles of service-orientation
This step highlights the four principles of service-orientation we listed in Chapter 8, as being those that are not intrinsically provided by the Web services platform (service reusability, service autonomy, service statelessness, and service discoverability).
Reuse was discussed in the service modeling process and is addressed directly in Step 5, where we look at making our application service as useful to potential service requestors as possible. However, the existing operation candidates also should be reviewed to ensure they are designed to be generic and reusable.
Autonomy is of primary concern when designing application services. We must ensure that the underlying application logic responsible for executing the service operations does not impose dependencies on the service, or itself have dependencies. This is where the information we gathered in Step 2 of the service-oriented analysis process provides us with a starting point to investigate the nature of the application logic each service operation needs to invoke. Step 6 provides an analysis that covers this and other technology-related issues.
Statelessness also may be more difficult to achieve with application services. Because they are required to interface with a variety of different application platforms, these services are subject to highly unpredictable implementation environments. Sooner or later, application services are bound to encounter challenges that impose unreasonable or inconsistent performance requirements (outdated legacy systems are known for this). Therefore, the best way to promote a stateless application service design is to carry out as much up-front analysis as possible. Knowing in advance what the performance demands will be will allow you to investigate alternatives before you commit to a particular design.
As with entity-centric services, discoverability can be an important part of evolving the application services layer. To guarantee that this design does not overlap with the logic already provided by other application services, a discoverability mechanism is useful. This becomes more of an infrastructure requirement that can be planned as part of an SOA implementation. However, the Document services with metadata guideline still applies, as application services should be supplemented with as much metadata as possible.
The Transform Accounting Documents Service undergoes a review to ensure that it is properly incorporating service-orientation principles.
First, the reuse potential of its two operations is assessed:
After some discussion around whether these two operations should be combined into one generic Transform operation, it is decided to leave them as they are. The descriptive nature of the operations is preferred, and RailCo would like the option of evolving each operation separately in the future.
Next, the issues of autonomy and statelessness are discussed. Autonomy is not a problem, given that the logic required to carry out its transformation functions is contained within the service's underlying application logic. In other words, there are no dependencies on other programs. Statelessness also is not considered to be a concern because this service will be responsible for its own processing.
Finally, it is agreed that to better accommodate future discoverability, the service definition be outfitted with additional metadata documentation.
Example 15.12. The Transform Accounting Documents portType construct with supplemental metadata documentation.
<documentation> Retrieves an XML document and converts it into the native accounting document format. documentation> <documentation> Retrieves a native accounting document and converts it into an XML document. documentation>
Step 5: Standardize and refine the service interface
Even though the role and purpose of application services differs from other types of services, it is important that they be designed in the same fundamental manner. We accomplish this by ensuring that the resulting application service WSDL definition is based on the same standards and conventions used by others.
Following is a list of recommended actions you can take to achieve a standardized and streamlined service design:
Some changes are made to the service as a result of the considerations taken into account as part of this step. Upon reviewing naming standards, it is determined that the chosen names for the operations are in line with existing conventions. The name given to the service itself, however, is not. Therefore, the service is renamed from "Transform Accounting Documents" to "Transform Accounting."
Then the need to support a primary contemporary SOA characteristic is raised. RailCo established early on that it wants to be able to expand its SOA in the future with a minimal amount of redevelopment effort. Therefore, the characteristic of extensibility should be built into each of its services to whatever extent feasible.
Upon a review of the service design, increased extensibility is achieved with the following adjustments:
Example 15.13. The revised types construct.
These modifications position the service as a transformation utility that initially supports only transformation functions for use with the accounting system but that can be extended to offer additional transformation-related features.
Step 6: Outfit the service candidate with speculative features
If you are interested in delivering highly reusable application services, you can take this opportunity to add features to this service design. These new features can affect existing operations or can result in the addition of new operations. For application services, speculative extensions revolve around the type of processing that falls within the service context.
Of course, before actually adding speculative extensions to the application service, you should repeat Step 1 to confirm that no part of these new operations already exists within other services. Additionally, when adding new extensions, Steps 2 through 5 also need to be repeated to ensure that they are properly standardized and designed in alignment with the portion of the service interface we've created so far.
Although RailCo would like to build highly reusable application services, it cannot afford to do so at this time. Having designed the Transform Service to be sufficiently generic and reusable so that it can be used by both the Invoice Submission and Order Fulfillment Processes, RailCo is confident that its immediate requirements are being fulfilled. Further, because extensibility is being emphasized as well, RailCo feels that it can continue to evolve this service if future reusability opportunities present themselves.
Step 7: Identify technical constraints
At this point we have created an ideal service interface in a bit of a vacuum. Unlike our business services, application services need to take low-level, real-world considerations into account.
We now need to study and document the processing demands of each service operation more closely. First, for each operation, write a list of the processing functions required for the operation to carry out its processing. Then, for every entry on this list, find out exactly how the processing of the function will need to be executed in the existing technical environment.
The types of details we are specifically looking for are:
After characteristics of individual processing functions have been gathered, they need to be viewed collectively. For example, individual response times need to be added to calculate the overall estimated execution time of the operation. The result of this study is typically a series of constraints and limitations imposed by the technical environment onto our service interface. In some cases, the restrictions will be so severe that an operation may need to be significantly augmented.
Note that when transitioning an organization toward an enterprise-wide SOA, there is a tendency to want to service-orient everything. However, it is important to identify which processing requirements cannot be fulfilled by the Web services technology set. It may not make sense to expose some portions of underlying legacy application logic as Web services. Either way, it is worth reminding ourselves that even though this book focuses on the creation of services as Web services, SOA is in fact an implementation-neutral architectural model and service-orientation is an implementation-neutral design paradigm. Existing forms of application logic not made available through Web services can still be modeled as services. This is of particular relevance to application services, where exposing application logic through a Web service may not always be the right decision. For example, façade components are often created to encapsulate functionality from different sources and to then expose a distinct context representing a set of reusable functions. This results in a legitimate service, which may, in the future, still be expressed via a Web service.
The one issue that comes up when assessing the technical constraints of the Transform Service is a potential performance bottleneck. A review of existing metrics suggests that the conversion process can be time consuming when processing invoice or purchase order documents with more than twenty line items. Because the service will be performing its own processing, it is expected that an instance of the service will be tied up for the duration of the transformation process. Therefore, larger documents will likely introduce some noticeable lag time.
This revelation runs contrary to our original assumption that maintaining statelessness would not be a problem. However, because RailCo is not expecting a high usage volume and because the transformation period has no real bearing on the efficiency of its internal invoice and PO processing processes, it is decided that the service design will not be altered.
Case Study (Process Results)
Following is the final version of the Transform Service definition, incorporating the changes to element names and all of the previous revisions.
Example 15.14. The final abstract service definition.
ForAccountingImport retrieves an XML document and converts it into the native accounting document format. ForAccountingExport retrieves a native accounting document and converts it into an XML document. ...
This process has produced an abstract definition only. The full WSDL document, including sample concrete definition details, is available for download at www.serviceoriented.ws.
SUMMARY OF KEY POINTS