The OSGi framework, which provides great mechanisms for developing modular and dynamic applications, has been growing in popularity. The recent OSGi Service Platform Release 4 V4.2 specifications introduced a specification called the Blueprint Container.
The Blueprint Container specification defines a dependency injection framework for OSGi. It is designed to deal with the dynamic nature of OSGi, where services can become available and unavailable at any time. The specification is also designed to work with plain old Java objects (POJOs) so that the same objects can be used within and outside the OSGi framework. The Blueprint XML files that define and describe the various components of an application are key to the Blueprint programming model. The specification describes how the components get instantiated and wired together to form a running application.
The Blueprint Container specification uses an extender pattern, whereby an
extender bundle monitors the state of bundles in the framework and
performs actions on behalf of those bundles based on their state. The Blueprint extender bundle waits
for the bundles to be activated and checks whether they are Blueprint
bundles. A bundle is considered to be a Blueprint bundle when it contains
one or more Blueprint XML files. These XML files are at a fixed
location under the OSGI-INF/blueprint/
directory or are specified explicitly in the
Bundle-Blueprint manifest header.
Once the extender determines that a bundle is a Blueprint bundle, it creates a Blueprint Container on behalf of that bundle. The Blueprint Container is responsible for:
- Parsing the Blueprint XML files
- Instantiating
- Wiring the components together
During initialization, the Blueprint Container ensures that mandatory service references are satisfied, registers all the services into the service registry, and creates initial component instances. The Blueprint extender bundle also destroys the Blueprint Container for a bundle when the bundle is stopped.
This article focuses on the Blueprint XML. Learn, with several examples, about the component XML definitions and their use.
The Blueprint XML file is identified by a top-level
blueprint element, as shown in Listing 1.
Listing 1. Blueprint XML file fragment
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns=”http://www.osgi.org/xmlns/blueprint/v1.0.0”>
...
</blueprint>
|
The Blueprint XML file contains definitions of various component managers. The Blueprint Container specification defines four main component managers: a bean manager, a service manager, and two service reference managers. Each manager is responsible for creating and managing the life cycle of the components they create. When asked, the managers provide a component instance. Each manager has a corresponding XML element that describes the manager properties. The managers can be top-level managers or inlined within other manager definitions. The managers also share some common attributes.
id- Defines the manager ID. The
idattribute is optional. If it is not specified, a unique ID will be automatically generated and assigned to a top-level manager. The inlined managers are considered anonymous and do not allow for theidattribute to be set. The manager IDs must be unique for all top-level managers within the Blueprint Container. The IDs are used so managers can refer to each other. For example, during injection, the manager will ask the referenced managers to provide an object that will be injected into the component that the manager is creating. activation- This optional attribute defines the
activation mode for the manager. Two activation modes are supported:
eager, where the manager is activated during Blueprint Container initialization.lazy, where the manager is activated on demand.
eageractivation mode is assumed. However, the default activation mode for all managers within the Blueprint XML file can be changed by setting thedefault-activationattribute on theblueprintelement. A manager is activated when it is asked to provide its first component instance. A manager is deactivated when the Blueprint Container is being destroyed. Each manager has its own activation and deactivation steps. -
dependsOn - This optional attribute specifies a
list of manager IDs. The listed managers will be activated first, before
the manager is activated. A manager can have explicit and implicit
dependencies. The
dependsOnattribute defines the explicit dependencies. The implicit dependencies are defined by the references to other managers within a manager definition.
A bean manager creates an instance of a Java object with the given arguments and properties. A bean manager can create single or multiple object instances depending on the scope settings. It can also manage the life cycle of an object and notify it when all properties have been injected or when it is being destroyed.
In Blueprint XML, a bean element defines a bean
manager. The arguments used for object construction are specified by the
argument elements; the injected properties
are specified by the property sub-elements.
During object construction, the Blueprint Container must first find the
right constructor or a factory method with a compatible set of
parameters
that matches the arguments specified in the XML. By default, the Blueprint
Container uses the number and order of the
argument elements in XML to find the right
constructor or method. If the argument
elements cannot be mapped to the parameters in the order they are in, the
Blueprint Container will attempt to reorder the
argument elements and find the best-fitting
arrangement.
To help the Blueprint Container pick the right
constructor, method, or parameter arrangement, additional attributes,
such as index or
type, can be specified on the
argument element. For example, the
type attribute specifies a class name
used to match the argument element to a
parameter by the exact type.
The property element specifies the name and
value of the property to inject. The property name corresponds to a setter
method name in the Java class. For example, if the property name is
foo, the corresponding setter method is
setFoo(arg). The property names and
corresponding setter method names follow the design pattern for properties
as defined in the JavaBeans specification.
The value for the argument and
property elements can be specified using a
value or ref attribute, or it can be inlined. The
ref attribute specifies the ID of a top-level
manager, and is used to obtain an object from the referenced manager as the
argument or property value. The inlined value can be any of the XML values
described in the "Object values" section.
A bean can be constructed in three ways by using:
- A class constructor
- A static factory method
- An instance factory method
Listings 2, 3, and 4 demonstrate three ways of constructing Java objects. Each listing shows a partial Java class and the corresponding Blueprint XML excerpt that drives the object creation.
Listing 2 shows a simple constructor creation example. In this example, the
class attribute specifies the name of the Java
class to instantiate. The Blueprint Container will create the
Account object by passing 1 as the argument to
the constructor and calling the setDescription()
method to inject the description property.
Listing 2. Constructor example
public class Account {
public Account(long number) {
...
}
public void setDescription(String description) {
...
}
public String getDescription() {
...
}
}
<bean id=”accountOne” class=“org.apache.geronimo.osgi.Account”>
<argument value=”1”/>
<property name=”description” value=”#1 account”/>
</bean>
|
Listing 3 shows a static factory method construction. In this example, the
class attribute specifies the name of the class
that contains a static factory method. The name of the static factory
method is specified by the factory-method
attribute. The Blueprint Container will call the
createAccount() static method on the
AccountFactory class and pass 2 as the argument
to create the Account object. Once the factory
returns the created object, the container will inject it with the
description property.
Listing 3. Static factory method example
public class StaticAccountFactory {
public static Account createAccount(long number) {
return new Account(number);
}
}
<bean id=”accountTwo” class=“org.apache.geronimo.osgi.StaticAccountFactory”
factory-method=“createAccount”>
<argument value=”2”/>
<property name=”description” value=”#2 account”/>
</bean>
|
With an instance factory method construction, as shown in
Listing 4, two managers are used. One manager is a
factory, and the other uses the factory to create an object. The
factory-ref attribute is used to specify the ID
of a top-level bean or a reference manager that acts like a factory. The
provided factory object must have a factory method as specified by the
factory-method attribute.
In the example, the
accountFactory bean manager is the factory. The
Blueprint Container will first create the
AccountFactory instance with its own arguments
and properties. In this case, only a single argument is specified: the
factory name. The Blueprint Container will then call the
createAccount() method on the
AccountFactory instance and pass 3 as the
argument to create the Account object. Once the
factory returns the created object, the container will inject it with the
description property.
Listing 4. Instance factory method example
public class AccountFactory {
public AccountFactory(String factoryName) {
...
}
public Account createAccount(long number) {
return new Account(number);
}
}
<bean id=”accountFactory” class=“org.apache.geronimo.osgi.AccountFactory”>
<argument value=”account factory”/>
</bean>
<bean id=”accountThree”
factory-ref=“accountFactory”
factory-method=“createAccount”>
<argument value=”3”/>
<property name=”description” value=”#3 account”/>
</bean>
|
Depending on the scope setting, a bean manager can create single or multiple object instances. The Blueprint Container specification defines two main scopes:
-
singleton - The bean manager creates a single instance of the bean and returns that instance every time the manager is asked to provide an object.
-
prototype - The bean manager creates a new instance of the bean every time the manager is asked to provide an object.
By default, the singleton scope is assumed for
top-level bean managers. The scope attribute
cannot be set on an inlined bean manager, so the inlined
managers are always considered to have
prototype scope.
The scope attribute is used to specify the scope
settings. Listing 5 shows two bean definitions with different scope
settings.
Listing 5. Scope examples
<bean id=”prototypeAccount” class=“org.apache.geronimo.osgi.Account”
scope=”prototype”>
<argument value=”4”/>
</bean>
<bean id=”singletonAccount” class=“org.apache.geronimo.osgi.Account”
scope=”singleton”>
<argument value=”5”/>
</bean>
|
A bean manager can also manage the life cycle of the object it creates and can notify it when all properties have been injected or when it is being destroyed. The Blueprint Container specification defines two callback methods:
-
init-method - Specifies a method to be called once all the properties have been injected.
-
destroy-method - Specifies a method to be called when the Blueprint Container is destroying the object instance.
The destroy-method callback is not supported for
beans in the prototype scope. It is the
responsibility of the application to destroy those instances. Both
life-cycle methods must be public, take no arguments, and return no value.
Listing 6 shows an example of a Java class with life-cycle methods and
a Blueprint XML bean entry that specifies the
init-method and
destroy-method attributes.
Listing 6. Life-cycle callback example
public class Account {
public Account(long number) {
...
}
public void init() {
...
}
public void destroy() {
...
}
}
<bean id=”accountFour” class=“org.apache.geronimo.osgi.Account”
init-method=”init” destroy-method=”destroy”>
<argument value=”6”/>
<property name=”description” value=”#6 account”/>
</bean>
|
Service reference managers provide access to the services registered in the OSGi service registry. There are two service reference managers defined by the Blueprint specification: reference and reference list.
The reference manager provides an object that is a proxy to the actual service registered in the service registry. A proxy allows the injected object to remain the same while the backing service can come and go or be replaced with another service. Calls on a proxy that does not have a backing service will block until a service becomes available or a timeout occurs.
The reference manager is defined by a reference
element. The amount of time a proxy will wait for a backing service to be
available is specified using the timeout
attribute. If the timeout attribute is not
specified, the default timeout of five minutes is assumed. The default
timeout can also be changed for all reference managers in the Blueprint
XML file using the default-timeout attribute on
the blueprint element. All timeout values are
specified in milliseconds; a value of 0 means indefinite timeout.
Listing 7 shows a simple reference manager example. The service proxy will have a 30-second timeout.
Listing 7. Reference manager example
<reference id=”serviceReferenceOne”
interface=”java.io.Serializable”
timeout=”30000”/>
|
The reference-list manager provides a List object that contains the
service proxy objects or ServiceReference
objects, depending on the member type setting. The provided List object is
dynamic, as it can grow and shrink as matching services are added or
removed from the service registry. The List object is read-only and
supports only a subset of the List API.
The proxies in a reference-list manager are different from the proxies in a
reference manger. They have a fixed backing service, do not have a
timeout, and throw ServiceUnavailableException immediately if the backing service becomes unavailable.
The reference-list manager is defined by a
reference-list element. The type of the members
in the provided List object is specified using the
member-type attribute. The
member-type attribute supports two values:
-
service-object - Injects a list of service proxy objects, assumed by default.
-
service-reference - Injects a list of
ServiceReferenceobjects.
Listing 8 shows a simple reference-list manager example. The List members
will be service proxies.
Listing 8. Reference-list manager example
<reference-list id=”serviceReferenceListOne”
interface=”java.io.Serializable”
member-type=”service-object”/>
|
The reference and reference-list managers share several attributes.
Three shared attributes are used for service selection: interface,
component-name and a
filter.
You can use the interface attribute to specify an
interface class. The interface class is used for two purposes:
for service selection and for service proxies. The
interface attribute is optional, but if set, it
must specify an interface class. For service selection, the interface
class is used to select services from the service registry
registered with that interface name. For service proxies, the proxies
returned by service reference managers must implement all the methods
defined by that interface class. If the interface attribute is not
specified, the proxy behaves as if it implements an interface without any
methods.
You can also use the component-name and
filter attributes for service
selection. The component-name attribute is just
a convenient way of adding an
osgi.service.blueprint.compname=<component-name>
expression to the selection filter. Similarly, the filter attribute specifies the raw OSGi filter expression to be added to the selection filter. The
interface,
component-name, and
filter attributes are combined to create
one main OSGi filter expression used for the service selection.
For example, the selection filter for the reference in Listing 7 is
(&(objectClass=java.io.Serializable)),
while the selection filter for the reference in Listing 9 is
(&(objectClass=java.io.Serializable)(osgi.service.blueprint.compname=myAccount)(mode=shared)).
Listing 9. Service selection example
<reference id=”serviceReferenceTwo”
interface=”java.io.Serializable”
component-name=”myAccount”
filter=”(mode=shared)”/>
|
A service reference manager can require that at least one service that
matches its selection criteria must exist before the Blueprint Container
initialization can continue. That requirement is controlled with the
availability attribute. The
availability attribute can have two values:
-
optional - Services matching the selection criteria may or may not exist.
-
mandatory - At least one service matching the selection criteria must exist.
By default, mandatory availability is assumed.
The default availability setting can be changed for all service
reference managers in the Blueprint XML using a
default-availability attribute on the
blueprint element.
A service reference manager with mandatory
availability that has a matching service is considered satisfied. A
service reference manager with optional
availability is always considered satisfied even if it does not have
any matching services. The Blueprint Container initialization will be
delayed until all mandatory service reference managers are satisfied.
It's important to understand that mandatory
availability is only considered during Blueprint Container initialization.
After initialization, the mandatory service reference can become
unsatisfied as services come and go at any point.
Listing 10 shows an example of a reference manager with
mandatory availability.
Listing 10. Availability example
<reference id=”serviceReferenceThree”
interface=”java.io.Serializable”
timeout=”30000”
availability=”mandatory”/>
|
Both service reference managers can have zero or more reference listeners.
Reference listeners are objects that have callback methods
invoked when the service is selected by the service reference manager or
when the service is no longer used by the service reference manager. A
reference listener is specified using the
reference-listener element. The
bind-method and
unbind-method attributes specify the callback
methods. The object that provides the callback methods can be
inlined within the reference-listener element
or specified as a reference to a top-level manager.
Both bind and unbind callback methods can have any of the following
signatures. (anyMethod represents an arbitrary
method name.)
-
void anyMethod(ServiceReference) - The argument is a
ServiceReferenceobject of the service being bound or unbound. -
void anyMethod(? super T) - The argument is the service object proxy being bound or unbound. The type T must be assignable from the service object.
-
void anyMethod(? super T, Map) - The first argument is the service object proxy being bound or unbound. The type T must be assignable from the service object. The second argument provides the service properties associated with the service.
If a reference listener has multiple overloaded methods for a callback, every method with a matching signature is invoked.
For a reference-list manager, the listener callbacks are invoked each time a matching service is added or removed from the service registry. However, for a reference manager, the bind callback will not be invoked when the manager is already bound to a service and a matching service with lower ranking is added to the service registry. Similarly, the unbind callback will not be called when the service the manager is bound to goes away and it can be immediately replaced with another matching service.
It's important to understand that when using a reference manager and interacting with stateful services, you should use reference listeners to track the backing services of the proxy in order to manage the state of the service appropriately.
Listing 11 shows a simple registration listener example. The
ReferenceListener class has two bind and one
unbind callback methods, which will be called as the services are bound and
unbound from the service reference-list manager.
Listing 11. Reference-listener example
public class ReferenceListener {
public void bind(ServiceReference reference) {
...
}
public void bind(Serializable service) {
...
}
public void unbind(ServiceReference reference) {
...
}
}
<reference-list id=”serviceReferenceListTwo” interface=”java.io.Serializable”
availability=”optional”>
<reference-listener
bind-method=”bind” unbind-method=”unbind”>
<bean class=“org.apache.geronimo.osgi.ReferenceListener”/>
</reference-listener>
</reference-list>
|
A service manager registers a service in the OSGi service registry. The service
manager registers and unregisters the service if all the mandatory service
reference managers in its dependencies are satisfied. Since the mandatory
service references can become unsatisfied at any point, a service manager
returns a ServiceRegistration proxy object that
delegates the calls to the actual
ServiceRegistration object.
During initialization, a Blueprint Container registers
ServiceFactory-based services for each service
manager in the Blueprint Container instead of the actual service objects.
These services allow the Blueprint Container to delay the object creation
as they intercept the service requests and instantiate the actual service
object only when needed. The actual service object is provided by another
manager, usually a bean manager. The actual service object can implement
the OSGi ServiceFactory interface.
In Blueprint XML, a service element defines a
service manager. The manager that provides the service object can
be referenced using the ref attribute or be
inlined within the service element. Listing 12
shows two services: one with a referenced and one with an inlined
manager.
Listing 12. Service-manager examples
<service id=”serviceOne” ref=”account” ... />
<service id=”serviceTwo” … >
<bean class=“org.apache.geronimo.osgi.Account”>
<argument value=”123”/>
</bean>
</service>
|
Each service must be registered under one or more interface names. The list of the interface names for the service can be specified explicitly or determined automatically from the service object based on the auto-export setting. The interface names can be set explicitly using either:
interfaceattribute, which can only specify a single interface name.interfacessub-element, which allows any number of interfaces to be set.
The auto-export setting is
specified by the auto-export attribute and
supports the four options below.
-
disabled - The default value if the
auto-exportattribute is not specified. The list of interfaces must be specified using theinterfaceattribute orinterfacessub-elements. -
interfaces - Register the service using all public interfaces implemented by the service class and any of its super classes.
-
class-hierarchy - Register the service using the service class and any of its public super classes.
-
all-classes - Combines
interfacesandclass-hierarchyoptions.
Listing 13 shows services with three ways of specifying the
service interfaces. In this example, serviceOne
and serviceTwo services are registered with a
single Serializable interface class, while
serviceThree service is registered with
MyAccount, Account,
and Serializable classes.
Listing 13. Service interface examples
public class MyAccount extends Account implements java.io.Serializable {
...
}
<bean id=”myAccount” class=”org.apache.geronimo.osgi.MyAccount”>
<argument value=”7”/>
<property name=”description” value=”MyAccount”/>
</bean>
<service id=”serviceOne” ref=”myAccount” interface=”java.io.Serializable”/>
<service id=”serviceTwo” ref=”myAccount”>
<interfaces>
<value>java.io.Serializable</value>
</interfaces>
</service>
<service id=”serviceThree” ref=”myAccount” autoExport=”all-classes”/>
|
A service can also be registered with a set of properties that
can be specified using the service-properties
sub-element. The service-properties element
contains multiple entry sub-elements that
represent the individual properties. The property key is specified using a
key attribute, but the property value can be
specified as a value attribute or
inlined within the element. The service property values can be of
different types, but only primitives, primitive wrapper classes,
collections, or arrays of primitive types are allowed.
Listing 14 shows an example of a service registration with two service
properties. The active service property has a
value of java.lang.Boolean type. The
mode property is of
String type.
Listing 14. Service properties examples
<service id=”serviceFour” ref=”myAccount” autoExport=”all-classes”>
<service-properties>
<entry key=”mode” value=”shared”/>
<entry key=”active”>
<value type=”java.lang.Boolean”>true</value>
</entry>
</service-properties>
</service>
|
An osgi.service.blueprint.compname property is
automatically added to the service properties if the manager that provides
the service object for the service is a top-level manager. The value of
the osgi.service.blueprint.compname property is the ID
of the top-level manager that provides the service instance. For example,
given the service example in Listing 14, the value of
osgi.service.blueprint.compname property would be set
to myAccount.
You can use the ranking attribute to expose the
service with a specific ranking. If the ranking attribute is not
specified, the service will be registered without a ranking. In such
cases, the OSGi framework assumes 0 as the default ranking for the
service.
An example of service registration with a ranking is shown below.
Listing 15. Service ranking example
<service id=”serviceFive” ref=”myAccount” auto-export=”all-classes” ranking=”3”/>
|
A service manager can have zero or more registration listeners,
which are objects that have callback methods
invoked right after the service is registered or right before the service
is unregistered. A registration listener is specified using the
registration-listener sub-element. The
registration-method, and
unregistration-method attributes specify the
callback methods. The object that provides the callback methods can
be inlined within the registration-listener
element, or be specified as a reference to a top-level manager.
The signature for the registration and unregistration callback methods
depends on whether the service object implements the
ServiceFactory interface. If the service
implements the ServiceFactory interface, both
methods must have a
void anyMethod(ServiceFactory, Map) signature,
where anyMethod represents an arbitrary method
name.
If the service does not implement the
ServiceFactory interface, both callback methods
must match the void anyMethod(? super T, Map)
signature, where the type T is assignable from the service object's type.
The first argument to the callback method is an instance of the service
object, and the second argument is the registration properties. If a
registration listener has multiple overloaded methods for a callback, then
every method with a matching signature is invoked.
Listing 16 shows a simple registration listener example.
Listing 16. Registration listener example
public class RegistrationListener {
public void register(Account account, Map properties) {
...
}
public void unregister(Account account, Map properties) {
...
}
}
<service id=”serviceSix” ref=”myAccount” auto-export=”all-classes”>
<registration-listener
registration-method=”register” unregistration-method=”unregister”>
<bean class=“org.apache.geronimo.osgi.RegistrationListener”/>
</registration-listener>
</service>
|
The Blueprint Container specification also defines a number of special environmental managers that have set IDs and provide access to the environmental components. They have no XML definition and cannot be overridden, since their IDs are reserved and may not be used with other managers. The objects provided by environment managers can only be injected into other managers using a reference. The Blueprint Container specification defines four environment managers:
-
blueprintBundle - Provides bundle's
Bundleobject. -
blueprintBundleContext - Provides bundle's
BundleContextobject. -
blueprintContainer - Provides the
BlueprintContainerobject for the bundle. -
blueprintConverter - Provides the
Converterobject for the bundle that provides access to the Blueprint Container type conversion facility. Type conversion has more information.
Listing 17 shows a simple example where the
Bundle object provided by the
blueprintBundle environmental manager is
injected into the accountManagerOne bean.
Listing 17. Environment manager example
public class AccountManager {
public void setManagerBundle(Bundle bundle) {
...
}
}
<bean id=”accountManagerOne” class=”org.apache.geronimo.osgi.AccountManager”>
<property name=”managerBundle” ref=”blueprintBundle”/>
</bean>
|
The Blueprint Container specification defines many XML elements that describe different types of object values. These XML value elements are used within the manager definitions. For example, they can be used in a bean manager to specify argument or property values, or in a service manager to specify the service properties' values. The XML value elements are converted into the actual value objects and injected into the manager components.
The ref element defines a reference to a top-level
manager. The component-id attribute specifies
an ID of a top-level manager. The injected value will be the object
returned by the referenced manager.
Listing 18 shows an example of the ref value
element. The accountOne bean instance is
injected into the managedAccount property of the
accountManagerTwo bean.
Listing 18. Reference value example
public class AccountManager {
...
public void setManagedAccount(Account account) {
...
}
}
<bean id=”accountOne” class=“org.apache.geronimo.osgi.Account”>
<argument value=”1”/>
<property name="description" value="#1 account"/>
</bean>
<bean id=”accountManagerTwo” class=“org.apache.geronimo.osgi.AccountManager”>
<property name=”managedAccount”>
<ref component-id=”accountOne”/>
</property>
</bean>
|
The idref element defines an ID of a top-level
manager. The injected value is the component-id as specified by the
component-id attribute. The
idref element is used to ensure that the manager of
the specified ID actually exists before the manager is activated.
The value element represents an object to be
created from the string content of the element. You can use the optional
type attribute to specify a type
into which the string content should be converted. If the
type attribute is not specified, the string
content will be converted into the type it is being injected into.
The null element represents Java null.
The list, set, and
array elements are collections and represent a
java.util.List object,
java.util.Set object, and
Object[] array, respectively. The sub-elements
of these collections can be any of the XML value elements described in
this section. The optional value-type
attribute can be set on these elements to specify a default type for the
collection sub-elements.
The example in Listing 19 shows how the XML value elements can be combined to create a list. The created list will contain the following four items:
- A “123”
String - A
java.math.BigIntegerobject with 456 value - A null
- A
java.util.Setobject with two values of typejava.lang.Integer
Listing 19. Complex list value example
<list>
<value>123</value>
<value type=”java.math.BigInteger”>456</value>
<null/>
<set value-type=”java.lang.Integer”>
<value>1</value>
<value>2</value>
</set>
</list>
|
The props element represents a
java.util.Properties object where the keys and
values are of String type. The
prop sub-elements represent the individual
properties. The property key is specified using a
key attribute, but the property value can be
specified as a value attribute or as a
content of the element.
Listing 20 shows an example of the props value
element.
Listing 20. Properties value example
<props>
<prop key=”yes”>good</prop>
<prop key=”no” value=”bad”/>
</props>
|
The map element represents a
java.util.Map object where the keys and the
values can be arbitrary objects. The entry sub-elements represent the individual properties. The key can be specified as
a key attribute,
key-ref attribute, or inlined within a
key sub-element. The value can be specified as
a value attribute,
value-ref attribute, or be inlined. The inlined
value can be specified as any of the XML value elements described in this
section. However, the inlined key can be specified as any of the XML value
elements except the null element. Null keys are
not allowed in map elements in the Blueprint
Specification. The key-ref and
value-ref attributes specify an ID of a top
level manager and are used to obtain an object from the specified manager
as the property key or value. The map
element can specify key-type and
value-type attributes to define a default type
for keys and values.
Listing 21 shows an example of the map value
element. It also shows how the entries of a map object can be constructed
in several ways. The created map object will contain the
following entries:
- A myKey1
Stringkey that is mapped to myValueString. - A key that is an object returned by
accountbean manager is mapped to myValueString. - A key that is a
java.lang.Integerobject with 123 value is mapped to myValueString. - A myKey2
Stringkey is mapped to a value that is an object returned byaccountbean manager. - A myKey3
Stringkey is mapped to a value that is ajava.lang.Longobject with 345 value. - A key that is a
java.net.URIobject with urn:ibm value is mapped to a value which is ajava.net.URLobject with http://ibm.com value.
Listing 21.
map value example
<map>
<entry key=”myKey1” value=”myValue”/>
<entry key-ref=”account” value=”myValue”/>
<entry value=”myValue”>
<key>
<value type=”java.lang.Integer”>123</value>
<key/>
</entry>
<entry key=”myKey2” value-ref=”account”>
<entry key=”myKey3”>
<value type=”java.lang.Long”>345</value>
</entry>
<entry>
<key>
<value type=”java.net.URI”>urn:ibm</value>
<key/>
<value type=”java.net.URL”>http://ibm.com</value>
</entry>
</map>
|
Each manager can also be inlined as a value. Listing 22 shows an inlined bean manager example.
Listing 22. Inlined manager value example
<bean id=”accountManagerThree” class=“org.apache.geronimo.osgi.AccountManager”>
<property name=”managedAccount”>
<bean class=“org.apache.geronimo.osgi.Account”>
<argument value=”10”/>
<property name="description" value="Inlined Account"/>
</bean>
</property>
</bean>
|
During injection, the Blueprint Container converts the XML value elements
into actual objects. It converts the elements based on the type of the
injected property. For example, in Listing 2, the Blueprint Container
converts the 123 String value into a long
value. The Blueprint Container provides a number of built-in conversions,
such as converting:
- String values into all primitive types, wrapper types, or any types that have a public constructor that takes a String value.
-
arrayelements into collection objects (with compatible member types). -
listorsetelements into array objects (with compatible member types).
The Blueprint Container also supports generics. If the generics information
is available, the Blueprint Container will use that information to perform
the conversions. For example, in Listing 23 the
list element will be converted into a list of
java.util.Long objects.
Listing 23. Generics conversion example
public class AccountManager {
...
public void setAccountNumbers(List<Long> accounts) {
...
}
}
<bean id=”accountManagerFour” class=“org.apache.geronimo.osgi.AccountManager”>
<property name=”accountNumbers”>
<list>
<value>123</value>
<value>456</value>
<value>789</value>
</list>
</property>
</bean>
|
In addition to the built-in conversions, a Blueprint bundle can provide its
own converters. The custom converters are bean managers that
provide an object that implements Blueprint's
Converter interface. The custom converters
are specified within the type-converters
element under the blueprint element. The type
converters are initialized first during Blueprint Container initialization
so other managers can take advantage of the custom converters. The Blueprint Container specification has more information about
writing custom converters.
To experiment with Blueprint applications, you need two things: an OSGi platform and the Blueprint Container implementation. In this article, we will use Equinox as the OSGi platform, but others — such as Apache Felix — would work just as well. For the Blueprint Container, we will use an implementation from the Apache Aries incubator project. The Blueprint implementation in Aries was originally developed at the Apache Geronimo project, but has been moved to Aries, where it is being actively developed.
The attached sample provides a good starting point for experimenting with Blueprint. It
contains two modules: blueprint-sample and blueprint-assembly. The blueprint-sample
module is a sample Blueprint bundle. It contains many of the Java classes and
Blueprint XML definitions shown in this article. The blueprint-assembly module packages the Equinox framework, the Apache Aries Blueprint implementation, and the sample bundle together in an easy-to-start container.
Download and unzip the attached sample source to a directory of your choice. Use Apache Maven to build the sample source. Execute the commands in Listing 24 to build the sample.
Listing 24. Building the sample
cd sample mvn install |
Maven will automatically build both modules in the sample. Once the entire sample is
successfully built, the target directory of the blueprint-assembly module will contain a number of JAR files. It will
contain the Apache Aries Blueprint implementation, the sample bundle and a couple
other JARs that provide logging capabilities for the OSGi framework. It will also
contain the osgi-3.5.0.v20090520.jar file, which provides the Equinox framework. Once
started, the Equinox framework will automatically install and start all the other JARs
in the target directory. To start the Equinox framework, execute the commands in Listing 25.
Listing 25. Starting Equinox
cd blueprint-assembly/target java -jar osgi-3.5.0.v20090520.jar -console |
The Equinox console will appear after successful startup. Use the ss command to display the installed bundles; Figure 1 shows the output of the ss command.
Figure 1. Installed bundles output
The sample bundle will be automatically installed in Equinox framework, but
will not be started. To start the sample bundle, execute the start 5 command in the Equinox console; the number 5 is the ID of the
org.apache.aries.sample_1.0.0.SNAPSHOT sample
bundle. Once the sample bundle is successfully started, you should see the following output in the console, as shown in Figure 2.
Figure 2. Sample bundle output
The Blueprint Container specification, introduced in the latest OSGi specification, provides a simple and easy programming model for creating dynamic applications in the OSGi environment without adding complexity to the Java code. With the Aries Blueprint Container implementation, you can start building Blueprint-based applications today.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample source | os-osgiblueprint-sample.zip | 11KB | HTTP |
Information about download methods
Learn
-
Check out JavaWorld's OSGi
Bundles for
beginners tutorial. Learn how to create, execute, and manage bundles in an OSGi
container.
-
Read more about dependency injection.
-
Learn more about the
OSGi Alliance and get the latest
news, events, forums, specifications. and more.
-
Apache Geronimo is producing
a server runtime framework that pulls together open source
alternatives to create runtimes that meet the needs of developers and system administrators.
-
Learn all about
Apache Felix.
-
Get an overview of Apache Aries.
-
The property names and
corresponding setter method names follow the design pattern for properties
as defined in the
JavaBeans
specification.
- Learn how
Spring Dynamic Modules
make it easy to build Spring applications that run in an OSGi framework.
-
To listen to interesting interviews and discussions for software developers, check out developerWorks podcasts.
-
Stay current with developerWorks' Technical events and webcasts.
-
Follow developerWorks on Twitter.
-
Check out upcoming conferences, trade shows, webcasts, and other Events around the world that are of interest to IBM open source developers.
-
Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products, as well as our most popular articles and tutorials.
-
Watch and learn about IBM and open source technologies and product functions with the no-cost developerWorks On demand demos.
Get products and technologies
-
Download the OSGi
V4.2 specifications from the
OSGi Alliance. The Blueprint Container Specification is in the Compendium Specification.
- To install Karaf,
download the binary
distribution file for your
platform.
- Get
Apache Maven to build the sample
bundle source.
-
Innovate your next open source development project with IBM trial software, available for download or on DVD.
- Download
IBM product evaluation versions
or explore
the online trials in the IBM SOA Sandbox and get your hands on application development tools and middleware products from
DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
Discuss
-
Participate in developerWorks blogs and get involved in the developerWorks community.






