This article will discuss two fundamentally different approaches to development of the enterprise Web Services (WS). Both approaches use SOAP over HTTP protocols and define endpoints and operations via a Web Services Definition Language (WSDL) file. The two methods are contract-first and contract-last. Even though the technology stack can be similar for both methods, they differ in both the methodology and the implementations. The examples will be in Java and cover the most common toolkits such as Spring-WS and Apache Axis, and some automation tools, like JBuilder 2007.
In the contract-first web service, the “contract” (a WSDL definition of operations and endpoints and XML schema of the messages) is created first, without actually writing any service code. In the contract-last web service, existing logic is “exposed” as a web service and the contract is created at the very end. I will present both advantages and disadvantages of each implementation and play the role of devil’s advocate when analyzing them.
A Brief History of SOAP
The SOAP acronym originally meant Simple Object Access Protocol, but later it was dropped and now SOAP is an official name by itself. Coincidently, SOAP can also mean SOA Protocol or Service Oriented Architecture Protocol, but no one currently is using this definition. The SOAP-based WS are the bread and butter of some enterprise developers; since the original introduction of the standard, it has changed a lot. The current SOAP specification (XML) defines the envelope structure, encoding rules, and conventions for representing requests and responses.
Modern web-service tools and standards evolved from the initial RPC (Remote Procedure Call) methodology. The idea was that the automated systems will be invoking methods on the remote servers and the communications will be done via the SOAP protocol.* Because web services were also a way to make different legacy systems (developed on diverse platforms and in various languages) talk to each other, initial WS development often exposed existing APIs to be consumed by clients. The communication “contract” that the WS clients needed to uphold was created last, because the business logic code was already written.
* Semantically speaking, modern web services are RPC- and SOAP-based at the same time, but the distinction is Document vs. RPC style. There is also another protocol called REST, but it’s beyond the scope of this article.
Tools automating the creation of enterprise web services appeared as early as 2004; I covered one way to expose existing Java code in one of my previous articles, “Developing Web Services with Borland JBuilder Enterprise and BEA WebLogic Server” (01/2006). These tools provided auto-generation of the server code including WSDL and under the hood, compliance with the SOAP and the xml schema—a sort of easy way to SOAP-ify the code. Similarly, tools automating client binding and stubs generation also emerged and eliminated the need for developers to concentrate on the protocols and the low-level plumbing of the services.
The Flow of SOAP Requests and Responses
To better understand both types of the web service methodologies, the communication flow needs to be discussed first. Because the web services XML standards are platform and language indifferent, the translation of parameter values (passed in the request and response) into the host system technology needs to take place on both the client and the server. This includes any complex types, such as custom objects.
For example, if the server is based on C# and the client on Java, C# structures are mapped into XML, which is passed to the client. Subsequently, the client needs to un-wrap XML into the Java object model. This process is called XML marshaling and un-marshaling (also knows as the plumbing of the web services). See Figure 1.
Figure 1: The diagram of XML request marshaling
For this process to work coherently, the set of objects corresponding to the XML elements on both server and clients needs to exist, and the communication XML (payload) needs to be generated dynamically and match the agreed schema format.
In many cases, the client-object model can be automatically generated with the use of the object-XML mapping tool or an IDE. Most popular object-XML mapping (OXM) toolkits for Java are:
- Castor
- Jaxb
- Jibx
- XMLBeans
- XStream
These tools can create the XML from the object model, which then can be used by the web service toolkit such as Apache Axis, Xfire, or Spring-WS. (See the References section for more details.)
What Is a Web-Service Contract?
Even though there is no official definition of the web-service contract, the contract is assumed to be the WSDL file. The WSDL describes all operations that the service provides, locations of the end-points (where the service can be invoked), and simple and complex elements that can be passed in requests and responses.
Looking at the contract from the RPC methodology standpoint, the specification of only WS operations (and their signatures) is the contract. Analogous to the Java Interfaces, which define class methods and their signatures and establish object-oriented contract, the web service definition of operations is the contract between the server and the client. Accordingly, as long as the names of the methods and parameters are immutable, the underlining implementation changes do not affect clients. For example, a WSDL can define operations such as “getBalance” or “updateBalance”.
Looking at the contract from the message (or document) standpoint, one also can define the contract in terms of the XML schema of the request and response messages. For example, assuming you are developing a service that returns chemical compositions of household products queried by name, you can define a request and response structure in XML, create a validation schema, and support only those elements by the service. The web service server’s logic will decide what to do based on the message, and not on the operation invoked.*
* The operation name also can be imbedded in the request message, controlling what is executed on the server or a combination of the actual endpoint operation invoked. SOAP message contents [action] also can be used to define what is perfumed on the server.
For instance, a massage-based contract can look like this:
Request: <action>get</action><product>SOAP</product> Response: <product name="soap"> <ingredients> <item>fat</item> <item>lye</item> <item>perfume</item> <item>color</item> </ingredients> </product>
No other XML elements should be supported if both client and server adhere to the XSD schema based on this XML.
These two types of contracts are also are known as RPC and Document-based contracts. The RPC style WS contract is assumed to be based on operations, and a Document style WS contact is in terms of XML/XSD schema. For instance, Java Spring-WS encourages document-based web services, and then can auto-generate the WSDL from the schema.
Another distinction between RPC and Documents WS is that RPC can accept SOAP messages with multiple XML root nodes, whereas the Document-style service requires only one root node element.
Devil’s Advocate of the Contract-First
So, why would anyone create a contract (WSDL) of the service before writing the service itself? Why would someone create an XML schema of the SOAP message, which evolves understanding of XML/XSD schema elements, SOAP definitions and structures, and tools that support them, such as XMLSpy? Why would anyone invest time in learning OXM toolkits?
It seems that a contract-first web-service is a lot more work upfront than the contract-last WS. First, the schema (or XML) files need to be created, and then the object model needs to be written along with any business logic. The setup and configuration needs to take place between the web-service toolkit and the application, often also through the XML config files. Some recent tools, such as Spring-WS, help a little with the setup, but still requires quite a bit of work.
For instance, after you create the XML schema (.xsd files), you can “wire” the Spring DynamicWsdl11Definition bean to auto-generate WSDL based on the schema.
<bean id="echo" class="org.springframework.ws.wsdl.wsdl11. DynamicWsdl11Definition" <property name="builder"> <bean class="org.springframework.ws.wsdl.wsdl11.builder. XsdBasedSoap11Wsdl4jDefinitionBuilder"> <property name="schema" value="/WEB-INF/echo.xsd"/> <property name="portTypeName" value="Echo"/> <property name="locationUri" value="http://localhost:9090/echoservice/"/> </bean> </property> </bean>
Note: In case you are wondering how it knows what operations to create, this bean is looking for any element whose name ends with “Request” and “Response” and turns those into operations. For a step-by-step guide on how to create Spring-WS, see Chapter 9 in Spring 2 in Action from Manning or the References section.
In Apache Axis, for example, the service needs to be configured in the .wsdd file.
<service name="Product" provider="java:MSG" style="message" xmlns:ns="http://www.xyz.com/ServiceSchema/v1"> <parameter name="className" value="com.xyz.common.ws.EchoWebServiceImpl" /> <parameter name="allowedMethods" value="*" /> <wsdlFile>wsdl/Product.wsdl</wsdlFile> <operation name="echoProduct" qname="ns:ProductRequest" /> </service>
The maintenance also needs to be considered because a lot more components are involved with the creation of the service. Any future schema changes will require regeneration of the object model (and vice versa), as well as possibly regeneration of the client’s bindings.
Devil’s Advocate of the Contract-Last Web Services
Why would anyone create the WSDL at the very end of the development process? Why anyone would couple the server and a client to the existing business logic by SOAP-ifyng it? One can argue that with contract-last approach, clients will be tightly coupled to the server’s internal APIs (or the server to the specific technology stack), in which case any future changes would break the contract and affect all clients, or require service to be versioned.
With this approach, the contract is not a first-class citizen, and is treated as a side effect of the client and server bindings. This also means that the developers have no control over the structure of the WSDL and the SOAP payload, including the XML being transmitted. For instance, it’s not possible to specify what parameters should be attributes of the message elements, and which should be values. Because the XML payload can not be controlled, there is a possibility of traffic overhead, because auto-generation often creates more XML then needed.
For example, instead of auto-generated:
<person>
<first_name>Vlad</first_name>
<last_name>Kofman</last_name>
</person>
Developers can fine-tune it to: <person fn=”Vlad” ln=”Kofman”>. This results in faster transfer times for the large payloads.
Contract-First vs. Contract-Last
In the aforementioned discussion, I have concentrated on the drawbacks of the two approaches. Now, look at the benefits as well.
In the case of contract first, clients are decoupled from any logic on the server. The logic can be revised on the server without affecting the clients. Teams can work simultaneously on the server and the client implementations as long as they agree on the contract, which is the first thing that is created anyway. More granular control exists over what is in the request and response messages and WSDL structure. OXM libraries can be replaced/changed based on the implementation, and potentially even web service toolkits also can be changed.
In the case of contract-last, developers don’t need to learn SOAP or any XML-related technologies, and services are created quickly by “exposing” internal APIs with automated tools, such as JBuilder or .NET Studio. The learning curve is smaller compared with the contract-first, and so could be the development time.
Example of XSD Schema for SOAP message
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sp="http://www.xyz.com/ServiceSchema/v1" xmlns:ns1="http://www.xyz.com/ServiceSchema/v1" targetNamespace="http://www..xyz.com/ServiceSchema/v1" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xsd:include schemaLocation="Master.xsd"/> <xsd:complexType name="ProductSchemaType"> <xsd:complexContent> <xsd:sequence> <xsd:element name="DataArea" type="ns:ProductDataAreaType"/> </xsd:sequence> </xsd:complexContent> </xsd:complexType> <xsd:complexType name="ProductDataAreaType"> <xsd:sequence> <xsd:element ref="ns:Action"/> <xsd:element ref="ns:Product" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:element name="Product" type="ns:ProductSchemaType"/> </xsd:schema>
Conclusion
In this article, I have shown you different ways to implement SOAP web services. The methods I have described involve either RPC or Document approaches, and can significantly differ in ROI and development and maintenance efforts. It will be up to the readers to decide which methodology is right for his project and what technologies they need to use.
It will be interesting to see what new improvements will appear in the area of the enterprise web services next and how current standards will evolve.
Special thanks go to Man Chan for his terrific insights into the Document-based web services!
References
- Wikipedia: http://en.wikipedia.org/wiki/Web_services, http://en.wikipedia.org/wiki/SOAP
- http://webservices.xml.com/pub/a/ws/2001/04/04/ webservices/index.html
- Xfire: http://xfire.codehaus.org/
- Apache Axis: http://ws.apache.org/axis/
- Spring WS: http://static.springframework.org/spring-ws/site/, http://springtips.blogspot.com/2007/07/ step-by-step-spring-ws.html
- Spring 2 in Action, Manning ISBN: 1-933988-13-4b: http://www.manning.com/walls3/
- Castor: http://www.castor.org/
- XML Beans: http://xmlbeans.apache.org/
- Jaxb: http://java.sun.com/developer/technicalArticles/ WebServices/jaxb/
- Jibx: http://jibx.sourceforge.net/
- Xstream: http://xstream.codehaus.org/
About the Author
Vlad Kofman works on enterprise-scale projects for the major Wall Street firms. He has also worked on defense contracts for the U.S. government. His main interests are object-oriented programming methodologies, UI, and design patterns.