InfoQ has a discussion thread summarizing the reactions to the announcement of the SpringSource Application Plaform. Michael Burke asked a great question on that thread which can be paraphrased as “forgetting the hype surrounding OSGi, what benefits can I expect to see if I port an application currently packaged as an EAR to OSGi bundles?”.
I started answering this question on the InfoQ thread, but my answer was growing too long for a comment so instead I’ll address it here.
The question is a good one. The main difference you will see in an OSGi-based application versus a traditional JEE EAR-based application is improved modularity. So the question becomes, does this improved modularity bring me any benefits, and if so what are they? The book “Design Rules, The Power of Modularity” gives a very thorough treatment of the question. It’s great background but I get that feeling that Michael may be looking for something a little less theoretical than what you’ll find in that book! Let’s break the modularity benefits down into two categories: benefits you should expect to experience during development time, and benefits you should expect to experience during runtime:
Development time benefits.
- Strict development time (and runtime) enforcement of module boundaries
- A service-oriented architecture that works for managing service dependencies between modules.
- Better ability to structure development teams the way you want to
- Faster team-based development
- Faster testing cycles
- Support for versioning as part of dependency management
- Less road-blocks
OSGi has mechanisms to ensure that module boundaries are respected by the development teams. Using OSGi the types exported by a module are explicitly declared (if it’s not exported, it’s not visible), and the dependencies of a module are also explicitly declared (this can include version-range compatibility information). This means that when using the development tools the team can’t code-complete themselves into a violation of module boundaries, and at runtime the OSGi service platform will prevent one module from seeing the private internals of another module. So your application architecture stays clean and protected during the development cycle rather than slowly breaking down through (often inadvertent) unwanted coupling.
The dependencies between modules aren’t restricted to just types of course - modules also need to make available services (think Spring beans) for other modules to use, and may depend on services (think Spring beans again) provided by other modules. Instead of your application essentially being one large application context, think of it as a set of peer contexts interacting via a local service registry. Spring beans (components) are private to the module unless explicitly exported. Bean references across modules are managed by the runtime. Once again this means that developers working on a module are free to make whatever internal changes they like, so long as the external contract (beans published, types exported) stays constant. When using Spring Dynamic Modules both the imported and exported types and the imported and exported services of a module are specified declaratively (the former in the OSGi manifest, the latter in a Spring configuration file).
“Organization follows architecture”. It’s easy to assign a team to work on a given module or modules. It’s much harder to ask a team to implement a function that crosscuts many modules. So what naturally tends to happen is that your technical architecture (how you divide a system into modules) dictates your organizational structure - i.e. how effectively you are able to partition the work among teams and individuals. Greater flexibility in modularizing your application means greater flexibility in structuring your team. Sometimes you see the reverse: “architecture follows organization”. This tends to happen when there are sets of co-located individuals forming a distributed team. In order to make sensible work assignments you want to align modules with locations if you can. So if you can’t move the people, then to a reasonable extent your architecture is dictacted by your organization. The more flexibility you have in module decomposition, the greater the chance you can find something that works well for you.
When modules have clear boundaries - well defined external interfaces, well-specified dependencies, and protected internals, it’s much easier for teams working on those modules to develop in parallel without accidentally treading on each others toes. Well-specified interactions are easier to stub and mock, and easier to integrate. This should lead to more productive teams and faster development cycles.
When you’re testing in-container the SpringSource Application Platform development tools for Eclipse take advantage of the OSGi Service Platform’s ability to dynamically update a given module in a running system. An incremental builder associated with your project automatically udates the module in a running platform instance whenever you make a change. This can be any change - code or otherwise. So if for example you are working in the web tier, continuously interacting with your web application and testing as you go, the web module will be refreshed on each change - and you won’t need to wait for your persistence layer to be reinitialised each time. The smart management of service references between bundles (modules) that Spring Dynamic Modules provides ensures that all inter-module links are repaired after refresh. This development experience is quite addictive: you have been warned!
When a module specifies its dependencies, it can give a version range (which can be restricted to just a single version) for the versions of the dependency that it is compatible with. OSGi allows for multiple versions of a Java package to be present at runtime simultaneously. This allows scenarios whereby the team working on module A need version x of some library, and the team working on module B need version y of some library (and x and y are incompatible). So long as modules A and B never need to exchange types from that library between them this will work without any difficulties. If modules A and B do need to exchange types between them then the OSGi Service Platform will detect this potential conflict at deployment time rather than at runtime (assuming the manifests for the two modules have been correctly generated).
Unlike my other points (which relate to OSGi in general) this point is particular to the SpringSource Application Platform. We’re confident that if you start developing Spring and OSGi-based enterprise applications on the SpringSource Application Platform you’ll encounter a lot less road-blocks along the way with enterprise libraries not working the way you would expect them to under OSGi than you would if you tried to develop directly to an OSGi Service Platform (even though the programming and deployment model is the same).
The runtime benefits stem from the fact that modules in OSGi are not just development time constructs. They very much exist at runtime, have their own lifecycle, and can be inspected in a running system.
- Full information about the installed modules and their wiring is available at runtime - a level of insight operations teams have never had before.
- Isolate changes
- Share dependencies
- Use just the server facilities you need
You can list all of the installed bundles and their versions, see the packages they are exporting and importing, and also see the services they are exporing and importing (together with the identity of the bundles providing those services and packages). Previously operations teams have had little or not visibility into a running application beyond the JEE deployment unit level, OSGi changes all of that. (Aside, the SpringSource Application Management Suite provides even more insights, but that’s another topic).
Since it is possible to install, uninstall, update and refresh modules independently, you can reduce the risk of making changes to production applications by scoping the change to a smaller unit (the bundle). The rest of the application (the other bundles) can remain unchanged. Yes you may well have a long change control process meaning that in real terms making the change is no quicker, but at least you can now make the change with greater certainty that you have not introduced any other unintended differences.
OSGi’s support for versioning makes it practical to install trusted versions of enterprise libraries once in the platform and then share them between applications.
Since the server platform itself is built on top of OSGi in a modular manner you can configure the platform to have only the services you need to support the application or applications currently running on it.
Non-OSGi related benefits
What if you don’t care two hoots about OSGi??? Does the SpringSource Application Platform bring any benefits then?
Yes it does.
I like to think of the SpringSource Application Platform this way:
Firstly it’s a server. A lightweight configurable server with a focus on serviceability (see Rob’s original post on the platform). It has useful features such as per-application separated tracing and log files, deadlock detection, failure detection and dump-processing, smart thread pools and work stealing etc.. It’s a great place to deploy web applications for these reasons.
Secondly, it’s a server that understands Spring-based applications. Spring is integrated out of the box, and the deployer can simplify the process of packaging and deploying Spring-based apps - for example by doing away with the need for a boiler-plate web.xml file just to configure Spring’s DispatcherServlet.
Thirdly, and only thirdly, it supports OSGi for end-user applications, giving the benefits I already outlined above.