Title: BlueprintAnnotation
# Introduction
Blueprint annotation is being prototyped in Apache Aries in
trunk/blueprint. The blueprint annotation service is an optional service
to the blueprint core and should not affect the blueprint core if
annotation supported is not required. If the blueprint annotation service
is available, the bundle contains no blueprint definition XML and the
bundle contains the manifest header *Bundle-Blueprint-Annotation* with
the value set to true, the blueprint annotation service will attempt to
scan the bundle for blueprint annotations, such as @Blueprint, @Bean,
@Service, @Reference, @ReferenceList, etc. The blueprint annotation api is
available in trunk/blueprint/blueprint-annotation-api module, while the
blueprint implementation is available in
trunk/blueprint/blueprint-annotatiom-impl module. A blueprint annotated
sample is also provided in trunk/blueprint/blueprint-sample-annotation.
## Overview of Available blueprint Annotations
### @Inject Annotation
@Inject annotation can be used to inject fields or methods.
@Bean(id="bar")
public class Bar {
@Inject(value="Hello FooBar")
private String value;
@Inject(ref="blueprintBundleContext")
private BundleContext context;
...
}
### @Bean Annotation
You can annotate a bean using @Bean annotation. The bean id is currently
required, even tho it is possible we may want to the annotation service to
auto generate one in the future. Optionally, you can also specify
activation, dependsOn, description, scope, factoryRef, factoryMethod and
args of the bean.
\* Example of using args property for the @Bean annotation.
@Bean(id="accountOne", args=@Arg(value="1"))
public class Account {
private long accountNumber;
public Account(long number) {
this.accountNumber = number;
}
}
\* Example of using factoryMethod and args properties for the @Bean
annotation
@Bean(id="accountTwo",
factoryMethod="createAccount",
args = @Arg(value="2"))
public class StaticAccountFactory {
public static Account createAccount(long number) {
return new Account(number);
}
}
\* Example of using factoryRef, factoryMethod, and args properties for the
@Bean annotation
@Bean(id="accountThree",
factoryRef="accountFactory",
factoryMethod="createAccount",
args=@Arg(value="3"))
public class NewAccount {
private long accountNumber;
public NewAccount(long number) {
this.accountNumber = number;
}
...
}
### @Service, @RegistrationListener, @Register, @Unregister Annotations
If you want to register a bean as a service, you can use @Service
annotation to do so. You can specify ranking, autoExport, interfaces,
serviceProperties and registrationListeners for the service.
@Bean(id="foo")
@Service(autoExport="all-classes",
serviceProperties =
@ServiceProperty(key="blueprint.annotation.sample", value="true"),
registerationListeners =
@RegistrationListener(ref="fooRegistrationListener"),
ranking=0)
public class Foo implements Serializable {
...
}
To annotation a class as registration listener, you can use the
@RegistrationListener annotation. @Register can be used to annotate the
register-method for the registration listener and @Unregister annotation
can be used on the unregister-method for the registration listener.
@Bean(id="fooRegistrationListener")
@RegistrationListener
public class FooRegistrationListener {
@Register
public void serviceRegistered(Serializable foo, Map props) {
System.out.println("Service registration notification: " + foo + "
" + props);
}
@Unregister
public void serviceUnregistered(Foo foo, Map props) {
System.out.println("Service unregistration notification: " + foo +
" " + props);
}
}
### @Reference, @ReferenceList, @ReferenceListener Annotations
For a bean that you want to act as a ReferenceListener, you can use
@ReferenceListener to annotate the bean class.
For the service that you want to inject the reference, you can use the
@Inject and @Reference annotation, with the id, serviceInterface, timeout
and referenceListeners properties specified for the reference.
@Bean(id="bindingListener")
@ReferenceListener
public class BindingListener {
@Inject @Reference (id="ref2",
serviceInterface = InterfaceA.class,
timeout=100,
referenceListeners=@ReferenceListener(ref="bindingListener"))
private InterfaceA a;
...
@Init
public void init() {
}
@Bind
public void bind(InterfaceA a, Map props) {
this.a = a;
this.props = props;
}
@Unbind
public void unbind(InterfaceA a, Map props) {
this.a = null;
this.props = null;
}
}
@ReferenceList is very similar as @Reference, except that the timeout
property is not supported in @ReferenceList, while the memberType property
is supported in @ReferenceList. This is same as the blueprint XML schema.
@Bean(id="listBindingListener")
@ReferenceListener
public class ListBindingListener {
@Inject @ReferenceList (id="ref-list",
serviceInterface = InterfaceA.class,
referenceListeners=@ReferenceListener(ref="listBindingListener"))
private InterfaceA a;
...
}
### @Blueprint annotation
@Blueprint annotation can be used on any class to annotate the global
property of the blueprint bundle, such as defaultActivation,
defaultTimeout, defaultAvailability.
@Blueprint(defaultActivation="eager", defaultTimeout=300,
defaultAvailability="optional")
@Bean(id="bar")
public class Bar {
...
}
### Type converters
If type converters are desired, you can use the @Bean annotation for it.
The blueprint annotation service will recognize it as a type converter if
it implements the *org.osgi.service.blueprint.container.Converter*
interface
@Bean(id="converter1")
public class DateTypeConverter implements Converter {
@Inject(name="format", value="yyyy.MM.dd")
DateFormat dateFormat;
...
}
### Limitation
Blueprint Annotation is still prototype work and currently only runtime
annotation scanning is supported. While it provides some basic useful
functions, there are still many things that you cannot do using annotation,
such as inject a list with values, inject inline beans, etc.