blob: ab43a76e59701986b8db5901c375c2580254bf8e [file] [log] [blame]
:doctype: book
Title: Blueprint
+++<a name="Blueprint-Blueprint">++++++</a>+++
= Blueprint
+++<a name="Blueprint-Introduction">++++++</a>+++
== Introduction
Blueprint provides a dependency injection framework for OSGi and was standardized by the OSGi Alliance in OSGi Compendium R4.2.
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) enabling simple components to be written and unit tested in a JSE environment without needing to be aware of how they are assembled.
The Blueprint XML files that define and describe the assembly of various components are key to the Blueprint programming model.
The specification describes how the components get instantiated and wired together to form a running module.
The following documentation covers the 80:20 usage of Blueprint.
For further details, please refer to the OSGi Compendium R4.2 specification.
+++<a name="Blueprint-BlueprintBundles">++++++</a>+++
== Blueprint Bundles
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 the components
* Wiring the components together
* Registering services
* Looking up service references
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.
+++<a name="Blueprint-BlueprintXML">++++++</a>+++
== Blueprint XML
The Blueprint XML file is identified by a top-level blueprint element, as shown below:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
...
</blueprint>
The XML namespace identifies the document as conforming to the Blueprint version 1.0.0.
The top-level blueprint element identifies the document as a blueprint module definition.
_TODO:_ ensure id, activation and dependsOn get documented somewhere.
+++<a name="Blueprint-Beans">++++++</a>+++
== Beans
Beans are declared using the bean element.
The following defines a single bean called _accountOne_ implemented by the POJO _org.apache.aries.simple.Account_.
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<bean id="accountOne" class="org.apache.aries.simple.Account" />
</blueprint>
+++<a name="Blueprint-BeanConstruction">++++++</a>+++
=== Bean Construction
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.
A bean can be constructed using a class constructor.
In the following 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.
....
:::java
public class Account {
public Account(long number) {
...
}
...
}
<bean id="accountOne" class="org.apache.aries.simple.Account">
<argument value="1"/>
</bean>
....
A bean can be constructed using a static factory method.
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 _StaticAccountFactory_ class and pass 2 as the argument to create the Account object.
....
public class StaticAccountFactory {
public static Account createAccount(long number) {
return new Account(number);
}
}
<bean id="accountTwo"
class="org.apache.aries.simple.StaticAccountFactory"
factory-method="createAccount">
<argument value="2"/>
</bean>
....
A bean can be constructed using an instance factory method.
In the example, the _accountFactory_ bean 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.
public class AccountFactory { + public AccountFactory(String factoryName) { ...
} public Account createAccount(long number) { return new Account(number);
} }
....
<bean id="accountFactory"
class="org.apache.aries.simple.AccountFactory">
<argument value="account factory"/>
</bean>
<bean id="accountThree"
factory-ref="accountFactory"
factory-method="createAccount">
<argument value="3"/>
</bean>
....
+++<a name="Blueprint-BeanProperties">++++++</a>+++
=== Bean Properties
Beans can have property values injected.
Injection is performed immediately after the bean is constructed.
The following example creates the Account bean and then sets the description property using the Java Beans naming convention.
public class Account { + public Account(long number) { ...
} public String getDescription() { ...
} }
<bean id="accountOne" class="org.apache.aries.simple.Account">
<argument value="1"/>
<property name="description" value="#1 account"/>
</bean>
+++<a name="Blueprint-BeanWiring">++++++</a>+++
==== Bean Wiring
Property injection is used for wiring beans together.
In the following example _accountOne_ is injected with a _Currency_ bean.
....
public class Account {
public Account() {
...
}
public void setCurrency(Currency currency) {
...
}
}
public class Currency {
public Currency() {
...
}
}
<bean id="accountOne" class="org.apache.aries.simple.Account">
<property name="currency" ref="currency" />
</bean>
<bean id="currency" class="org.apache.aries.simple.Currency" />
....
+++<a name="Blueprint-Services">++++++</a>+++
== Services
In Blueprint XML, a service element defines the registration of a service in the OSGi service registry.
The bean that provides the service object can be referenced using the _ref_ attribute.
The interfaces under which the service is registered can be specified using the _interface_ attribute:
....
public class AccountImpl implements Account {
public Account() {
...
}
public void setCurrency(Currency currency) {
...
}
}
<service id="serviceOne" ref="account"
interface="org.apache.aries.simple.Account" />
<bean id="account" class="org.apache.aries.simple.AccountImpl" />
....
The bean that provides the service object can be inlined in the service element as follows:
<service id="serviceTwo" interface="org.apache.aries.simple.Account">
<bean class="org.apache.aries.simple.AccountImpl" />
</service>
The interfaces under which a service is registered can be determined by Blueprint using _auto-export_.
The following registers the service under all the bean's interfaces:
....
<service id="serviceOne" ref="account" auto-export="interfaces" />
<bean id="account" class="org.apache.aries.simple.AccountImpl" />
....
Other values for _auto-export_ are _disabled_ (the default) _class-hierarchy_ and _all-classes_.
+++<a name="Blueprint-ServiceProperties">++++++</a>+++
=== Service Properties
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 OSGi service property types are permitted: primitives, primitive wrapper classes, collections, or arrays of primitive types.
The following is an example of a service registration with two service properties.
The _active_ service property has type of _java.lang.Boolean_.
The _mode_ property is of the default type, _String_.
<service id="serviceFour" ref="account" autoExport="all-classes">
<service-properties>
<entry key="active">
<value type="java.lang.Boolean">true</value>
</entry>
<entry key="mode" value="shared"/>
</service-properties>
</service>
+++<a name="Blueprint-ServiceRanking">++++++</a>+++
=== Service Ranking
Service ranking can be used to affect the choice of service when there are multiple matches.
When choosing between two services, the higher ranked service will be returned ahead of the lower.
The default ranking value is
. Service ranking is specified using the _ranking_ attributes as follows:
<service id="serviceFive" ref="account" auto-export="all-classes"
ranking="3" />
+++<a name="Blueprint-References">++++++</a>+++
== References
Services are found in the service registry using the reference element.
The following shows a reference named _accountRef_ to an _Account_ service.
If a service matching this reference is found in the service registry then it is set on the _accountClient_ bean through the _account_ property.
....
<bean id="accountClient" class="...">
<property name="account" ref="accountRef" />
</bean>
<reference id="accountRef" interface="org.apache.aries.simple.Account"
/>
....
+++<a name="Blueprint-ReferenceDynamism">++++++</a>+++
=== Reference Dynamism
The object that is injected for a reference is actually a proxy to the service registered in the service registry.
A proxy enables 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 at which point a ServiceUnavailableException will be thrown.
try {
balance = account.getBalance();
} catch (ServiceUnavailableException e) {
...
}
The default timeout Blueprint will wait for is 300000 milliseconds (5 minutes).
This value can be changed on a per bundle basis using directives on the Bundle-SymbolicName.
The following switches the timeout off completely (the default is true):
Bundle-SymbolicName: org.apache.aries.simple.account;
blueprint.graceperiod:=false
The following sets the timeout to 10000 milliseconds (10 seconds):
Bundle-SymbolicName: org.apache.aries.simple.account;
blueprint.graceperiod:=false; blueprint.timeout=10000;
The timeout can also be set on an individual reference using the _timeout_ attribute.
The following sets the timeout for the account reference to 20000 milliseconds (20 seconds).
<reference id="accountRef" timeout="20000"
interface="org.apache.aries.simple.Account" />
In all cases, a value of 0 means wait indefinitely for the reference to become satisfied.
+++<a name="Blueprint-ReferenceLists">++++++</a>+++
=== Reference Lists
Multiple matching services can be found using the _reference-list_ element.
The _reference-list_ 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 only supports a subset of the _List_ API.
The proxies in a _reference-list_ are different from the proxies for a reference.
The _reference-list_ proxies target a specific service, do not have a _timeout_, and throw _ServiceUnavailableException_ immediately if their service becomes unavailable.
The following example shows a reference-list that returns a list of service objects (proxies).
This is the default value for the _member-type_ attribute
<reference-list id="accountRefs" member-type="service-object"
interface="org.apache.aries.simple.Account" />
The following shows an example of a reference-list that returns a list of ServiceReferences:
<reference-list id="accountRefs" member-type="service-reference"
interface="org.apache.aries.simple.Account" />
Example showing mandatory or optional references (availability)
Example showing use of filter
+++<a name="Blueprint-BeanProperties">++++++</a>+++
== Bean Properties
Example showing use of bean properties
+++<a name="Blueprint-Scopes">++++++</a>+++
== Scopes
Example showing singleton scope
Example showing prototype scope for beans
Example showing prototype scope for services
+++<a name="Blueprint-ObjectValues">++++++</a>+++
== Object Values
Intro to Object Values
Examples showing the use of the various different object value types - ref, map, props collection (list, array, set).
+++<a name="Blueprint-Lifecycle">++++++</a>+++
== Lifecycle
Example showing use of init/destroy-method
+++<a name="Blueprint-LazyandEagerActiviation">++++++</a>+++
== Lazy and Eager Activiation
Example showing lazy activiation.
Example showing eager activation.
+++<a name="Blueprint-Dynamism">++++++</a>+++
== Dynamism
Example showing service-listener
Example showing reference-listener
+++<a name="Blueprint-TypeConverters">++++++</a>+++
== Type Converters