The Connector pattern is very simple in structure and builds on top of a common distributed object design. Most importantly, the pattern shows a solution to communicate between physical tiers, so there are two significant aspects to this pattern:
The component structure
The physical deployment
Figure 13-3 illustrates the component structure of the pattern implementation. The structure is similar in nature to what you would expect from most remote object implementations , such as Java's RMI.
Figure 13-3 contains a slightly misleading association between the ServiceImplementation instance and the ImplementationClassProxy instance. The true association is between the ServiceImplementation instance and the ImplementationClass interface. In reality, the service implementation does not know that it is using a proxy to the implementation class. At runtime, the service implementation retrieves the stub that then communicates between processes with the ImplementationClassImpl instance.
Also not evident in the figure is the deployment structure of the solution. Keep in mind that the ServiceImplementation instance and the ImplementationClassProxy instance reside in the Web tier , and the ImplementationClassImpl instance resides in the logic tier and is in a separate process from the Web tier, as shown in Figure 13-4.
In Figure 13-4, the ServiceImplementation instance and the ImplementationClassProxy instance reside in the Web tier. The service instance calls operations on the logicProxy instance instead of calling operations directly against the logic instance. The logicProxy instance serves as a connector to the Logic tier where the actual logic implementation resides.
Four components make up the Connector pattern. As previously mentioned, these four components mirror most remote object implementation structures:
ImplementationClass: This is an interface to help with implementation transparency. Both the ImplementationClassImpl and the ImplementationClassProxy instances implement this interface.
ImplementationClassImpl: This class contains the actual behavior of any service implementation. For example, if a stand-alone application needs to subscribe to a Web Service event generator, this class contains the code that interacts with the stand-alone application. In the case that you are moving logic implementation out of the Web tier, this class contains any business logic or logic that is unique to the implementation language, such as your JDO persistence mechanisms. This class implements the ImplementationClass interface.
ImplementationClassProxy: The ImplementationClassProxy component facilitates communication between the ServiceImplementation instance and the ImplementationClassImpl instance residing in a separate process. The ImplementationClassProxy instance implements the ImplementationClass interface. The ServiceImplementation instance should have little or no awareness of the fact that they are having a conversation with a service that does not reside within the same physical tier.
ServiceImplementation: The service implementation becomes a mere shell of what it was in previous chapters. The interesting logic and behaviors move out of the ServiceImplementation instance and into the ImplementationClassImpl instance that resides in the Logic tier. This leaves the ServiceImplementation instance as a mechanism to forward the Web Service requests to the ImplementationClassImpl instance that resides in a separate physical tier through the mechanism embodied in the ImplementationClassProxy instance. There are many ways to embody this practice besides RMI. Rather than building your own remote service implementations, you can use an Enterprise JavaBean (EJB) provider in Apache Axis to forward requests to an EJB that exists outside of your own process and takes the place of your ImplementationClassImpl instance. This type of implementation for Web Services will be common in practice.
Each of these components implements the same operations; however, the behavior of the operation is different on each class. The service implementation's operation generates a call to the implementation class stub. The stub communicates across processes with the concrete implementation class. Each operation can have similar signatures, but often the service implementation class will require a slightly different operation signature.
The collaborations between components are, essentially , a chain of operations that pivot around the implementation class and return to the caller. The collaborations are interesting, especially the details of what goes on between one operation and another and what processes in which each operation runs. Figure 13-5 illustrates the chain of operations typical in the sequence for interprocess communications.
Within the sequence, a client makes an operation call against a service implementation through a Web Service environment. This collaboration traverses a client's process, and the operation actually executes within the same process space as the Apache Axis implementation. This operation makes a call to the implementation class stub, which is a proxy. The proxy resides within the Apache Axis proxy space, but its target does not. The implementation class itself resides within the destination process, sometimes an application subscriber (other times this will be the Web Service's implementation).