SeamFramework.orgCommunity Documentation
A Weld-OSGi auto-published service is described by these attributes (and their equivalents for a regular OSGi service):
A (nonempty) set of service contracts (service class names)
A set of qualifiers (service properties)
A scope
A Publish
annotated CDI bean instance (service instance)
A Weld-OSGi service bean is described by these attributes (and their equivalents for OSGi service lookup):
An OSGiService
annotated or Service<T>
typed injection point
A type (lookup type)
A Filter
qualifier (lookup LDAP filter)
A (possibly empty) set of reachable instance (lookup result)
Annotate a CDI bean class with a Publish
annotation makes Weld-OSGi register this bean as a
OSGi service.
Such a service is accessible through Weld-OSGi service injection and OSGi classic mechanisms.
Automatically publish a new service implementation:
@Publish public class MyServiceImpl implements MyService { }
However, such an implementation also provides a regular CDI managed bean, so MyServiceImpl can also be injected using CDI within the bean bundle.
Weld-OSGi auto-published service get their types from the following algorithm:
If a (nonempty) contract list is provided (as an array of Class
) with the
Publish
annotation the service is registered for all these types. This is how
define a contract
list:
@Publish(contracts = { MyService.class, AbstractClass.class }) public class MyServiceImpl extends AbstractClass implements MyService, OtherInterface { }
The implementation class may be assignable for all of the contract types. If not, Weld-OSGi detects the problem and treats it as an error.
Else if the implementation class possesses a (nonempty) list of non-blacklisted interfaces the service is registered for all these interface types.The blacklist is described below.
Else if the implementation class possesses a non-blacklisted superclass, the service is registered for this superclass type.
Last if the implementation class has neither contract nor non-blacklisted interface or superclass, the service is register with is the implementation class type.
An OSGiService
annotated or a Service<T>
typed injection point is managed by
Weld-OSGi through the creation of a new service bean. OSGiService
annotation and
Service<T>
type are exclusive on injection point. If an injection point has both,
Weld-OSGi detects the problem and treats it as an error.
Direct injection with OSGiService
annotation and OSGiServiceBean
:
@Inject @OSGiService MyService service;
Such an injection point (an
OSGi service injection point) will match an unique Weld-OSGi OSGiServiceBean
.
For every different OSGi service injection point an unique OSGiServiceBean
is
generated by Weld-OSGi.
Injection using programmatic lookup with Service<T>
type and
OSGiServiceProviderBean
:
@Inject Service<MyService> services;
Such an injection point (an
OSGi service provider injection point) will match an unique Weld-OSGi
OSGiServiceProviderBean
.
For every different OSGi service provider injection point an unique
OSGiServiceProviderBean
is generated by Weld-OSGi.
OSGiService
annotated or a Service<T>
typed injection points are not eligible
to regular CDI injection.
OSGiServiceBean
injects an instance of the first service implementation matching the
injection point.
OSGiServiceProviderBean
injects a service provider (as a Service<T>
) for all
the service implementations matching the injection point.
Service provider allows to over-specify the matching service implementation set with additional OSGi service properties.
Service provider does not allow to subtype the matching service implementation set.
Service provider allows to instantiate the first service implementation matching the (possibly) over-specified injection point.
Service implementation are searched into the OSGi service registry, it may be:
A Weld-OSGi auto-published service
A regular OSGi service
Qualifier
annotations might be used for both specifying auto-published services and
service injection points. Such qualifiers should be seen as OSGi service properties, thus every set of
qualifiers corresponds to a set of OSGi service properties and so to a OSGi service LDAP filter.
However qualifiers keep a regular meaning for the CDI generated bean of an auto-published service class.
A qualifier will generate an OSGi service property for each of its valued element (an element with a default value is always considered valued) following these rules:
A valued element generates a property with this template:
decapitalized_qualifier_name.decapitalized_element_name=element_value.toString()
@MyQualifier(lang="EN", country="US")
will generate:
(myqualifier.lang=EN) (myqualifier.country=US)
A non valued element with a default value generates a property with this template:
decapitalized_qualifier_name.decapitalized_element_name=element_default_value.toString()
@MyQualifier(lang="EN")
will generate:
(myqualifier.lang=EN) (myqualifier.country=US) //admitting US is the default value for the element country
A non valued element with no default value generates a property with this template:
decapitalized_qualifier_name.decapitalized_element_name=*
@MyQualifier(lang="EN")
will generate:
(myqualifier.lang=EN) (myqualifier.country=*) //admitting there is no default value for the element country
A qualifier with no element generates a property with this template:
decapitalized_qualifier_name=*
@MyQualifier()
will generate:
(myqualifier=*)
Some qualifiers follow a specific processing:
OSGiService
qualifier will not generate any service property
Required
qualifier will not generate any service property
Default
qualifier will not generate any service property
Any
qualifier will not generate any service property
Filter
and Properties
qualifiers processing is described
below
Filter
qualifier allows to specify a OSGi LDAP filter for a OSGiServiceBean
or a OSGiServiceProducerBean
injection point.
A Filter
qualifier generates a "as it is" OSGi LDAP filter.
Properties
qualifier allows to specify OSGi LDAP properties for a auto-published service
class or for a OSGiServiceBean
or a OSGiServiceProducerBean
injection
point.
A Properties
qualifier generates a property for every one of its Property
annotation with this
template:
Property.name()=Property.value()
@Properties({@Property(name = "lang", value = "EN") @Property(name = "country", value = "US" })
will generate:
(lang=EN) (country=US)
If a Filter
qualifier is used on a bean class, Weld-OSGi detects the problem and treats it
as an error.
It is discouraged to use the Properties
qualifier on a bean that might be use as a regular
CDI bean.
An annotation annotated with a Filter
qualifier is considered similar to the
Filter
qualifier alone.
An annotation annotated with a Properties
qualifier is considered similar to the
Properties
qualifier alone.
Declaring a filter stereotype:
@Filter("name=1") public @Interface Name1 { }
@Inject @Name1 Service<MyService> named1Services;
is similar to:
@Inject @Filter("name=1") Service<MyService> named1Services;
Declaring a properties stereotype:
@Properties({@Property(name = "name", value = "1")}) public @Interface Name1 { }
@Publish @Name1 public class MyServiceImpl implements MyService { }
is similar to:
@Publish @Properties({@Property(name = "name", value = "1")}) public class MyServiceImpl implements MyService { }
Weld-OSGi processes all the OSGi LDAP properties (from regular qualifiers and Properties
qualifier) and provided OSGi LDAP filter (from Filter
qualifier) to generate a global OSGi
LDAP filter as:
With multiple OSGi LDAP properties and a provided OSGi LDAP filter
(& provided_ldap_filter (ldap_property_1) (ldap_property_2) ... (ldap_property_i) )
With multiple OSGi LDAP properties and no provided OSGi LDAP filter
(& (ldap_property_1) (ldap_property_2) ... (ldap_property_i) )
With one OSGi LDAP properties and a provided OSGi LDAP filter
(& provided_ldap_filter (ldap_property) )
With one OSGi LDAP properties and no provided OSGi LDAP filter
(ldap_property)
With no OSGi LDAP properties and a provided OSGi LDAP filter
provided_ldap_filter
With no OSGi LDAP properties and no provided OSGi LDAP filter
null
Weld-OSGi never ensure that the provided OSGi LDAP properties, neither the provided OSGi LDAP filter, neither the generated OSGi LDAP filter are valid.
On an auto-published service class:
@Publish @AnyQualifier public class MyServiceQualifiedImpl implements MyService { }
Will
generate an AnyQualifier
qualified regular CDI bean and register an OSGi service with
the property (anyqualifier=*).
On an OSGi service injection point:
@Inject @OSGiService @AnyQualifier MyService qualifiedService; @Inject @AnyQualifier Service<MyService> qualifiedServices;
Will
generate an OSGiServiceBean
and an OSGiServiceProducerBean
looking up for
OSGi services with the property (anyqualifier=*).
With an
OSGiServiceProducerBean
:
services.select(new AnnotationLiteral<AnyQualifier>() {}).get().deSomething();
Will over-specify the valid service implementation set to those matching the property (anyqualifier=*).
Using the special Properties
qualifier:
@Publish @Properties({@Property(name = "country", value = "US") @Property(name = "lang", value = "EN") }) public class MyServiceQualifiedImpl implements MyService { }
Will
generate an Properties(...)
qualified regular CDI bean and register an OSGi service
with the properties (lang=EN) and (country=US).
Using the special Filter
qualifier:
@Inject @OSGiService @Filter("(&(lang=EN)(country=US))") MyService qualifiedService; @Inject @Filter("(&(lang=EN)(country=US))") Service<MyService> qualifiedServices;
Will
generate an OSGiServiceBean
and an OSGiServiceProducerBean
looking up for
OSGi services matching the OSGi LDAP filter (&(lang=EN)(country=US)).
Weld-OSGi ensures that every OSGiService
annotated or Service<T>
typed
injection point matches an unique OSGiServiceBean
or
OSGiServiceProviderBean
.
Therefore, for every bean bundle Weld-OSGi:
Processes annotated types
Wraps every OSGiService
annotated injection point
OSGiService
annotated injection points are wrapped
as:
@Inject @OSGiService @Filter(Calculated_filter) Type var_name;
The global OSGi LDAP filter of the final Filter
qualifier is calculated from:
The original set of qualifiers (except OSGiService
and Filter
)
The OSGi LDAP filter value of the original Filter
qualifier
The set of properties of the original Filter
annotation
@Inject @OSGiService MyService qualifiedService;
will become:
@Inject @OSGiService @Filter("") MyService qualifiedService;
@Inject @OSGiService @AnyQualifier MyService qualifiedService;
will become:
@Inject @OSGiService @Filter("(anyqualifier=*)") MyService qualifiedService;
@Inject @OSGiService @AnyQualifier Service<MyService> qualifiedServices;
will generate an error.
@Inject @OSGiService @AnyQualifier @Filter(value="(lang=EN)",properties={"country=US","currency=*"}) MyService qualifiedService;
will become:
@Inject @OSGiService @Filter("(&(anyqualifier=*)(lang=EN)(country=US)(currency=*)) MyService qualifiedService;
An auto-published service instance is a CDI contextual instance, so:
The instance injected through a OSGiService
annotated or Service<T>
typed injection point might be a CDI contextual instance
The instance obtained through a regular OSGi service checkout might be a CDI contextual instance
In either cases Weld-OSGi ensures that the injected or obtained instance is contextual if no similar service is published using regular OSGi mechanism
It is discouraged to use regular OSGi service publication mechanisms in a Weld-OSGi application.
A CDI scope might be precised for every auto-published service class:
If no scope is provided Dependent
is assumed, granting a capacity similar to
regular OSGi service
Only one scope may be precised for every auto-published service class
The scope is shared by both generated regular CDI bean and OSGi service
The available scopes are: Dependent
, Singleton
,
ApplicationScoped
, SessionScoped
, ConversationScoped
and RequestScoped
Other scope or pseudo-scope may not be supported by Weld-OSGi
@Publish @ApplicationScoped public class MyServiceImpl implements MyService { @Override public void doSomething() { } }
A OSGiService
annotated or Service<T>
typed injection point might be
annotated Required
with no influence on this injection point
with influence on the Valid
and Invalid
events management in the
current bean bundle
OSGiServiceBean
and OSGiServiceProviderBeans
bean instances are dynamically
obtained as OSGi service instance.
No instance might be available at runtime due to OSGi dynamism, in such case a
OSGiServiceUnavailableException
is thrown with any OSGiServiceBean
method call
or the OSGiServiceProviderBeans
get
method call.