Web Services in a Small to Medium-Sized Enterprise (SME)
Let's look at how you would use Web Services in a typical project where you're building an application that combines new functionality with existing components and services within your organization. In this case, you may want to use Web Services as the distribution mechanism between new clients and servers. You may also want to wrap existing functionality or data sources using Web Services so that you have a consistent distribution mechanism.
I'm not going to get into precisely how you access your new or existing data and business functionality. Let's consider instead how you'll plug things together. It may be rather obvious, but every system that exposes a Web Service will need to be running a web server of some form. Underneath this web server, most people will use either a Java servlet-based Web Service engine, such as Apache Axis, or will use Microsoft's .NET. (Okay, this is a broad generalizationI appeal to developers of Web Services in Perl and Python not to think too badly of me.) Given this assumption, you'll create either Java servlets (and associated classes) or ASP.NET classes in C# or VB.NET. In either case, the two platforms offer various connectivity options to access your existing data or functionality. If you're creating or consuming Web Services based on such data or functionality, you'll need a description of the Web Service and a way to transport data back and forth.
Now to a degree, connecting to a Web Service is not an issue. Everyone is agreed on Simple Object Access Protocol (SOAP) as the way of connecting. Despite this, there have been certain issues when using SOAP as a transport, particularly between different platforms and/or toolkits. As with any specification-based standard, there have been issues around interpretation and implementation. However, the principal issue has concerned the encoding of the SOAP message and its layout. Sections 5 and 7 of the SOAP specification describe how to encode and lay out a message. However, this predates work on the XML Schema specification. More recent products have introduced encoding based on the use of XML Schemas (called "literal" types), which is not interoperable with the SOAP encoding rules. Also, if you decide to use "document-style" layout rather than "RPC-style" layout, this will also cause interoperability problems. Although recent products and toolkits should work with most variations on this SOAP encoding/RPC versus document/literal style, this has been a common source of interoperability issues.
Moving on to the description of your Web Services, Web Services Description Language (WSDL) provides a commonly agreed way of describing Web Services. Although WSDL is flexible and reasonably comprehensive, some degree of thought needs to go into its use. In a typical analysis and development cycle, you'll create a Unified Modeling Language (UML) model containing your business classes and then map this onto "real" components on your chosen platform. Part of this process will involve deciding how components should be distributed physically, which leads to the introduction of Web Service boundaries.
If you come from the world of distributed objects, especially from a Java background, you may be used to passing objects by value (that is, the object is serialized down the wire and a copy appears in the remote process). However, this really relies on having the same environment at both the sending and receiving ends. Given that Web Services are meant to be interoperable across platforms and languages, this setup is certainly not guaranteed. Hence, when defining parameters and return values, WSDL only describes data structures and their relationships, not functionality. As an example, if you define a method in an ASP.NET Web Service that passes an object parameter, only the publicly accessible data members of this object will form part of the WSDL description. Effectively, any functionality that the object has is "stripped off" at the Web Service boundary. The same applies to private, internal data held by the object. If you want to retrieve "live" objects from your interaction with Web Services, it's your responsibility to intercept the data defined in the WSDL and "reconstitute" the object as it arrives. Although toolkits provide hooks for such functionality, this adds to the code that you would need to write, compared to doing the same thing in RMI or using binary encoded .NET remoting. You might also need to change the design of your object so that more of its internal state is publicly visible, so that this state is passed across the Web Service boundary. This may cause problems where encapsulation is important.
There are some other impedance issues when mapping your business components onto Web Services. Take the example of exposing multiple business components using .NET Web Services. You could have a single Web Service that exposes all of the methods in these components. However, you'll lose the grouping and cohesion gained from putting the functionality into separate components. Alternatively, you could go for one Web Service per component. If your components are sufficiently granular, this works quite well. However, consider the case of consuming multiple services under Visual Studio .NET. When you add a Web Reference, it imports the WSDL for the service and generates a client-side proxy for you to use. Each proxy is generated in its own .NET namespace (like a Java package). If your client uses two related Web Services that expose the same complex datatype (derived from the same object or struct parameter), this appears in the client under the same name in two different .NET packages, and the compiler won't treat them as equivalent. You can get around this problem by manually generating your client-side proxies, or by changing the WSDL for the two services to use shared types. However, each of these approaches adds a manual step to the development process. This is not intended to be a particular criticism of Visual Studio, simply a reflection that a lot of effort is required to make the use of Web Services "seamless."
Think about other things that you may require in a typical application. Any exceptions that your methods raise must be mapped to SOAP faults and then "reconstituted" at the client. If your application requires security between the client and the Web Service, you can use Secure Sockets Layer (SSL) to provide point-to-point authentication and privacy with varying levels of additional work. However, support for other things that you may want to use, such as distributed transactions across Web Services, is not presentunless you want to do it yourself.
This leads to a question about what we're trying to achieve. If we really want our Web Services to be platform-independent and reusable, we must sacrifice some level of comfort. This is the sort of lesson that CORBA should have taught us.