Applying SOA to an Existing Application
"Service-Oriented Architecture" could probably win a competition for buzzword of the year, as I'm sure we all know. Like any good buzzword, exactly what it means depends a bit on whom you ask, but if you take the most widely accepted definition, it describes an application architecture with many advantages.
SOA (if you will forgive the use of a TLA – three-letter acronym) doesn't just happen, however. It must be carefully architected into the design and structure of an application. This of course, is much easier when you are starting from scratch - you can orient the design of your application around services from the get-go, and apply modern techniques to the entire system. Unfortunately, the real world has a distinct shortage of "scratch", and many more man-hours are put into maintenance, upgrade, and modification of existing systems than are put into the development of new ones. If you are lucky enough to only work on new system development, then this article is not for you.
If, on the other hand, you share in the pain of upgrading, maintaining and enhancing existing applications, the read on. Having gone down the road of applying SOA to existing apps a few times, I'll try to pass on where some of the potholes are, so you can avoid joining me at the bottom of them.
More than just refactoring, some redesign
Many existing applications were designed before SOA was even a gleam in the IT communities' eye, and are not structured in a way that makes SOA easy to retrofit. The "services" in non-SOA apps tend to be coupled together more tightly, and often times also coupled to their corresponding user interfaces. For example, you may be trying to take an existing webapp that uses JSP and servlets as it's front-end, and upgrade it to include web services to allow access via SOAP from a .NET application (or any other SOAP-enabled UI).
A necessary step in SOAP-enabling such an application is to determine the degree of coupling between existing "services" (even though the app may not be structured in a way that makes identifying the services easy), and the degree of coupling to the existing user interface, then reducing those couplings to a manageable level - while at the same time trying not to break the application's connection to it's existing user interface. Often this will not be possible: better to organize the application around services, the re-connect the user interface pages to the new services.
This involves a de-construction of the application, and some understanding of how it's functionality is structured. You begin by attempting to identify "candidate services", that is, functional areas that might make "good" services. The topic of what makes a "good" service is a bit beyond this article, but is addressed in many different places on the web and in books and magazines.
As each candidate service emerges, an iterative process can be used: look at a servlet and corresponding JSP page(s), see what it does. List each of the operations provided, organizing them into the candidate services. Repeat for each page (or each page that's necessary, as often this is a task that's taken on in pieces).
Now you have a list of candidate services, and under each service a list of the operations (methods, messages, depending on your flavor of terminology) that can be part of that service. Now is the time to re-organize these operations more logically: for example, if you have a number of operations relating to customers, you might want to cluster them together into a "customer service". This is of course very simplistic - again the exact techniques for determining which operations go with which services are well documented elsewhere. The specifics here really depend on both the nature of your specific application and the way you want to organize services for consumption by the new user interface, which becomes the client to those services.
Once you've completed this phase, you need to actually start un-tangling the services from each other. In an existing webapp, you'll probably find it necessary to make an attempt at making each service more 'stateless' than it is now, as many JSP/Servlet webapps make heavy use of context to store information between requests, in many cases making subsequent requests vary depending on something "left over" from earlier requests. This is problematic in a SOA environment in many cases, as you cannot necessarily depend on this same sequence of events when the new clients access the services you are creating, so this "state-fulness" should be reduced as much as possible. It is often advantageous from a performance point of view as well, as many objects can be made thread-safe once they are stateless. Getting there, however, is often a - how to put it - a "significant challenge".
Any time you have to work on an existing application, there is the potential for company or development-team politics to get involved in the process. Often there will be constraints on either the technologies that can be used (e.g. Java, .NET, Windows, Unix, etc), or some "input" into the design process. Often times this "input" will be in the form of requirements to include certain operations in specific services - for example, the "create new customer" function might need to go in the "custom service", but a requirement is passed down to include it in the "invoice" process, because that is controller by a certain department.
These kinds of design influences can range from the merely annoying to the downright catastrophic, and it is important to determine the degree of latitude the design team has right up front, so the right choices can be made on technical merit, as opposed to political favor. Many an otherwise fine project has been derailed by having too many cooks into the broth, especially at the design level. Finding the Services
Often the amount of work necessary to properly apply service-oriented techniques to an application is badly underestimated: this too can turn into a political problem, as a team leader might have told management that it was a simple matter of "bolting on" service access, without taking into account any of the decoupling and other issues we've discussed above in creating his or her time estimates. Management typically has no sense of humor at all about such situations.
Of course, this kind of "political" issue can arise in any development project, but what often makes it harder when applying SOA techniques to an existing application is the lack of understanding of all that is involved in such a retrofit. With applications that are tightly integrated to a user interface, there is more to see - you can do things on a screen to see the code working as things get finished. With a SOA app, the user interface is decoupled frequently to greater degree, and may not even be developed at the same time or by the same people as the services - meaning all management get to see is a nice green light when a unit test passes, which is not as reassuring to them. As we explore further below, a lack of understanding of the complexities of SOA can also create difficulties in budgeting sufficient time.
The Hard Part
Because Service-Oriented Architecture is such a, shall we say "well used" term, many in the industry think they know what it means - in fact, they are sure they know what it means. Unfortunately, when it comes time to compare their understanding to that of others in their team discrepancies arise: many believe SOA simply means you can access an application via some kind of SOAP interface. This is a very superficial definition, but of course if it is sufficient for the project at hand, then well and good. Usually, however, applying SOA means properly structuring the application internally to make use of a service-oriented approach, thereby reaping all of the benefits of a proper treatment of SOA, as opposed to just bolting SOAP onto a monolithic application.
Again, a difference in the understanding of the term can lead to disagreement over the scope of the project - doing it right is very different from doing it quickly, especially with an existing application. Projects will sometimes appear that would actually be better served by a rewrite than a re-work. Convincing management, or, worse, the original developer of the existing application of this can sometimes be an uphill battle, however. An incremental approach is often better than a "rip out and replace" method in such circumstances, even if it takes longer.
Part of the benefit of a fully applied SOA architecture is the improved testability of the application - indeed, SOA apps lends themselves well to a test-first and/or test-driven approach to development. When retrofitting an existing application, however, the existing tests (if any), need to come along for the ride. Ideally, you'll be able to start with the tests for the new service classes, then work backwards to test and then upgrade/implement all of the supporting classes. For an existing application the orientation of testing sometimes has to change: the tests are no longer about whether the user interface does the correct thing at the correct time, but are more focused on whether the services all respond correctly to correct messages from their clients.
Existing teams are sometimes very familiar with user-level manual testing (e.g. someone sitting down and bashing away at the application like a user), but not as experienced in automated testing and unit testing, which are critical to true reliability of a SOA application. Special attention must be given to boundary conditions and error handling, as an entirely different team from the service-provider application often develops the client portion of a SOA application. It is essential to agree on a service contract as a critical part of the specification, and to make any changes clearly known to both teams as early as possible.
All in all, applying SOA to an application that already exists is generally harder than applying it to new development - although of course that takes some careful thought as well. It is important to manage expectations carefully, especially with the less technical part of the development team or company, so that they are expecting the hard work it takes to do SOA right.
With careful planning and some co-operation a SOA retrofit can be a success, just don't let anyone tell you it's "easy"!
About the Author
Michael Nash is the president of JGlobal Limited, a software development, consulting, training and support company specializing in open source Java technologies. He is also a core developer of the Keel meta-framework, the author of two books and a number of articles and papers about next-generation web-application development with Java, and a member of the JSR-127 (JavaServer Faces) Expert Group. He can be reached at firstname.lastname@example.org.