blob: 244bdc46b188459927adefce7abed339d1359a1e [file] [log] [blame]
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
0. 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