Menu

Enterprise SOA the Apache Way

March 7, 2007

Kyle Gabhart

Apache.org has been buzzing with Service-Oriented Architecture (SOA) and Web Services activity for the last several years. If you browse to the Apache Web Services Project, you'll find a list of more than 20 SOA and Web Services projects with another handful currently housed in the Apache incubator. Within this broad range of frameworks and tools, a few enterprise SOA technology stacks have emerged. In this article, we will explore one of the Apache SOA stacks, Synapse + Axis2 + Tomcat. I'll begin by briefly describing each of these components and what they bring to the table. Then I'll define a simple use case to demonstrate how these components collaborate to fulfill basic service-oriented requirements. Finally, we'll explore the importance of being able to configure services within a SOA.

Component Overview

This article explores the service-oriented combination of three Apache projects:

  • Synapse (mediation framework): A service mediation framework capable of filtering, routing, and transforming messages based on a flexible XML configuration.
  • Axis2 (web service engine): This second-generation service engine hosts SOAP 1.1/1.2 and REST services, as well as provides support for a host of other WS-* standards.
  • Tomcat (web server): The standard Java enterprise web server.

For an enterprise-grade deployment, a full installation of Synapse and Axis2 onto a Java Enterprise server is preferred. For testing and demonstration purposes (such as this article), you can actually download Synapse only (the binary distribution ships with an embedded Axis2 engine and HTTP server).

Sample Business Case: Defect Tracking

To explore these technologies within a real-world context, we'll use a simple but non-trivial scenario of a defect tracking system for a software engineering team. A service-oriented defect tracking system would interface with the software development IDE, quality assurance/testing software, customer feedback system, and historical data stored in a data warehouse (see Figure 1). Defect data could be aggregated, indexed, and cross-referenced using various categories and relevant metadata. Reports could then be generated to identify defect trends, underperforming team members, and SDLC phases where the highest frequency and severity of defects occur.

Figure 1
Figure 1 (Click to enlarge.)

Within the larger context of this service-oriented defect tracking system, we will focus on the specific use case of collecting defect data from the customer feedback system and defining some simple rules for escalating certain "high-priority" messages. Figure 2 provides a closer look at how the Synapse mediation framework might help fulfill this use case by re-routing messages to alternate service endpoints based on configurable criteria.

Figure 2
Figure 2 (Click to enlarge.)

Client and Service Code

Developing the client and service code is pretty basic stuff -- Web Services 101. Axis2 offers several approaches for generating client stubs from a WSDL document (Axis ADB, XMLBeans, JiBX, and more), and several approaches to creating a Web Service (from scratch, from POJO, from WSDL). For this simple scenario, we will actually deploy four services:

  • CustomerFeedbackProcessor: This service exposes a single operation: feedback( String accountId, String message ) and responds with "Thank you for your feedback."
  • HighPriorityProcessor: This service exposes a single operation: feedback( String accountId, String message ) and responds with "Thank you for your valuable feedback. We will respond to your request in one business day."
  • MediumPriorityProcessor: This service exposes a single operation: feedback( String accountId, String message ) and responds with "Thank you for your feedback. We will respond to your request in three business days."
  • LowPriorityProcessor: This service exposes a single operation: feedback( String accountId, String message ) and responds with "Thanks. We'll get around to you eventually."

The client stub code will be generated using a Web Services Description Language (WSDL) file from the first, more generic, service. Later we will configure business rules within Synapse that will re-reroute certain messages to one of the more specific services with a priority rating. There are numerous tutorials and examples available to learn more about deploying services with Axis2 (including the sample code that comes with Axis2). Consequently, we will put the basic SOAP/WSDL issues aside and focus on the meatier issues of SOA agility and flexibility that are made possible by Synapse.

Configuring the SOA

One of the key elements of a true Service-Oriented Architecture is the ability to configure services to adapt to business requirements. In traditional software development, business logic changes require code updates, followed by compilation and a complete testing cycle. SOA offers agility by allowing businesses to configure services as needed to meet changing business requirements. The Synapse mediation framework delivers on SOA's promise of agility by defining a robust configuration capability backed by the Synapse Configuration Language, allowing developers to configure message processing via one or more mediators.

At a high level, a Synapse configuration file is structured as follows:

<synapse>

   registrydef

   <definitions>

     (sequencedef | endpointdef | literalpropertydef)+

   <definitions>?

   <proxies>

     proxyservice+

   </proxies>?

   <rules [key="string"]>

     mediator*

   </rules>

 </synapse>

The message-processing capabilities of Synapse are pretty extensive. Through the definition of processing rules -- backed by mediators -- a range of message routing, secure handling, transport switching, data transformation, and a whole lot more can be accomplished. For more details on the message-brokering capabilities of Synapse, check out the Synapse Samples on Apache's site.

Configuring the Use Case

Getting back to our defect tracking scenario, one could imagine a whole host of message-brokering use cases. For the purposes of demonstration, consider the following case: customers experiencing our product provide feedback that we want to incorporate into the defect tracking system. In our simple scenario, there is an existing customer feedback system capable of communicating with WS-* endpoints. Synapse provides a value-add in that it is capable of brokering messages (transport switching, routing, proxying, etc.). In this use case, we will define some simple rules within the Synapse configuration to dictate feedback escalation criteria and route high-priority messages to the appropriate destination. Specifically, we want to sort feedback based on the size and/or significance of the account. In this scenario we will assume an account ID pattern of the format XXXXXX-XX, in which the final two characters indicate the type of account (enterprise, professional, personal, etc.). This message sorting is illustrated in Figure 3.

Figure 3
Figure 3 (Click to enlarge.)

To configure this message-sorting strategy, we start by defining service endpoints in the Synapse configuration file (synapse.xml). Services defined via external endpoints can be reused across different branches of the decision tree.

<synapse xmlns="http://ws.apache.org/ns/synapse">

 <definitions>

 <!-- define endpoints -->

   <endpoint name="genericFeedback" address="http://localhost:9000/axis2/services/CustomerFeedbackProcessor"/>

   <endpoint name="lowPriority" address="http://localhost:9000/axis2/services/LowPriority_FeedbackProcessor"/>

   <endpoint name="mediumPriority" address="http://localhost:9000/axis2/services/MediumPriority_FeedbackProcessor"/>

   <endpoint name="highPriority" address="http://localhost:9000/axis2/services/HighPriority_FeedbackProcessor"/>

 </definitions>

 ...

Next we will define the message-processing rules. We will start by specifying conditional routing for requests by placing a switch statement inside the in tag, and we will allow responses to pass through untouched by placing an empty send tag within the out tag.

<rules>

        <!-- Log all messages passing through -->

        <log level="full"/>        

        

        <in>

            <switch source="//n0:feedback/n0:accountId" xmlns:n0="http://services.apachesoa.gabhart.com/xsd">

                <case regex=".*-99">

                    <send>

                        <endpoint ref="highPriority"/>

                    </send>

                </case>

                <case regex=".*-35">

                    <send>

                        <endpoint ref="mediumPriority"/>

                    </send>

                  </case>

                <default>    

                    <send>

                        <endpoint ref="lowPriority"/>

                    </send>

                </default>

            </switch>

        </in>

      <out>

        <send/>

      </out>

 </rules>

</synapse>

That's a lot to digest all at once, so let's take a closer look at this Synapse configuration. We start by declaring full logging (a good idea for development work). Next we declare message-processing rules for requests (i.e., messages that come "in"). We want to process message requests and filter them as high, medium, and low priority based on the account ID matching a particular pattern. To do that, we start by narrowing the scope of the switch statement through its source attribute. We supply that attribute with an XPATH query, //n0:feedback/n0:accountId, to zero in on the accountId value. Within the body of the statement, we branch off based on the accountId matching one of the designated regular expressions. Finally, within each case block, we invoke one of the previously defined endpoints.

Although the original service endpoint, named feedback, was used by the client, the business rules configured within Synapse will cause messages to be sorted and re-routed at runtime to alternate service endpoints. In this particular example, messages that are brokered through Synapse will never reach the original service endpoint (notice that the default endpoint has been designated as the low-priority service). Instead, the only way to reach the original service endpoint would be to talk with the axis2 web application directly, rather than communicating with the Synapse server (by default, Synapse operates on port 8080 while axis2 operates on port 9000).

Apache-Powered SOA

Service-Oriented Architecture promises agility and alignment of business and technical objectives. The combination of three Apache projects -- Axis2, Synapse, and Tomcat -- results in a pretty compelling Apache SOA stack. In our use case, we explored how this SOA stack would enable a business to configure message routing and escalation business rules to prioritize customer feedback originating from key accounts. It is easy to see how these rules could be reconfigured and even expanded to adapt to changing business goals. Changes in business strategy might easily lead to a change in how customer feedback is processed and incorporated into bug fixes, R&D, and even Customer Relationship Management (CRM). This same agility and flexibility can then be realized throughout the enterprise as more and more of the business's Information Systems technology is assimilated into an overarching service-oriented enterprise. Keep a close eye on the momentum that SOA is gaining throughout the Information Technology industry and what it may mean for your enterprise. Keep track especially of the open systems arena, where players like Apache are gaining ground with technologies such as Axis2, Synapse, and the rest of the Apache Web Services Project.