The problem with discussing the tenets of SOA in the strictest sense is that levels of compliance may vary based on the scenario. On the one hand, SOA is a big business buzzword tossed into conversations at board meetings, at executive briefings, and in hallway conversations between C-level executives. At this level, however, SOA really refers to connecting disparate systems across application, department, corporate, and even industry boundaries. This is what I call Big SOA. The other use for the term SOA is to describe how applications are designed as chunks of business functionality that are isolated behind explicit service boundaries. I call this Little SOA.
Big SOA is an Enterprise Architect (EA) activity. The EA cares about connecting heterogeneous systems that may originate from different vendors. For example, you can connect HR, Payroll, CRM, and possibly other applications across the organization to achieve a business goal. In some cases, it is even useful to control messaging between systems and track usage with an Enterprise Service Bus (ESB)--a term that also means many things, but in this case I refer to the ability to pass all messaging through a common service for tracking and routing purposes. In short, Big SOA is about connecting entire systems through their respective service boundaries.
Little SOA is a Software Architect (SA) activity. The SA cares about designing a system that may encapsulate functionality behind service boundaries to achieve reuse, maintainability, version control, visibility, orchestration, and other benefits. These services may never see the light of day outside the application to which they belong. On the other hand, some internal application services may also be exposed for public access to facilitate communications and interoperability with other applications. If applications don’t expose public services, it becomes a challenge to connect applications.
Little SOA enables Big SOA.
The distinction between approaches in SOA is important because of the level of strictness in applying SOA tenets. For example, it isn’t always possible to completely isolate business components, business entities, and data tiers between services in the same system. Data is usually highly relational within a system, such that different areas of business functionality share common data stores and entities. Figure 1-10 illustrates an application with three services: Accounts, Customers, and Reporting.
Accounts Service and Customers Service each expose operations to their respective types, but Accounts data is related to Customers in the system; thus, there isn’t a pure separation between the tables required to support each service. At the same time, both Accounts and Customers also provide access to business functionality and CRUD operations (Create, Read, Update, Delete) that can be considered completely independent of one another—thus the need for separate services. The Reporting Service, in fact, needs to access all tables to aggregate results.
Figure 1-10.Sharing data between services is sometimes unavoidable
Service Oriented Architecture
In a pure SOA play, each service would have sole ownership over its data tables, and services would have to communicate with one anotehr to access those tables, even for reporting. This can create unnecessary overhead and complexity within a system. Instead, Figure 1-10 illustrates a way to support sharing relational tables behind the service boundary by coordinating relational results at the database, possibly via stored procedures. This way, the vertical assemblies associated with a service are completely owned by the service, and if a particular service, such as Reporting, requires access to multiple relational tables that are also accessed by other services, the data access layer coordinates this result for the service. While serialized business entities may be shared between services, business and data access components are not. Services can always call other downstream services to share functionality when service isolation is clear cut and the overhead of the service call makes sense--for example when services provides core functions such as document generation or messaging.
The point is that not all four tenets of SOA can be followed to the letter when designing services within an application. When application services are exposed to Big SOA in most cases the entire application is deployed with the service, thus the shared entities and data stores are implied parts of the atomic service.
In this book, I'll be focusing on how you deploy WCF services as part of an enterprise application. In other words, Little SOA.
WCF services are the new distributed boundary in an enterprise application--with an emphasis on SOA. In the past, you had to deliberate between Enterprise Services, .NET Remoting, or ASMX to distribute and reuse functionality, WCF provides you with a single programming model to satisfy the needs of any equivalent distribution scenario. With WCF, you can cross process, machine, and corporate boundaries over any number of protocols; you can expose interoperable web services; and you can support queued messaging scenarios. I'll take you through a few examples where WCF is deployed in lieu of earlier technologies.
Figure 1-11 illustrates an intranet scenario where a WCF service is invoked within an application domain over TCP protocol. In this scenario, the client needed to reach remote services and authenticate with Windows credentials, and didn't require interoperability. As such, the service is accessible over TCP using binary serialization for better performance, and supports traditional Windows authentication using NTLM or Kerberos. In the past, this may have been achieved using Enterprise Services (or possibly .NET Remoting although security features are not built-in).
Figure 1-12 illustrates an Internet scenario where multiple web services are exposed--one supporting legacy protocols (Basic Profile), another supporting more recent protocols (WS*). With WCF, a single service can be defined and exposed over multiple endpoints to support this scenario.
Figure 1-11. Deploying WCF services on the intranet
Figure 1-12. WCF services exposed on the Internet
In Figure 1-13 you can see WCF implemented at several tiers—behind the firewall to support an ASP.NET application, and outside the firewall for smart client applications. Again, the same service can be exposed over multiple protocols without duplicating effort or switching technologies.
Figure 1-13. WCF services deployed at several tiers over multiple protocols
Throughout this book, I’ll be exploring these and other scenarios while discussing specific features of the WCF platform.
At its core, WCF is a development platform for service-oriented applications. As I mentioned earlier, WCF is part of the .NET Framework 3.0, which comprises a set of new assemblies that rely on the .NET Framework 2.0. System.ServiceModel is the assembly that contains core functionality for WCF, which explains why the WCF platform is often called the service model. Any project that exposes or consumes WCF services must reference the System.ServiceModel assembly, and possibly other supporting assemblies.
Before you can begin to do interesting things with the service model, it helps to understand the core features that make it possible to create, host, and consume services. In this section, I will briefly summarize some of the concepts that will be elaborated on in this chapter, to help you on your way.
Message Serialization
All enterprise applications at some point must make remote calls across process and machine boundaries. This is handled by sending messages between applications. The format of the message is what determines an applications ability to communicate with other applications. Remote procedure calls (RPC) and XML messaging formats are two common ways for applications to communicate.
RPC calls are used to communicate with objects (components) across boundaries--for example, calls from a client application to a remote object living in another process. RPC calls are marshaled by converting them to messages and sending them over a transport protocol such as TCP. When the message reaches its destination, it is un-marshaled and converted into a stack frame that invokes the object. This is all usually handled transparently through a client proxy and stub at the destination. Both proxy and stub know how to construct and deconstruct messages. This process is known as serialization and deserialization.
Figure 1-14 illustrates the serialization and deserialization process (often just called serialization) from a high level. As I mentioned, the transport carries a message according to the agreed-upon format of both the client and remote application. As far as the client is concerned, it is usually working with a proxy that looks like the remote object. When a method is invoked at the client, the proxy invokes underlying plumbing of the technology (for example, Enterprise Services or .NET Remoting) to serialize the outgoing message. The remote application usually listens for messages on a particular port, and as they arrive, deserializes those messages (using the same technology) to build a stack frame and invoke the appropriate method on the remote object. The method return is likewise serialized by the underlying plumbing and returned to the client, at which time the plumbing deserializes the message and constructs a stack frame for the response. RPC communication like this comes in many flavors, and each flavor is generally not compatible with another--that's why RPC is not interoperable.
Figure 1-14. RPC serialization and deserialization
To achieve interoperability, systems rely on a standard format for messages understood by both ends of the communication. Applications still exchange messages, but they are formatted in XML according to known protocols. The technology used to support this is traditionally associated with web services such as ASMX, WSE, or WCF. As Figure 1-15 illustrates, the serialization process is consistent with RPC, the key difference being the underlying plumbing, the format of the message, and the target object, which is usually a web service. The other difference is in the lifetime of the service. While remote objects are frequently kept alive for the duration of a client session, web services are typically constructed anew for each call.
Figure 1-15.Web service serialization and deserialization
WCF can be used to achieve both RPC-style messaging and web service messaging. In both cases, the type that ultimately processes messages is a service type, but its lifetime can be controlled to behave like traditional client-server components or like web services without the notion of a session. The service model handles all serialization activities based on configuration settings.
WCF applications expose functionality through services. A service is a Common Language Runtime (CLR) type that encapsulates business functionality and exposes a set of methods that can be accessed by remote clients. In order for a regular CLR type to be considered a service it must implement a service contract.
A service contract is defined by applying theServiceContractAttributeto a class or interface. When applied to a class, the class becomes a service type. When applied to an interface, any class that implements the interface becomes a service type. In either case, methods exposed by the class or interface must be decorated with theOperationContractAttributeto be considered part of the service contract. Methods with this attribute are considered service operations.
A service type must be hosted before clients can invoke service operations.
Hosting
Service functionality is made available at runtime through a host process--any managed process will do the trick. Many hosting options are available for WCF services, including:
Self-hosting This includes console applications, Windows Forms or WPF applications, or Windows services.
Internet Information Services (IIS) Services can be hosted alongside other ASP.NET applications, for example.
Windows Activation Service (WAS) This is similar to IIS hosting but is only available to IIS 7.0.
Each hosting environment has its benefits and appropriate uses, which will be discussed in Chapter4.
Although a host process is important, ultimately it is the service model that knows how to process messages targeting a service. For this aServiceHostinstance is associated with each service type.ServiceHostis part of the service model and is responsible for initializing communication channels that receive messages to a service. Basically, to host any service, you construct aServiceHost, provide it with a service type to activate for incoming messages, provide it with one or more addresses where the service can be located along with the service contract supported by each address, and provide it with the supported communication protocols.
You can think of theServiceHost as responsible for managing the lifetime of the communication channels for the service.
Endpoints
When the ServiceHost opens a communication channel for a service, it must expose at least one endpoint for the service so that clients can invoke operations. In fact, endpoints are the key to invoking service functionality. An endpoint describes where services can be reached, how they can be reached, and what operations can be reached. Thus, endpoints have three key parts:
Address Refers to the URI where messages can be sent to the service.
Binding Bindings indicate the protocols supported when messages are sent to a particular address.
Contract Each address supports a specific set of operations, as described by a service contract.
TheServiceHost is provided with a list of endpoints before the communication channel is opened. These endpoints each receive messages for their associated operations over the specified protocols.
Please check back next week for the continuation of this article.