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; ... }