Dependency Injection pattern in Service Component Architecture
It shouldn’t come as a surprise that the key underlying pattern supporting the recently published Service Component Architecture (SCA) specifications is nothing but – Dependency Injection (DI)! Here I am attempting to explain why … Enabling reuse of components and making them available to a broad set of users is the fundamental goal of any component framework. So what are the key requirements in this regard and what does dependency injection have to do with it? First of all, the components themselves must exist and it is no longer considered fashionable to design monolithic applications with a specific UI attached with them. Now since this topic has beaten to death (and rightly so) by the supporters of Service Oriented Architecture (SOA), I am not going to talk about this aspect any more here. Relieved, hmm! It is also well understood that the design of the interface for accessing a component plays a large role in making the component functionality available to a broad set of consumers residing in possibly heterogeneous platform/language environments. The principles of SOA such as loose coupling via document oriented interactions, asynchronous interactions, etc, come handy in this regard and I do not intend to indulge on that topic here either. The aspect of component framework that is explored in this blog is – empowering the user of a component to effect specific behavior on the component without requiring changes to the component implementation. Of course, effecting specific behavior here does not mean changing the core functionality offered by the component in a wholesale manner but rather it means customizing the component functionality to suit the user specific needs. Perhaps an example might help to clarify this requirement and there are in fact many business as well as technical scenarios where this requirement is clearly felt. For a business example, consider that a global travel services company has purchased a software component that allows its worldwide user community to make hotel reservations. The travel services company works with the local hotel consortia in each country for making hotel reservations. For some good reasons, the IT department of this company has decided to deploy dedicated instances of the component for managing hotel reservations in each country. Now the component in each deployed instance must be configured to interact with the country specific hotel consortia and must handle the reservations in the local currency. So while the hotel reservations component must provide a clear interface for invoking the actual hotel reservation functionality, it must also allow the deployer of the component to configure the component to work with the local currency and to use the services offered by the local hotel consortia. So the actual component interface must include not just entry points (for invoking hotel reservation functionality) but also — settable properties (for using local currency) and settable external services (for using local hotel consortia services). Similarly, a technical example of the user requirement to effect specific component behavior is – the developer of a component may want to use dummy services for testing the component functionality. As is apparent from both the business as well as technical examples, it is necessary that the component should allow injection of the services it depends upon. The aspect of settable component properties is also crucial to effecting specific behavior, however I am not focusing on that aspect here. Now let us look at how SCA tackles this problem of empowering users of a component to effect customized behavior from the component. For those who are wondering what SCA is — SCA is a new component model based on SOA developed in collaboration by SAP, IBM, BEA, Oracle and bunch of other vendors. Cover pages on SCA provides a good overview of the SCA specifications and the dynamics around it. SCA defines a schema for defining the various aspects of the component including the component interface exposed to its users as well as the interfaces of the services the component depends upon and the settable component properties. Taking our business example of hotel reservations component – the ComponentType element in the SCA Assembly Model would look like:
Now some of you may be wondering what the big deal is with SCA using the dependency injection pattern. Dependency injection has been around since quite some time now. There is a lot of content explaining DI, its roots in earlier Inversion of Control (IoC) pattern, etc, on the web. Many proprietary, standards-based as well as open source component frameworks have been using the DI pattern explicitly in their architecture. For example, an EJB that invokes other EJBs in its implementation uses ejb-ref and ejb-local-ref elements in the deployment descriptor for encoding these dependencies. The deployer of the EJB can inject dependencies by appropriately setting the values for these references. Similarly, the Servlet 2.5 specification uses resource-ref, resource-env-ref and message-destination-ref elements to allow injection of resources such as datasources, JMS administered objects, etc. So in essence, as far as the use of the DI pattern itself is concerned, yes, I would agree that SCA perhaps is no different! However there are certain aspects of SCA that combine the benefits of DI and SCA in a unique manner including: – SCA embodies the DI pattern and provides a foundation for combining different existing component frameworks into one overall SCA framework. SCA allows a variety of resources such as Web services, EIS functions, remote EJBs to be modeled as remote components, and can generally be used without regard to the underlying implementation technology or of the transport. The DI feature of SCA is therefore neutral to the component implementation technology unlike the DI feature in the existing component frameworks out there today. – Via its assembly model comprising of elements with increasing composition granularity such as components, modules and subsystems, SCA provides multiples points of injecting dependencies that are suitable to different roles involved in developing, deploying and administering components. – I am not a big fan of this feature yet, but SCA seems to build upon DI to enable additional semantics such as publish/subscribe or aggregation of external services that a component depends upon. For example, a component reference that identifies a point of dependency injection of services with multiplicity of 0..n can be used to model a publish/subscribe semantics whereby many injected services can receive the same message from the component but the component can operate without any injected services as such. Similarly, a multiplicity of 1..n for dependency injection can be used by the component to invoke multiple external services and aggregate the results from all the services. Note that in both the cases of multiplicities, it is the user of the component implementation who gets to decide what the dependent services are and the component developer is only tasked with ensuring that all the points of dependency injections are properly exposed . In essence, use of DI in SCA seems right-on-spot and further enhances the benefits of DI by allowing injection of services from heterogeneous component environments, by allowing multiple points of service injection in a well specified manner and also by building upon the DI pattern to create additional semantics.