» tagged pages
» logout
Spring
Return to Spring

Interface21 Team Blog

(or Cancel)

(Editing anonymously: to be credited for your changes, login or register a new account)

other page actions:

Tags Applied to this Topic

1 person has tagged this page:

Thursday, May 15, 2008

Why should I care about OSGi anyway?

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
  • 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.

  • A service-oriented architecture that works for managing service dependencies between modules.
  • 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).

  • Better ability to structure development teams the way you want to
  • "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.

  • Faster team-based development
  • 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.

  • Faster testing 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!

  • Support for versioning as part of dependency management
  • 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).

  • Less road-blocks
  • 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).

Runtime benefits

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.
  • 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).

  • Isolate changes
  • 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.

  • Share dependencies
  • 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.

  • Use just the server facilities you need
  • 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.

Friday, May 09, 2008

Portability, Fish and Chips

It's been great to hear so much discussion on the SpringSource Application Platform, online and on the floor here at JavaOne. One of the most insightful comments is from WebSphere transaction architect Ian Robinson:

Does any of this affect WebSphere? Well, nothing has changed in the core Spring framework. Regardless of what the future holds for the SpringSource Application Platform, the core Spring framework project remains complimentary to WebSphere. Like fish and chips.

Ian is exactly right. The SpringSource Application Platform is another choice for Spring deployment. Nothing has changed in the Spring Framework and Portfolio itself, which remains committed to portability. We look forward to continuing our work with folk like Ian to ensure the optimal experience in running Spring on WebSphere and every other popular platform.


A short blog today. I'm off to give my repeat presentation on Spring 2.5 New and Notable–which unfortunately clashs with Ben Alex's session on Addressing Tomorrow's Security Requirements in Enterprise Applications. When I finish presenting at 5, it will have been a long–but good–week at Moscone…

Update - May 14, 2007

Just noted that WebSphere Foundation Architect Alan Little has reiterated IBM's commitment to working with Spring and SpringSource, and recognized the value Spring provides to WebSphere customers:

SpringSource has brought forth some interesting technology and concepts in the past with the Spring Framework. It provided us the concept of Inversion of Control containers, and a programming and component model that allows for loosely coupled components to be wired together to build applications. This programming model enables more and better reuse of software components.

The concept of wiring applications together, and loose coupling are all things that people look to Spring to provide. We in WebSphere worked with SpringSource to help certify a level of Spring with the WebSphere Application Server, and will be doing more to ensure our customers use of the Spring Framework is a good one.

We look forward to continued cooperation.

Friday, May 09, 2008

Working with SpringSource Application Platform's provisioning repository

One of the main advantages of the SpringSource Application Platform is its ability to provision dependencies on an as-needed basis. The benefits of this are two-fold: it ensures that the Platform's memory footprint is as small as possible and it allows applications to be deployed without encapsulating all of their dependencies in a monolithic deployment unit, e.g. a WAR file. To take advantage of these capabilities you will require an understanding of the Platform's provisioning repository and this blog intends to provide just that.

Where is the provisioning repository and how does it work?

By default the Platform's provisioning repository can be found in the repository directory at the root of the installation:

Directory structure of the provisioning repository
As you can see, there are three main directories: bundles, installed and libraries. installed is for the Platform's internal use so we'll focus on the bundles and libraries directories here. Each contains a number of subdirectories to separate the different types of dependencies:

  • ext contains external dependencies that are provided with the Platform but are not part of the Platform itself.
  • subsystems contains all of the subsystems that comprise the Platform.
  • usr is initially empty and is intended to contain user-added dependencies, i.e. anything upon which your applications depend that is not already provided by the Platform.

The Platform searches the repository directory structure for both bundles and libraries during its initial startup. I'll talk about how this searching can be configured later on in this entry. As bundles and libraries are found within the repository, details of their symbolic names, exported packages etc. are added to an in-memory index of the repository. Upon completing the scan the in-memory indexes are cached to disk. Minimising the Platform's startup time was a priority for us during development. This caching allows the Platform to save some time during startup: it can skip the scan unless it detects that the contents of the repository have changed.

Runtime provisioning

In a plain OSGi environment a bundle's dependencies can only be satisfied by other bundles which have already been installed in the environment. For example, installing and starting a bundle that imports the org.apache.commons.dbcp package will fail if no bundle which exports that package has already been installed. This can be a real pain for users as they have to manually install all of a bundle's dependencies. Thankfully, the SpringSource Application Platform improves upon this significantly by dynamically installing dependencies on an as-needed basis.

When a deployed application is started by the Platform its bundles are installed into Equinox. The Platform then asks Equinox for a list of all of the bundles' unsatisfied dependencies and tries to satisfy them. Let's analyse this process by walking through a simple example scenario:

  1. A bundle which imports org.apache.commons.dbcp is installed by the Platform into Equinox.
  2. The Platform asks Equinox for the bundle's unsatisfied dependencies and is told that the import of org.apache.commons.dbcp cannot be satisfied.
  3. The Platform searches its index of the provisioning repository for a bundle which exports org.apache.commons.dbcp
  4. The Platform installs the bundle which exports org.apache.commons.dbcp into Equinox
  5. Having satisfied the original bundle's dependencies the Platform successfully starts the original bundle.

We hope that this will make our users' lives much easier: as long as your application's dependencies are available to the Platform you can simply deploy your application and go! There's no need to get your hands dirty with the time consuming process of manually installing all of your application's dependencies. One great thing about this process is that dependencies are only installed when they're needed. You can add as many bundles as you wish to the provisioning repository with almost no impact upon the Platform's memory footprint.

If the Platform's unable to satisfy a dependency from its repository a log message is generated that details the dependency that could not be satisfied. Armed with this information you can use the SpringSource Enterprise Bundle Repository to get hold of what you need. We'd like the repository to provide as complete a set of bundles as possible: if there's a dependency that you need and it's not available then please let us know.

Adding items to the provisioning repository

So you've downloaded a dependency or two and now you want to add them to the Platform. All you need to do is copy them to the appropriate directory in the repository. For example, a new bundle would typically be added to the repository/bundles/usr directory and a new library descriptor would typically be added to the repository/libraries/usr directory.

As described above, the Platform uses an in-memory index of its provisioning repository that's populated during startup. In addition to this, the Platform will also check that its view of the repository is up-to-date whenever an application is deployed. When you want to install an application with new dependencies simply copy the dependencies to the appropriate locations in the repository and then deploy your application. During its deployment processing, the Platform will notice that the repository has been updated and will refresh its view of it. This means that you don't need to spend time restarting the Platform every time you want to install an application with new dependencies.

Sharing the provisioning repository between installations

The locations where the Platform searches for items in the provisioning repository can be easily configured to suit your needs. For example, it's possible for multiple Platform instances to share some or all of a provisioning repository so you don't need to waste effort maintaining duplicate sets of bundles between Platform installations.

The locations which are scanned by the Platform when creating its provisioning repository can be configured in the config/platform.config file. The default configuration, which is used in the absence of any specific configuration, is:

"provisioning" : {
    "searchPaths": [
        "repository/bundles/subsystems/{name}/{bundle}.jar",
        "repository/bundles/ext/{bundle}",
        "repository/bundles/usr/{bundle}",
        "repository/libraries/ext/{library}",
        "repository/libraries/usr/{library}"
    ]
}

Any relative paths are interpreted by the Platform as being relative to its installation root, with absolute paths being supported too. The entries in the search paths within curly braces are simply wildcards, e.g. the subsystems search path repository/bundles/subsystems/{name}/{bundle}.jar will find any file with a name ending in .jar in any of the subsystems directory's immediate sub-directories.

Hopefully you can see that it's a trivial change to share some or all of a provisioning repository between Platforms. For example, to make the Platform search a directory named shared-bundles in the root of the filesystem as well as in its own subsystems and ext directories, all you need to do is add the following snippet of JSON (JavaScript Object Notation) to the platform.config file:

"provisioning" : {
    "searchPaths": [
        "repository/bundles/subsystems/{name}/{bundle}.jar",
        "repository/bundles/ext/{bundle}",
        "/shared-bundles/{bundle}",
        "repository/libraries/ext/{library}",
        "repository/libraries/usr/{library}"
    ]
}

By configuring two or more Platform installations with this configuration they can be made to share the bundles in /shared-bundles. This can easily be taken one step further by configuring all of the search paths to point to shared locations so you wouldn't need to manage a per-Platform provisioning repository at all.

What's next?

We're planning to make it simpler to run multiple instances of the Platform from the same set of binaries by providing some tooling or scripts. These will do most of the work for you, providing a sensible default configuration that you can then tweak to meet your specific needs.

We also intend to combine the power of the Platform's on-demand provisioning and the SpringSource Enterprise Bundle Repository by allowing the Platform to be configured to optionally search a remote repository when it's trying to satisfy a dependency. If a dependency is found in a remote repository the Platform will handle its download and installation automatically. Hopefully this'll make developers' lives a lot easier, especially in the initial stages of an application's development as new dependencies are being added on a regular basis.

We'd love to hear your suggestions as we work on the above-described enhancements and the Platform in general: please don't hesitate to comment on this blog entry, raise a JIRA, or post on our forums.

Thursday, May 08, 2008

SpringSource Application Platform Manifest Headers

The SpringSource Application Platform is constructed from OSGi bundles and supports applications which are also constructed from OSGi bundles. The Platform supports the standard features of OSGi, but it also supports some additional manifest headers. Several people have asked Why did SpringSource add proprietary headers? and What are the semantics of the new headers?, so this post explains the background motivation and the semantics of Import-Library and Import-Bundle.

Standard OSGi Bundle Support

The Platform is built on the OSGi R4.1 standard, or JSR 291 if you prefer, and uses Equinox as its OSGi implementation. The result is that you can develop standard OSGi bundles using the Platform's tooling and deploy those bundles on the Platform, as a number of users have been doing since the Platform's launch.

So OSGi savvy developers can use the Platform as a standard OSGi container and benefit from Platform features such as:

  • the ability to deploy bundles using the Admin Console or by dropping bundles in the Platform's pickup directory,
  • diagnostics such as resolution failure diagnosis, application specific trace, and automatic deadlock detection,
  • strong integration with Spring and Spring Dynamic Modules, for developers who want to use these frameworks, and
  • automatic provisioning of dependencies from a repository.

However, the Platform also aims to make it easy for enterprise application developers with little or no prior exposure to OSGi to benefit from OSGi, which places some extra requirements on the Platform.

Additional Requirements of Enterprise Applications

As Sam's recent blog on the Platform's deployment options explains, you can deploy existing monolithic WAR files on the Platform with no need to understand OSGi - the Platform takes care of everything for you. But to benefit from shared libraries, shared services and, ultimately, PAR file scoping, it is necessary to break monolithic WAR files into OSGi bundles. How hard can that be?

Well, some steps in the process are relatively easy, especially if good software engineering practices have been followed and the code has been organised into service, domain, and infrastructure components. These components can be converted into bundles and the dependencies between them expressed using standard OSGi Import-Package and Export-Package headers in META-INF/MANIFEST.MF.

A more difficult step is expressing dependencies on enterprise frameworks such as Spring and Hibernate. It is entirely possible to express these dependencies using standard OSGi Import-Package and Require-Bundle headers, and this is exactly what you should do if your aim is to create OSGi bundles which will run in other OSGi containers, but this approach has some hidden costs.

Firstly, the developer has to decide precisely which packages comprise a given framework. It isn't sufficient merely to import the packages the application code uses, as several enterprise frameworks weave further dependencies into the bytecode of the application when the application is loaded. The developer has to discover, probably by trial and error, which additional implementation packages to import to ensure correct behaviour of the woven application.

Then there is the chore of migrating from one version of a framework to the next where the precise set of packages comprising the framework has changed. The additional packages required for weaving are typically not defined by a public contract and so are subject to change.

Additionally, the resultant package imports don't properly capture the design intent, which makes maintaining or extending the application more difficult in the future.

We really don't want to impose these burdens on our users, so we created some additional SpringSource Application Platform specific manifest headers, Import-Library and Import-Bundle, as convenient ways of expressing dependencies on enterprise frameworks. As you'll see below, these headers are really just syntactic sugar which are expressed in terms of standard OSGi package imports.

Import-Library

The basic syntax is similar to that of other manifest headers:

    Import-Library: <librarySymbolicName>;version=<versionRange>

where <librarySymbolicName> is the symbolic name of the library and <versionRange> is a range of acceptable versions of the library using OSGi version range notation. A library definition specifies the library's symbolic name and version and these together uniquely identify the library to the Platform.

If you are unfamiliar with OSGi version range notation, by far the most commonly used forms are minimum version ranges such as 2, meaning version 2 or later, and half-open ranges such as [2.2.1,2.2.2), meaning any version between 2.2.1 inclusive and 2.2.2 exclusive. If version=<versionRange> is omitted, together with the semicolon delimiter of course, then the default range includes all versions.

For each library import, the Platform selects the library with the given symbolic name and the highest version in the given version range available in the Platform's repository. The Platform then replaces the library import with a set of package imports which match all the packages exported by the bundles of the library. The Platform detects the situation where a bundle imports two or more libraries which export a common package, issues an appropriate log message, and fails to install the importing bundle.

So, for example, the following header imports some version of the Spring Framework library between 2.5.4 inclusive and 2.5.5 exclusive:

    Import-Library: org.springframework.spring;version="[2.5.4,2.5.5)"

Optional Library Import

You can indicate that a library import is optional using the following syntax. Note the special separator := which indicates a directive that modifies the semantics of the manifest header, as opposed to the separator = which indicates a matching attribute, like version.

    Import-Library: <librarySymbolicName>;version=<versionRange>;resolution:=optional

If resolution is not specified, or is specified as mandatory, the bundle containing the import library header will fail to install if there is no library with the given symbolic name and a version in the given range. But if resolution:=optional is specified, the library import will be ignored if no suitable library is available.

So, for example, the following header imports some version of the Spring Framework library from 2.5 onwards, but is ignored if no suitable library is available:

    Import-Library: org.springframework.spring;version="2.5";resolution:=optional

Importing More than One Library

If you need to import more than one library, then specify a comma-separated list of library imports in a single Import-Library manifest header as in the following example:

    Import-Library: org.foo.p;version="[1,2)",org.bar.q;version="[2,3)"

Import-Bundle

Import-Bundle is a further convenience for cases where a library would consist of only a single bundle and a library definition is inconvenient to create. The syntax is very similar to that of Import-Library except that it refers to a bundle's symbolic name and version instead of those of a library.

As you would expect, for each imported bundle, the Platform selects the bundle with the given symbolic name and the highest version in the given version range available in the Platform's repository. The Platform then replaces the bundle import with a set of package imports matching the packages exported by the bundle.

So, for example, the following header imports the Hibernate Object-Relational Mapper bundle:

    Import-Bundle: com.springsource.org.hibernate;version="[3.2.6,3.2.7)"

Why not Overload Require-Bundle?

If you are familiar with OSGi, you may be asking yourself why we didn't overload Require-Bundle instead of introducing Import-Bundle.

Well, we wanted Require-Bundle to retain its standard semantics, including the ability to marry together pieces of a split package. But we wanted Import-Library and Import-Bundle to have the same underlying semantics as Import-Package which avoid the complexities of split packages.

We also anticipate that, as the Platform evolves over time, we'll need to add further directives to Import-Library and Import-Bundle which would not be appropriate to add to Require-Bundle.

What Next?

The Platform beta program is in progress and we'll be listening to all feedback on Platform features, including the new manifest headers.

For users who want to take advantage of the Platform's headers, but who need to produce bundles which will run on other OSGi containers, we plan to produce a tool which will replace the Import-Library and Import-Bundle syntactic sugar with equivalent standard package imports.

We'll also be discussing the new manifest headers with our colleagues in the OSGi Alliance to determine if there are general requirements which would be appropriate for OSGi to address in the future.

Tuesday, May 06, 2008

SpringSource Application Platform Deployment Options

Since we released the SpringSource Application Platform last Wednesday, numerous developers have downloaded the 1.0.0 beta and started taking the Platform for a test drive. As a result, people have begun asking, "How can I deploy my apps on the Platform, and what kind of deployment and packaging options do I have?" Moreover, developers are eagerly requesting to see working samples. In response, the S2AP team will be releasing several sample applications over the coming weeks demonstrating these features and more, but before you get your hands on these samples, I'd like to give you a high-level overview of the deployment and packaging options available in the Platform. After reading this post you'll be ready to hit the ground running with the samples as well as with your own applications.

Overview

As Rob mentioned in his post last week, Introducing the SpringSource Application Platform, the Platform supports applications packaged in the following forms:

  1. Raw OSGi Bundles
  2. Java EE WAR
  3. Web Modules
  4. Platform Archive (PAR)

When you deploy an application to the Platform, each deployment artifact (e.g., a single bundle, WAR, or PAR) passes through a deployment pipeline. This deployment pipeline supports the notion of personality-specific deployers which are responsible for processing an application with a certain personality (i.e., application type). The 1.0.0 release of the Platform natively supports personality-specific deployers analogous to each of the aforementioned packaging options. Furthermore, the deployment pipeline can be extended with additional personality deployers, and future releases of the Platform will provide support for personalities such as Batch, Web Services, etc.

Let's take a closer look now at each of the supported deployment and packaging options to explore which one is best suited for your applications.

Raw OSGi Bundles

At its core, the SpringSource Application Platform is an OSGi container. Thus any OSGi-compliant bundle can be deployed directly on the Platform unmodified. You'll typically deploy an application as a single bundle or a set of stand-alone bundles if you'd like to publish or consume services globally within the container via the OSGi Service Registry. Please note, however, that due to the scoping nature of the PAR format, stand-alone bundles will not be able to consume services across application boundaries. In other words, a stand-alone bundle can not reference the services of modules deployed within a PAR.

WAR Deployment Options

For Web Application Archives (WAR), the SpringSource Application Platform provides support for the following three formats.

  1. Standard Java EE WAR
  2. Shared Libraries WAR
  3. Shared Services WAR

Each of these formats plays a distinct role in the incremental migration path from a standard Java EE WAR to an OSGi-ified web application.

Standard WAR

As Rob has already pointed out, "Standard WAR files are supported directly in the Platform. At deployment time, the WAR file is transformed into an OSGi bundle and installed into Tomcat. All the standard WAR contracts are honoured, and your existing WAR files should just drop in and deploy without change." Support for standard, unmodified WAR files allows you to try out the SpringSource Application Platform on your existing web applications and then gradually migrate toward the Shared Libraries WAR, Shared Services WAR, and Web Module formats.

Shared Libraries WAR

If you have experience with developing and packaging web applications using the standard WAR format, you're certainly familiar with the pains of library bloat. So, unless you're installing shared libraries in a common library folder for your Servlet container, you have to pack all JARs required by your web application in /WEB-INF/lib. Prior to the release of the Platform, such library bloat has essentially been the norm for web applications, but now there is a better solution! The Shared Libraries WAR format reduces your application's deployment footprint and eradicates library bloat by allowing you to declare dependencies on libraries via standard OSGi manifest headers such as Import-Package and Require-Bundle. The Platform provides additional support for simplifying dependency management via the Import-Library and Import-Bundle manifest headers which are essentially macros that get expanded into OSGi-compliant Import-Package statements.

For detailed information on what kind of libraries you already have at your disposal, check out the SpringSource Enterprise Bundle Repository. In addition, Andy Wilkinson will be posting a blog later this week explaining how to make the most of the Bundle Repository within your applications and the SpringSource Application Platform. So stay tuned.

Shared Services WAR

Once you've begun taking advantage of declarative dependency management with a Shared Libraries WAR, you'll likely find yourself wanting to take the next step toward reaping further benefits of an OSGi container: sharing services between your OSGi-compliant bundles and your web applications. By building on the power and simplicity of Spring-DM, the Shared Services WAR format puts the OSGi Service Registry at your fingertips. As a best practice you'll typically publish services from your domain, service, and infrastructure bundles via <osgi:service … /> and then consume them in your web application's ApplicationContext via <osgi:reference … />. Doing so promotes programming to interfaces and allows you to completely decouple your web-specific deployment artifacts from your domain model, service layer, etc., and that's certainly a step in the right direction. Of the three supported WAR deployment formats, the Shared Services WAR is by far the most attractive in terms of modularity and reduced overall footprint of your web applications.

Web Modules

Above and beyond WAR-based deployment formats, the SpringSource Application Platform introduces a deployment and packaging option for OSGi-compliant web applications, the Web Module format. Web modules have a structure similar to a Shared Services WAR and can therefore take full advantage of all three WAR deployment formats. In addition, web modules benefit from reduced configuration for Spring MVC based applications via new OSGi manifest headers such as Web-DispatcherServletUrlPatterns and Web-FilterMappings. For further details on these and other Web-* manifest headers, please consult the Platform's Programmer Guide. Upcoming releases of the Platform will also support web.xml fragments as well as the aforementioned manifest headers.

If you're building a Spring MVC based web application as a web module, you won't need to worry about configuring a root WebApplicationContext or an ApplicationContext for your DispatcherServlet. Based on metadata in your web module's /META-INF/MANIFEST.MF, the Platform will auto-generate an appropriately configured web.xml for you on-the-fly, and your application will use the ApplicationContext created for your web module by Spring-DM. Future releases will add additional support to simplify configuration of Spring Web Flow based web applications as well.

Migration path from WAR to Web Module

The following diagram graphically depicts the migration path from a Standard WAR to a Web Module. As you can see, the libs move from within the deployment artifact to the Bundle Repository. Similarly, the services move from within the WAR to external bundles and are accessed via the OSGi Service Registry. In addition, the overall footprint of the deployment artifact decreases as you move towards a Web Module.

Migration path from WAR to Web Module

Platform Archives

The final piece of the puzzle is the PAR (Platform Archive) deployment format. A PAR is a standard JAR which contains all of the modules of your application (e.g., service, domain, and infrastructure bundles as well as a WAR or web module for web applications) in a single deployment unit. This allows you to deploy, refresh, and undeploy your entire application as a single entity. For those of you familiar with Java EE, a PAR can be considered a replacement for an EAR (Enterprise Archive) within the context of an OSGi container. As an added bonus, modules within a PAR can be refreshed independently and on-the-fly, for example via the SpringSource Application Platform Tool Suite (register for the beta program and check out the Eclipse tooling support).

Furthermore, PARs scope the modules of your application within the Platform. Scoping provides both a physical and logical application boundary, shielding the internals of your application from any other applications deployed within the Platform. This means your application doesn't have to worry about clashing with other running applications (e.g., in the OSGi Service Registry). You get support for load-time weaving, classpath scanning, context class loading, etc., and the Platform does the heavy lifting for you to make all this work seamlessly in an OSGi environment. If you want to take full advantage of all that the SpringSource Application Platform and OSGi have to offer, packaging and deploying your applications as a PAR is definitely the recommend choice.

Where to go from here

If you haven't already done so, I encourage you to join the beta program and take the SpringSource Application Platform for a test drive yourself.

You'll find up-to-date documentation in the user guide and programmer guide, and if you happen to run into any issues deploying your applications or have recommendations on how we can improve the Platform, please don't hesitate to create a JIRA issue.

And last but not least, be sure to check out upcoming posts on the SpringSource Team Blog to keep abreast of news regarding the Platform and to see working examples including an OSGi-ified Spring PetClinic sample application which has been modularized and packaged as a PAR.

Friday, May 02, 2008

Running Spring Applications on OSGi with the SpringSource Application Platform

A lot of people have been asking what exactly the SpringSource Application Platform does for Spring applications to make them run well under OSGi, over and above what you can get out of the box with OSGi and Spring Dynamic Modules. Adrian's post yesterday highlighted some of the general issues, now lets look at a few of the details.

The three most challenging aspects of running Spring applications on OSGi are:

  • Load-time weaving
  • Classpath scanning
  • Thread context classloader management

The remaining, but less interesting, issues include: JSP support, TLD scanning, annotation matching and resource lookups. Overall, there was a decent-sized set of issues that needed to be solved to make applications deploy smoothly.

Load-time weaving

Load-time weaving was one of the most problematic features to support in a robust manner. At the basic level, it requires hooking into the Equinox ClassLoader so that standard ClassFileTransformers can be attached and used during the defineClass calls. On top of this, many uses of LTW require access to a throwaway ClassLoader that can be used to inspect types to decide what needs to happen during the weave, without affecting the real ClassLoader.

This base level of support was actually reasonably simple to achieve. The difficulty comes in when weaving is driven by classes in one bundle, but classes in another bundle need to be woven. This is pretty common in enterprise applications where one bundle contains domain entities and another contains types that use a JPA EntityManager. The Platform takes care of this complexity by ensuring that all bundles in an application can be woven with the appropriate ClassFileTransformers.

When you start propagating weaving across to other bundles, you really need to know when to stop. If you simply apply weaving to all bundles, then applications will interfere with each other. The Platform prevents this from happening by explicitly scoping weaving so that it applies only to modules in the application.

Another issue with LTW is that it complicates refresh. When a bundle is refreshed, OSGi will refresh all the bundles that depend on it. This means that, in the example I gave above, refreshing the domain bundle will cause the EntityManager bundle to be refreshed. However, refreshing the EntityManager does not refresh the domain bundle, meaning that weaving is possibly out of sync. The Platform handles this by propagating refresh to other bundles that are affected by weaving.

Classpath scanning

With classpath scanning, the main issue is that Equinox doesn't expose standard jar: and file: resources. The Platform puts an adapter in the middle so that libraries see the resource protocols that they expect. This has a nice side-effect of making a lot of third-party libraries work - it's not just a fix for classpath scanning.

Thread context classloader management

Many third-party libraries use the thread context ClassLoader to access application types and resources. Each bundle in OSGi has it's own ClassLoader, so therefore, only one bundle can be exposed as the thread context ClassLoader at any time. This means that if a third-party library needs to see types that are distributed across multiple bundles, it isn't going to work as expected.

The Platform fixes this by creating a ClassLoader that imports all the exported packages of every module in your application. This ClassLoader is then exposed as the thread context ClassLoader, enabling third-party libraries to see all the exported types in your application.

This is just a small cross-section of the issues that are addressed by the Platform but hopefully it gives you an idea of what the Platform means for Spring Framework users.

Thursday, May 01, 2008

Completing the picture: Spring, OSGi, and the SpringSource Application Platform

** Updated May 2nd with case study :- see the bottom of this post for details **
I'm sure most of you reading this blog will have seen the announcement of the SpringSource Application Platform yesterday. If not, be sure to check out Rob's blog post which describes some of the motivation, programming model, and roadmap.

A couple of common questions are being asked that I'd like to address straight away in this post. After that I'll describe two other exciting announcements that complement the SpringSource Application Platform itself but that didn't grab the headlines yesterday: the SpringSource Enterprise Bundle Repository and the Application Platform tools for Eclipse. Together these complete the story around OSGi-based enterprise application development with Spring.

The question I've heard several times over the last 24 hours is: what's wrong with OSGi - why can't we just use a vanilla OSGi Service Platform (such as Equinox, Felix, or Knopflerfish) instead of the SpringSource Application Platform?

There is absolutely nothing wrong with OSGi.

OSGi is a great foundation and service platform - that's why we and many others have chosen to build upon it. It's proven in a wide range of industries and applications, and underpins applications such as Eclipse and IBM's WebSphere as well as the middleware stacks of several other vendors.

Programming straight to the the OSGi specification APIs lacks some of the qualities we have come to expect for enterprise applications - such as the ability to use dependency injection and create applications that are easily unit and integration testable outside of the container. Programming straight to the OSGi specification APIs also forces you to deal at a relatively low level with the dynamics of the OSGi platform - what do you do when modules and services you depend on are stopped, started, installed, and updated at runtime? But there's no fundamental obstacle here that we weren't able to overcome with the Spring Dynamic Modules project. Applications built using Spring Dynamic Modules can run on any standard OSGi Service Platform, and we test all our builds against Equinox, Felix, and Knopflerfish. We are committed to ensuring that Spring Dynamic Modules and the Spring based programming model remain runtime neutral. That position will not change with the introduction of the SpringSource Application Platform.

There is also absolutely nothing wrong with existing enterprise libraries.

Well, ok. There are some cases that leave a little to be desired, but by and large we know how to make them work for enterprise application development needs.

So what's the problem then?

If OSGi works so well, and existing enterprise libraries are meeting our needs, then where's the problem? The difficulty comes when you try to combine an OSGi Service Platform with a set of existing enterprise libraries that weren't written with OSGi in mind. That's not the fault of OSGi, it's got a great model that provides for excellent modularity, versioning, and operational control. It's not the fault of the enterprise libraries either - they weren't written to run under OSGi. But the very things that make OSGi so attractive break assumptions that the developers of those enterprise libraries made. The modularity model of OSGi for example stops you seeing the private parts of other people's bundles. That's exactly what you want, until you realise that your enterprise library can no longer see your application types. Lots of things can break: from commons logging to jsps, tag libraries to data sources, load-time weaving to component scanning, resource loading to orm mapping. The list goes on… (Yes, you can get many of these things to work when you package your application code and all of the libraries it needs into a single bundle, but that's very much missing the point!).

This is why you see lots of people building on top of OSGi, but very few cases of passing OSGi benefits on into the application programming model (Eclipse RCP is a rare exception). When you build on top of OSGi, but don't necessarily expose that model for end user application development, you can build to the OSGi model and make things work. When you need to provide a platform on which large numbers of existing enterprise libraries can be used it's a different ball game. If we could just throw all that away and start again with libraries written explicitly for OSGi we'd be fine. We've made sure for example that the Spring Framework is fully able to run inside an OSGi Service Platform. But that's not a realistic proposition. Alternatively we could wait for the developers of existing libraries to convert them all to run under OSGi out of the box (as we have done with Spring). But what's the motivation for them to do that unless everyone else does it too? So we seem to be stuck in a chicken-and-egg situation. It's a problem that the OSGi Enterprise Expert Group has spent a lot of time discussing over the past year.
This is the problem that the SpringSource Application Platform solves :- it bootstraps enterprise application development into the world of OSGi by making standard OSGi bundles with standard OSGi semantics work with existing enterprise application libraries.

I'd also like to re-emphasize that the platform is not just about OSGi : the OSGi support is one of the features we're most excited about, but the SpringSource Application Platform is also an excellent server platform for deploying standard war files. We'll describe the benefits the platform offers in such scenarios in later postings.

Hopefully this post has helped to clear up some of the confusion surrounding exactly how the SpringSource Application Platform relates to OSGi. If you've been following along so far, you might have picked up on another lurking problem: it's all well and good to make existing enterprise libraries work under OSGi, but don't you need to turn all of their jar files into OSGi bundles in order to be able to deploy them? Yes you do. And it turns out that's a lot of work if you want to correctly version all of the imports and exports and ensure that you have correct symbolic names etc.. The good news is that for hundreds of commonly used enterprise applications libraries, we've done the hard work for you and made the OSGi-ready versions available in the SpringSource Enterprise Bundle Repository…

SpringSource Enterprise Bundle Repository

The SpringSource Enterprise Bundle Repository is both a repository that can be used from Ivy and Maven, and also an online searchable database of enterprise libraries. You'll find it at www.springsource.com/repository. You can browse for bundles by name, or just type in a search term to find bundles with matching names, exported packages, classes, or resources. You can also see the minimal (satisfying only the required dependencies) and maximal (satisfying as many of the optional dependencies as possible) transitive dependencies of any bundle.

From the FAQ:

"The SpringSource Enterprise Bundle Repository is a collection of open source libraries commonly used for developing enterprise Java applications with the Spring Framework. The repository contains jar files (bundles) and library definition (".libd") files. A library defines a collection of bundles that are often used together for some purpose (e.g. the "Spring Framework" library). There are hundreds of bundles contained in the repository."
The repository meets the following criteria:

  • Every jar file in the repository is a valid OSGi bundle. Any jar you download from the repository can be deployed as-is into an OSGi Service Platform and the SpringSource Application Platform. It can also be used as a regular jar file outside of OSGi.
  • Every bundle and library has full version information associated with it. The package export information for a bundle contains version information, and the package import information for a bundle contains full version range compatibility information.
  • The repository is transitively complete. The mandatory dependencies of any bundle are guaranteed to also be in the repository. Most of the optional dependencies of any bundle in the repository will also be present. The bundles listed in any library definition are guaranteed to be in the repository.
  • The repository is self-consistent. Before any artefact is uploaded to the repository, we verify that it can be installed, resolved, and started in an OSGi Service Platform (using the same profile as the SpringSource Application Platform) alongside all of the other bundles in the repository.
  • The repository can be used from Ivy and Maven based builds.

To maintain these guarantees we have put in place a governance model around the publishing of artefacts to the repository. There is a JIRA instance against which you can raise requests for additional libraries to be included and to report any problems (relating to OSGi manifests etc.) with existing published artefacts.

Application Development Tools:

So far we've discussed the Spring-based programming model for developing applications as OSGi bundles, the availability of enterprise libraries to deploy into an OSGi Service Platform, and a runtime (the SpringSource Application Platform) that enables these legacy libraries to work in an OSGi runtime. The missing piece of the puzzle is the developer tools that make the creation of OSGi-based applications easy.

Eclipse already has OSGi development tools built-in. Since every Eclipse plugin is also an OSGi bundle, the Eclipse PDE tools (Plugin Development Environment tools) can be used for OSGi application development. However, the fact that these tools were primarily designed for the development of Eclipse plugins shows through and there are a couple of common frustrations when using them for OSGi application development. One is that the META-INF/MANIFEST.MF file can only be placed at the root of the project - which doesn't work well with build tools such as Ivy and Maven, and the other is that you are restricted to a single target platform (collection of bundles to develop against) for your whole workspace. What *is* great about the PDE tools, and which you really need, is that they build the compilation classpath for your project from the OSGi manifest - so that you don't have differences in classpath and class visibility between compile, test, and runtimes.

Alongside the SpringSource Application Platform we've also released a set of Eclipse plugins (available from the SpringSource Application Platform download page) that makes the development of OSGi applications easier, especially applications targeted at the SpringSource Application Platform. Your META-INF/MANIFEST.MF file can be in any source directory, and the tools build the compilation classpath from the manifest entries. Instead of a single target platform though, you can associate your project with a SpringSource Application Platform server defined to Eclipse (using the WTP facilities). The classpath for your project is then derived from the import statements in your manifest, resolved against other bundle projects in your workspace and the bundles installed in the associated server. You get the exact same interpretation of your classpath and dependencies at compile time as you do at runtime. And of course, the normal "deploy to server" options work too.

Here's how the server looks when it's running inside Eclipse:

And this screenshot shows how the classpath is managed with a "Bundle Dependencies" classpath container. Notice how packages that you have not imported in your manifest file are greyed out to indicate that you can't currently access them.

Even better is how we're able to take advantage of OSGi's modularity. A set of projects (one per bundle) make up your application. When you change anything in the project, an additional incremental builder analyses the resources deltas and does a live update of the running bundle in the SpringSource Application Platform - so you're continually running with the latest code : every time, all the time. That's a great productivity boost and a great development experience.

Case Study

Matt Raible posted a blog entry about his adventures trying to get a Spring web application working under OSGi using Freemarker - without using the SpringSource Application Platform. This seemed like a good challenge application to test out what I said above about making existing enterprise libraries work. The good news is, this application runs very happily on the SpringSource Application Platform. Here are the steps I followed to make it work (total time, about 10 minutes):

  • Download the zip file from Matt's blog
  • Run 'mvn'
  • cp target/mpapp.war to the pickup directory of the Platform
  • Startup the platform: bin/startup.sh.

I got the following output to the console:

com.springsource.platform.deployer.core.DeploymentException: Unable to satisfy constraints of 'myapp' version '0.0.0':
Cannot resolve: myapp  Unsatisfied leaf constraints:
Bundle: myapp_0.0.0 - Import-Package: org.springframework.osgi.web.context.support; version="0.0.0"
Did you mean: 'org.springframework.osgi.context.support'?
Bundle: myapp_0.0.0 - Import-Package: freemarker.ext.servlet; version="0.0.0"
Did you mean: 'javax.servlet'?
Bundle: myapp_0.0.0 - Import-Package: freemarker.core; version="0.0.0"
Did you mean: 'org.hamcrest.core'?
Bundle: myapp_0.0.0 - Import-Package: freemarker.template; version="0.0.0"
Did you mean: 'org.antlr.tool'?
Bundle: myapp_0.0.0 - Import-Package: freemarker.cache; version="0.0.0"
Did you mean: 'org.apache'?

These are expected messages since I don't have freemarker or the osgi.web.context support bundles installed in the platform.

  • Go to http://www.springsource.com/repository. Type "freemarker" into the search box, find the one matching entry and click on the link to download it. Copy the downloaded bundle in repository/bundles/usr
  • Simplify the manifest to point to the new bundles and libraries on the platform. The original manifest looked like this:
Import-Package: javax.servlet,javax.servlet.http,javax.servlet.resources,javax.swing.tree,
javax.naming,org.w3c.dom,org.apache.commons.logging,javax.xml.parsers;resolution:=optional,
org.xml.sax;resolution:=optional,org.xml.sax.helpers;resolution:=optional,
org.springframework.osgi.web.context.support, org.springframework.context.support,
org.springframework.web.context, org.springframework.web.context.support,
org.springframework.web.servlet, org.springframework.web.servlet.mvc,
org.springframework.web.servlet.mvc.support, org.springframework.web.servlet.view,
org.springframework.ui, org.springframework.web.servlet.view.
freemarker, freemarker.cache,freemarker.core,freemarker.template,freemarker.ext.servlet

and I took it down to:

Import-Package: org.apache.commons.logging
Import-Library: org.springframework.spring;version="[2.5.4,3.0.0)"
Import-Bundle: com.springsource.freemarker;version="2.3.12"

When we know you are deploying a web application, the commonly required imports are automatically added at deployment time. Import-Library and Import-Bundle allow you to conveniently refer to libraries and bundles in a single statement. I also deleted the "Bundle-Classpath" entry as the application platform will automatically detect libraries in WEB-INF/lib and add them to the bundle classpath.

  • I edited web.xml and commented out the context-param declaration since there is no need to use a custom application context type here
  • Run 'mvn' again, and copy the myapp.war into the pickup directory.
  • The Application Platform automatically redeployed the application
  • Point a browser at http://localhost:8080/myapp/ …. SUCCESS!

I think this is a nice demonstration of the value proposition of the platform in smoothing the path of making enterprise libraries work under OSGi.

Wednesday, April 30, 2008

Introducing the SpringSource Application Platform

After many months of feverish coding, I am pleased to announce the beta release of the SpringSource Application Platform 1.0.

At the beginning of 2007 we began discussing possible alternatives to the monolithic and heavyweight application servers with which Enterprise Java has become synonymous. Customers were looking for a platform that was lightweight, modular and flexible enough to meet their development and deployment needs.

The Spring and Tomcat pairing demonstrates that developers and operators can successfully use a lightweight platform in production. Despite the success of this combination, the lack of modularity and explicit support for non-web applications limits its applicability and flexibility.

We set about building the SpringSource Application Platform to address these requirements and remove these limitations.

At the heart of the Platform is the Dynamic Module Kernel (DMK). The DMK is an OSGi-based kernel that takes full advantage of the modularity and versioning of the OSGi platform. The DMK builds on Equinox and extends its capabilities for provisioning and library management, as well as providing core function for the Platform.

SpringSource Application Platform Architecture

To maintain a minimal runtime footprint, OSGi bundles are installed on demand by the DMK provisioning subsystem. This allows for an application to be installed into a running Platform and for its dependencies to be satisfied from an external repository. Not only does this remove the need to manually install all your application dependencies, which would be tedious, but it keeps memory usage to a minimum.

The DMK itself requires a minimal set of bundles to run, and is configured with a profile to control exactly the set of additional modules that are loaded. For example, the DMK does not require Tomcat to be present, but the default Platform profile includes Tomcat to allow web applications to be deployed. If you want to run a Platform without Tomcat, you can simply edit the profile and it won't be installed. (If you try this - remember that removing web support means that web modules will no longer deploy, so delete the contents of the pickup directory so the platform won't attempt to install the Admin and splash screen applications when it starts.) The default Platform configuration with the admin console installed takes only 15MB of memory.

One frustration I have always had with Enterprise Java is that applications are often shoe-horned into contrived silos, and that explicit support for different application types is lacking. Consider an application for an online store. This application has a web front-end, a message-driven order processing module, a batch-driven stock reordering module and a B2B web service module. Today, many applications like this would be packaged as a WAR or an EAR and the modules would look very similar, with little support for the differences in the module types. Interestingly, many people would refer to this as a web application, rather than an application with a web module.

In the SpringSource Application Platform, applications are modular and each module has a personality that describes what kind of module it is: web, batch, web service, etc. The Platform deploys modules of each personality in a personality-specific manner. For example, web modules are configured in Tomcat with web context. Each module in the application can be updated independently of the other modules whilst retaining the identity of being part of the larger application. Whatever kind of application you are building, the programming model remains standard Spring and Spring DM.

In the 1.0 Platform release we support the web and bundle personalities, which enable you to build sophisticated web applications. Future releases will include support for more personalities as detailed later.

Building Applications

The Platform supports applications packaged in three forms:

  1. Java EE WAR
  2. Raw OSGi bundles
  3. Platform Archive (PAR)

Standard WAR files are supported directly in the Platform. At deployment time, the WAR file is transformed into an OSGi bundle and installed into Tomcat. All the standard WAR contracts are honoured, and your existing WAR files should just drop in and deploy without change.

Any OSGi-compliant bundle can be deployed directly into the Platform, and can take full advantage of on-the-fly provisioning for any dependencies referred to by Import-Package and Require-Bundle.

The PAR format is the recommended approach for packaging and deploying applications for the Platform. A PAR is simply a collection of OSGi bundles (modules) grouped together in a standard JAR file, along with a name and a version that uniquely identify the application. The PAR file is deployed as a single unit into the Platform. The Platform will extract all the modules from the PAR and install them. Third-party dependencies will be installed on-the-fly as needed.

The PAR format has three main benefits over deploying the bundles directly into the Platform. Firstly, it's just easier. An average-sized enterprise application might contain 12+ bundles - deploying these by hand will be far too cumbersome. Secondly, the PAR file forms an explicit scope around all the bundles in the application which prevents applications that use overlapping types or services from clashing with each other. This scope is also used by some advanced features such as load-time weaving to ensure that weaving of one application doesn't interfere with weaving of another. Lastly, the PAR forms a logical grouping to define what modules are part of an application and what third-party dependencies the application has. This grouping is used by the management tools to provide a detailed view of the application. A typical PAR application looks like this:

PAR File Structure

Dependencies between modules in an application are typically expressed using Import-Package and Export-Package. Dependencies on third-party libraries can be expressed in the same way, but for many libraries this can be error-prone and time-consuming. When using a library such as Hibernate, you will typically have to import more packages than you initially expect. To get around this you could use Require-Bundle, but this has some semantic rough edges such as split packages where a logical package is split across two or more class loaders causing problems at runtime. The Platform introduces two new mechanisms for referring to third-party dependencies: Import-Bundle and Import-Libary. Import-Bundle is analogous to Require-Bundle except it prevents split packages and the other problems with Require-Bundle. Import-Library provides a mechanism to refer to all the packages exported by a group of bundles, for instance all bundles in the Spring Framework, in a single declaration:

Bundle-SymbolicName: com.myapp.dao.jdbc
Bundle-Version: 1.0.0
Import-Bundle: org.apache.commons.dbcp;version="1.2.2.osgi"
Import-Library: org.springframework.spring;version="2.5.4.A"

Here I have a module bundle that depends on the Commons DBCP bundle and the Spring Framework library. The Spring Framework library contains all the bundles needed to use Spring in your application.

Import-Library and Import-Bundle expand under the covers into Import-Package and are therefore consistent with standard OSGi semantics.

The Platform understands the personality of a module, and from this can infer how to configure the module's execution environment. When deploying a web module, all the servlet infrastructure needed for a typical Spring MVC application is created automatically, removing the need to recreate this boilerplate code across applications. In the 1.0 final release, more smarts will be added to the web module personality to support additional technologies such as Spring Web Flow.

Whatever packaging format you choose, the programming model is simply Spring Framework and Spring Dynamic Modules, with the other Spring Portfolio products running on top.

Serviceability

Serviceability was a critical consideration for the whole engineering team. We have spent an inordinate amount of time worrying about the format of log messages and the size of stack traces to make sure that diagnosing problems with your applications is as easy as possible. Any time we find a task that is repetitive and time-consuming we look for a way to automate it or remove it altogether.

To aid with problem diagnosis the Platform has a strong split between log and trace messages. Log messages are intended for end-user consumption and allow you to get access to the most important failure information without having to trawl through gigabytes of trace content. All application failures are displayed and coded in the log output - the codes serving as a convenient way to access knowledge base or support content. To understand why this is so useful, consider the following output from Platform startup:

[2008-04-29 12:12:01.124] main <SPKB0001I> Platform starting.
[2008-04-29 12:12:04.037] main <SPKE0000I> Boot subsystems installed.
[2008-04-29 12:12:06.013] main <SPKE0001I> Base subsystems installed.
[2008-04-29 12:12:07.396] platform-dm-1 <SPPM0000I> Installing profile 'web'.
[2008-04-29 12:12:07.674] platform-dm-1 <SPPM0001I> Installed profile 'web'.
[2008-04-29 12:12:07.721] platform-dm-14 <SPSC0000I> Creating ServletContainer on port 8080
[2008-04-29 12:12:08.036] platform-dm-10 <SPPM0002I> Platform open for business with profile 'web'.
[2008-04-29 12:12:09.405] fs-watcher <SPSC1000I> Creating web application '/admin'
[2008-04-29 12:12:09.652] async-delivery-thread-1 <SPSC1001I> Deploying web application '/admin'

Gone are the pages and pages of output detailing the inner workings of every single type in the startup call chain. Instead, you get messages that actually mean something. Of course, this doesn't mean you can't find out what every type is doing: we still maintain an extensive trace. Indeed, because we split out the most important log messages from trace, our trace can be more verbose because it is intended to be read less often.

Critical failures in the Platform generate a service dump that can be passed to support personnel to aid in the diagnosis process. This dump contains state from all the major subsystems in the Platform and is hooked in via AspectJ to make sure we pick up every possible site where an unchecked Exception can be raised.

The Platform also actively monitors for problems in the JVM and triggers a dump. In the 1.0 release this is limited to deadlock monitoring only, but will include memory, lock contention and CPU contention in future releases.

Roadmap

This beta release is only the start for the SpringSource Application Platform. We have tentatively defined a roadmap to cover the 2.0 release with a focus on five main areas: the Admin Console, middleware integration, additional personalities, clustering and DMK 2.0.

With the Admin Console we want to exploit all the application knowledge that the Platform has, and make this available to the end-user. The Admin Console will allow for detailed inspection of applications starting at the module level and running right down to the bean level. Applications will be linked to the libraries and bundles they depend on, and the Admin Console will provide the ability to upgrade these libraries dynamically. By understanding the different types of beans that an application contains, the Admin Console will provide for detailed insight into application internals and allow for dynamic reconfiguration of certain application components.

To support typical enterprise deployment scenarios, the 2.0 version of the Platform will provide explicit support for common enterprise middleware components such as Oracle, TIBCO EMS and IBM MQSeries. Integration with the Admin Console will allow for connections to these middleware providers to be established in minutes rather than hours or days. Applications will be able to access these connections using the OSGi service registry and Spring DM's <osgi:reference>.

The 2.0 release will introduce additional personalities to cover batch, web services and SOA applications.

Clustering is an important feature for the 2.0 release, with cluster-wide Single System Image (SSI) being the critical piece, and load-balancing and clustered caching being on the roadmap as well. Using the SSI support, administration and deployment operations will be propagated across the cluster. Ultimately, we want to support per-module updates across the cluster, with full cluster-rollback if the upgrade breaks a deployed application.

DMK 2.0 will include improvements to the concurrency subsystem to support large numbers of bundles that change frequently and to support larger numbers of modules with more complex interdependencies. Also included will be updates to the provisioning subsystem and integrated resource management and monitoring for memory, threads, IO and CPU.

What next?

Please download the Platform and try it out. We are keen to hear about your experiences building new applications and deploying existing ones. All feedback, positive or negative, is welcome. We are particularly interested to hear how we can make the process of building and deploying applications easier and more enjoyable.

The binary releases and forums can be found here. Both the user's guide and programmer's guide are available online. We have a JIRA instance set up here.

Tuesday, April 29, 2008

Today, Portability Matters More Than Ever

Yesterday, I blogged about how Spring helps maximize application portability. Even if the portability problem has been an ongoing topic in enterprise Java land for many years, that blog was timely. Today, Oracle announced that its $6.7 billion acquisition of BEA Systems has closed. There is substantial overlap between the product sets of the two companies, so this is bound to bring uncertainty to the WebLogic and OC4J customer bases. WebLogic and OC4J may both fall into the "J2EE server" category but they are very different products with very different characteristics.

Since many enterprise applications end up integrating very closely with the hosting environment, switching a J2EE server is never a trivial task. Quite on the contrary, it may turn out to cause as much pain as switching an operating system. Common J2EE APIs such as the Servlet API are usually less of a problem, despite subtleties in configuration etc. The real problems usually hide in transaction management setup, resource access semantics, integration with external messaging providers, application-wide authentication and authorization, etc. Even the very heart of J2EE, namely JNDI as lookup mechanism, can cause a lot of issues due to different setup rules, server-specific names for EJB components, etc.

Fortunately, the many WebLogic and OC4J customers who adopted the Spring programming model are in a comfortable position. They are not only enjoying Spring-style productivity, but are well placed to manage any server migration that may lie ahead. The Spring Framework in conjunction with key portfolio products such as Spring Security allows for handling many common concerns within an enterprise application's own boundaries. Environment services are used in typical Spring delegation style, in a more specific fashion than in a standard J2EE scenario. As a consequence, moving to a different hosting environment is usually much less intrusive from the application's perspective.

We also hear from Spring users on WebSphere who appreciate those same portability benefits in the migration scenarios that they are currently facing: between different generations of the WebSphere Application Server itself (5.1 / 6.0 / 6.1 / 6.1 with EE 5 feature packs), but also between the established WebSphere Application Server and the Geronimo-based WebSphere Community Edition (which are very different products under the common WebSphere naming umbrella).

I never thought that I would be in the insurance business ;-) - but it is satisfying to see Spring helping developers deal with the changing marketplace.

Tuesday, April 29, 2008

Web Applications and OSGi

Since the first milestones of Spring Dynamic Modules, requests for running web applications in OSGi started to come in. It has been probably one of the most requested features and no wonder, once 1.0 final was released, web support has been the main focus of the 1.1 branch. I am pleased to report that, with the just released M2, as already hinted by Juergen, Spring-DM supports not just vanilla wars (available since 1.1.0 M1) but also Spring-MVC applications running inside OSGi. In this entry, I would like to briefly discuss the typical OSGi web scenario and Spring-DM's approach. But first,

Why deploy WARs in OSGi?

Easy question: OSGi natively provides versioning, package wiring and hot reloading. Imagine taking advantage of these features within your applications: you can stop embedding libraries under WEB-INF/lib and start sharing them between your web apps, avoid taglibs duplications (while keeping multiple versions running) and update, at runtime, only certain parts of your application. This is especially useful as web applications tend to be tiered and thus subject to a significant number of changes during their life cycle.

Why are web applications in OSGi problematic?

The Servlet specification revolves around the idea of a web container: a runtime environment for web components that provides standard services such as life cycle management (object creation and disposal, thread allocation), concurrency, HTTP request handling and so on. The OSGi platform on the other hand, acts also as a managed environment with its Service Registry, package wiring and versioning (to name just a few). To deal with this problem, the OSGi committee designed, part of the compendium specification, the Http Service.

As a side note, when dealing with two managed environments, one is facing an interesting problem: what deployment model to use? That is which is be the bootstrapping platform and which one embedded? In our case, one can either deploy the OSGi platform as a WAR or deploy the web container (under some form of service), inside the OSGi platform. More about this though, in a future entry.

This optional service provides a simple API for registering Servlets and static resources which are mapped to incoming HTTP requests. In order to have a Servlet serving requests inside OSGi, one must programmatically create the Servlet instance and registered it through the aforementioned API. Further more, the Http service supports only the Servlet 2.1 specification which can be quite inconvenient since filters and listeners (used by virtually all of the web frameworks today) are not available.
Most (if not all) of the solutions available today (that I am aware of), for running web applications in OSGi, rely on the Http Service for their functionality. Some address the problems mentioned above using one of the following techniques (as far as I know):

  • eliminate the need for code by imposing new or translating existing declarative approaches (such as web.xml) into calls to the Http Service
  • provide Servlet 2.1+ features by building on top of the 2.1 API (for example a filter can be implemented by decorating a Servlet instance) or by extending the standard API

Both of these methods can be successful and go a long way however, in Spring-DM, we opted for a different, unique approach by:

Integrating directly with the web container

In Spring-DM, the OSGi and container space are bridged: the WARs, deployed as usual to the web container