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_filterWith no OSGi LDAP properties and no provided OSGi LDAP filter
nullWeld-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.