5.3. Simplifying dependencies through libraries

Large applications tend to be structured to include shared portions. For example, all web applications are likely to share common web infrastructure such as Spring MVC and Spring Web Flow. Direct use of the Import-Package directive will force expressing the same dependencies in multiple applications as shown in the following figure.

An OSGi application may express dependencies on libraries, a new artifact introduced by the SpringSource Application Platform. A library is a collection of bundles with a library name and library version number. Libraries may be packaged inside the applications that use them for ease of deployment. This takes the form of a library JAR nested inside an OSGi application JAR. Libraries typically do not have a personality and simply provide supporting code for other applications to use.

Library dependencies are defined in the metadata of the bundles of an OSGi application and these dependencies are managed by the Platform to ensure that an application with unsatisfied transitive dependencies is never started. Dependencies are always captured in individual bundles rather than at the level of a whole application or library. Each dependency is represented as a new SpringSource Platform specific Import-Library header which specifies a list of libraries and library version ranges and which supports a resolution directive with values 'optional' and, the default, 'mandatory'.

As a program element, a library is simply a text file describing a set of bundles.

Library-SymbolicName: org.springframework.spring
Library-Version: 2.5.4
Import-Bundle: org.springframework.core;version="[2.5.4,2.5.5)",
 org.springframework.beans;version="[2.5.4,2.5.5)",
 org.springframework.context;version="[2.5.4,2.5.5)",
 org.springframework.aop;version="[2.5.4,2.5.5)",
 org.springframework.web;version="[2.5.4,2.5.5)", 
 org.springframework.web.servlet;version="[2.5.4,2.5.5)",
 org.springframework.jdbc;version="[2.5.4,2.5.5)",
 org.springframework.orm;version="[2.5.4,2.5.5)",
 org.springframework.transaction;version="[2.5.4,2.5.5)",
 org.springframework.context.support;version="[2.5.4,2.5.5)",
 org.springframework.aspects;version="[2.5.4,2.5.5)",
 com.springsource.org.aopalliance;version="1.0"
	

Table 5.3. Library directives

DirectiveDescription
Library-SymbolicNameIdentifier for the library
Library-Version Version number for the library
Import-BundleA comma separated list of bundles, each may optionally specify a version
Library-NameOptional. The human-readable name of the library
Library-DescriptionOptional. A human-readable description of the library

Forms of libraries

The SpringSource Application Platform support two forms of libraries: one that declares the constituents and another that additionally packages the constituent bundles.

The first form of library is simply a text file with .libd extension. The file includes directives to express the constituent bundles and their versions. Here is an example of the org.springframework.spring_2.5.4.libd file:

Library-SymbolicName: org.springframework.spring
Library-Version: 2.5.4
Import-Bundle: org.springframework.core;version="[2.5.4,2.5.5)",
 org.springframework.beans;version="[2.5.4,2.5.5)",
 org.springframework.context;version="[2.5.4,2.5.5)",
 org.springframework.aop;version="[2.5.4,2.5.5)",
 org.springframework.web;version="[2.5.4,2.5.5)", 
 org.springframework.web.servlet;version="[2.5.4,2.5.5)",
 org.springframework.jdbc;version="[2.5.4,2.5.5)",
 org.springframework.orm;version="[2.5.4,2.5.5)",
 org.springframework.transaction;version="[2.5.4,2.5.5)",
 org.springframework.context.support;version="[2.5.4,2.5.5)",
 org.springframework.aspects;version="[2.5.4,2.5.5)",
 com.springsource.org.aopalliance;version="1.0"

The org.springframework.spring library includes twelve bundles. If an application module wishes to use Spring it may simply do so by using an Import-Library directive in its manifest file:

Import-Library: org.springframework.spring;version="[2.5.4,2.5.4]"
This is equivalent to an Import-Package directive that lists every export of each of the twelve bundles in the org.springframework.spring library.
[Tip]What's the catch?

A downside to using libraries, instead of the Import-Package directive, is that the bundle that uses the library ends up importing all the packages exported by its constituent bundles. For example, a bundle importing the org.springframework.spring library will end up importing the org.springframework.web.servlet.view.jasperreports package even if it doesn't need to use Jasper Reports. This poses a problem if you intend to exercise very fine control over the imported packages. In most practical situations, however, the simplicity offered by libraries outweighs the coarse granularity introduced by it. Further, the possibility of using the same libraries in multiple application tips the balance in favor of library. Without libraries, you not only have to write long Import-Package directives, you have to repeat those in each application.

The second form of library includes, in addition to the directives, the referred bundles. This offers and simpler way to distribute the library artifacts. As an artifacts, this form of library is a jar files that includes a ".libd" file and jars for the referred bundles. As an example, org.springframework_spring-mvc.lib, is a file with jar format that contains the following entries:

org.springframework_spring-mvc.libd
org.springframework.bundle.spring.web.jar
org.springframework.bundle.spring.webmvc.jar