Chapter 6. Service consumer patterns
The previous chapter focused on the basics of service interactions—the message exchange patterns. This chapter also focuses on the interactions of services with their consumers but it covers a wider range, looking at patterns that support these interactions. Like chapter 5, this chapter’s focus is on the service consumer in the SOA components model (see figure 6.1).
Service consumers aren’t necessarily other services (though that’s common as well). One important type of nonservices that are service consumers are UIs. It’s important to talk about connecting UIs to services, because SOA, in itself, doesn’t really pay attention to the needs of UIs. SOA separates business concepts into different services, whereas users working with a UI want a unified view.
Reservations can be explicit (the scenario in figure 6.2 would also have a Reserve item action) or implicit. In the case of an implicit order, the service decides internally what will be considered a “reserving” message and what will be considered a “confirming” message. An action like placing an order might trigger the internal reservation and an action like making a payment could serve as the confirming message. When the reservation is implicit, the service consumer implementation will probably be simpler because the consumer designers are likely to treat reservation expirations as simple failures, whereas when the reservation is explicit, the service consumer is expected to have specific behavior to handle the reservation state (reserved, expired, overbooked, and so on).
It’s easy to understand the Reservation pattern being applied to services that handle real-life reservations as part of their business logic, such as ordering services for hotels or airlines. But reservations are also suitable for a lot of other scenarios where services are asked to provide guarantees on internal resources. In one system I worked on (discussed at length in chapter 9), we used reservations as part of the saga initiation process. The system used the Service Instance pattern (discussed in chapter 3) where some services needed to be stateful. Naturally, services have limited capacity to handle consumers—an instance can handle a limited number of concurrent sagas or events. Because of the statefulness of instances, the services needed to know which service instances were allocated to a saga. As long as a single service instance initiates sagas, everything is fine. But when two or more services (or instances) initiate sagas concurrently, they may both try to allocate the same service instance to their particular sagas (and given enough load and time, they will).
The system had a few other services in addition to the COP, including the UNPV service. The UNPV service was responsible for anything related to the UNPV itself, such as setting its course and turning it around. The UNPV service had several UI screens that allowed the user to manage and monitor these functions. Another responsibility of the UNPV service was to send the UNPV’s location to the COP (locations are the COP’s responsibility, remember?), so in the COP UI, one of the icons on the map is the UNPV.
The Composite Front End pattern is a service consumer pattern, so the proxy will utilize the various service interaction patterns, like Saga, Request/Reply, and so on (see chapter 5). It can also benefit from the service composition patterns, such as Orchestration and Service Bus (see chapter 7).
In the discussion of the Composite Front End pattern in the previous section, we looked at building a UI for SOA in a manner that’s akin to a green-field project, creating a new UI, from scratch to consume newly developed services. In contrast, the Client/Server/Service pattern helps solve the problem of UI and SOA integration when you already have a working system in place and you want to evolve it to SOA.
The Client/Server/Service pattern works well with the various service integration patterns (discussed in chapter 7) and it utilizes the message exchange patterns (see chapter 5). It can also make use of the Identity Provider pattern (see chapter 4) for passing the security context between the existing system and the new services.
Naturally, a lot of other patterns are relevant to service consumers. UIs have patterns like Model-View-Controller (and related ones, like MVVM, MVP, and so on), but most of these patterns aren’t directly related to SOA. One notable pattern (or concept) that I recommend exploring is Command Query Responsibility Segregation (see the further reading section).
In chapter 5, we looked at several patterns related to how services and service consumers communicate. In this chapter, we looked at how consumers integrate with services. The next chapter talks about service integration patterns to complete the picture of how you can tie services together to deliver complete solutions.
Martin Fowler, “CQRS” (Command Query Responsibility Segregation), http://martinfowler.com/bliki/CQRS.html. CQRS is an interesting pattern that focuses on information flow from the UI to services and back to the UI. It can be used as a complementary approach for client-service communications.
OpenSocial, http://docs.opensocial.org/display/OS/Home. OpenSocial is an open standard pioneered by Google that can be used to implement the Composite Front End pattern with web technologies.