|
|||||
| Blog | / | OSGi Alliance Blog: Spring and OSGi: Jumping Beans | |||
|
Spring and OSGi: Jumping Beans2007-01-09
This week there was an interesting discussion going on in the Spring-OSGi mailing list. In this mailing list, a number of people discuss their fantastic work marrying Spring with OSGi. This project has created a lot of interest; Even JBoss seems to have been inspired by this work and is moving to OSGi, putting the majority of application servers on firm OSGi footing!
Anyway, the discussion was about the dynamics of services. Hal Hildebrand (Oracle) started a discussion about the cardinality of services. This opened a floodgate of mails that I tried to ignore due to after-vacation overload. However, Costin Leau (Interface21) asked me to jump in so I was forced to analyze the thread. I got myself a cup of strong coffee and wrestled through the mail flood. The issue was revolving around the cardinality. The cardinality indicates how many services of a given type you require and how many of them you are interested in. The OSGi-Spring specification treats OSGi services similar to beans. This allows you to inject beans into other beans, following the concept of inversion of control and dependency injection. For unary services like an OSGi Log Service this works fairly well. However, the devil is usually in the details, so let us take a closer look. The key differences between beans and OSGi services are:
Most Java programmers will recognize this model. Many developers use the Class.forName to find a class and then use Class.newInstance to create an instance for extendibility. Virtually any (non-OSGi) Java application uses this model to extend or configure itself this way. Notice that there is a strong 1:1 relation between the Class and the instance in this model. In contrast, OSGi services are more like jumping beans; they have a life of their own. When beans start jumping all over the place (spring, as they say in Dutch!) then most programmers will be shocked to the bones. Fortunately, once they grasp the power of a dynamic model they usually fall in love it. However, this model implies that the IoC is not limited to configuration and activation, it means that the IoC container must handle life cycle issues during the active life of the application. Obviously, many Spring applications will not be able to handle these dynamics, or even want to handle these dynamics. The Spring-OSGi group therefore chose to hide these dynamics behind a proxy. Instead of directly injecting the service object, a proxy to this object is injected into the configured bean. This gives us a choice to control the behavior later when the underlying service arrives or goes away. However, it also gives us a choice of optionality and multiplicity. The proxy mechanism of Spring gives us full control, the tricky thing is to define what to do with this control. These are exactly the issue we spent a lot of time discussing during the development of declarative services, inspired by Richard Hall’s service binder and designed by BJ Hargrave (IBM). Declarative services do not use proxies but instead bind and unbind services to the application using injection. After lots of deep discussions we came up with the following policies for binding and unbinding services to the application. Mandatory/Optional A mandatory service means that the service must be present before the application is activated and the application will be deactivated when there is no such service available anymore. An optional service does not influence the life cycle of the application. The declarative runtime can unbind a service and bind another service at will when the service is optional. Normal Spring beans are similar to mandatory services. Mandatory is normally indicated in the cardinality as 1.., and optionality as 0.. . Unary/Multiple The application can be interested in a single service (unary) or it can track a set of services. The set may require some explanation. The dynamic service registry enables some very interesting software patterns. For example, one bundle manages a Bluetooth hardware interface. The whiteboard pattern shows that the simplest solution for this bundle is to register a service per discovered device, and unregister this service when the device is no longer reachable. Other bundles can then just track these services from the registry and use when required. This pattern nicely decouples the lifecycle of the bundles that participate, making clients easier to develop. The idea that you can add and remove beans dynamically from a configured bean is new to Spring but it follows naturally from the OSGi model. This cardinality is indicated with ..1 for unary and ..n for multiple. Static/Dynamic Once an application is activated because its dependencies are met, the lifecycle state of a referred service can change. The traditional choice is to deactivate the application and restart it when the conditions are right again; this is called the static policy. Some people are repelled by this idea but in an OSGi system this is quite natural, and well under the control of the operator. An update can cause a ripple effect of many bundles restarting but well designed systems should be robust enough to handle this. Hmm, let me rephrase, if your system can’t handle this model, it will fail in the end anyway. In certain cases, it would do no harm to replace a service on the fly. If an application uses the Log Service, it is likely not interested which Log Service it uses. If this service is unregistered, it could easily be unbound and then bound again with a new instance. Most stateless services can be replaced this way. Binding and unbinding during the active life of the application is called the dynamic model. Usage Let us now take a look at the possible combinations and see what they mean, and where they are applicable.
Spring The Spring-OSGi spec can copy the concepts from the declarative services because they have exactly the same issues. The discussion in the mail group got confused because the interaction between the policies for proxying (static/dynamic) were confused with optionality. Spring adds the concept of proxies. It is my advice that the rules are as close as possible to the declarative services model which means that in most cases the application must participate in the binding and unbinding. It is tempting to automatically replace the service reference in a proxy but most of the time services are stateful and then it is easy to confuse them. Associating proxying with dynamic does not make sense because normally the application must do some action during binding. Maybe Spring needs an extra policy to indicate that replacing the service in the proxy is allowed or not, for example statefull and stateless. Then again, I am starting to have serious doubts how useful proxy rebinds are in reality. Anyway, this year will be an interesting year for declarative services. It is clear from this issue that declarative services did a good job in this area but the possibilities of Spring will likely encompass all the important features of declarative and then add more. I am not sure if it is a good idea to have declarative services compete with Spring. My personal preference is that the Spring-OSGi specification becomes an official OSGi R5 spec … Let me know if you have ideas how we should handle this. Peter Kriens Comments |
||||
Sounds like they are quite close to the concept of
Agents (a good thing).
Paul , Technology in Plain English