Pierre De Rop created FELIX-5939:
------------------------------------
Summary: DM annotations enhancements
Key: FELIX-5939
URL: https://issues.apache.org/jira/browse/FELIX-5939
Project: Felix
Issue Type: Improvement
Components: Dependency Manager, Dependency Manager Annotations
Affects Versions: org.apache.felix.dependencymanager-r11
Reporter: Pierre De Rop
Assignee: Pierre De Rop
Fix For: org.apache.felix.dependencymanager-r12
Some DM annotations improvements have been done regarding DM Annotation in this
github project: [https://github.com/pderop/dm.enhanced,] and the intent is to
merge the improvements to the felix trunk.
Essentially, the following DM annotations enhancements and modifications have
been done:
* in OSGi R7, declarative service now provides a @ComponentPropertyType
annotation that can be used to defined user defined property type annotations.
Now this annotation is used by other R7 libraries, like jaxrs whiteboard R7
API. So the DM annotation scanner has been enhanced for the support of the DS
@ComponentPropertyType, allowing you to reuse user defined annotations from
other r7 libraries (whiteboad, etc ...). The dm annotation plugin has been
enhanced by reusing some part of the ds annotation scanner from bndlib, which
is full of reusable useful code which has been applied to dm (scanning of
property types, PREFIX_, etc ...). For consistency api reasons, a new
@PropertyType annotation has also been added to the DM annotation API: this
annotation has the same semantics has the DS @ComponentPropertyType annotations.
* allow ServiceDependency to auto detect the service type when the annotation
is applied on a collection class field
* removed FactoryComponentAdapterService (some attributes have been added in
the Component annotation in order to declare factory pid components with the
@Component annotation)
* removed some old annotations / attributes. The attributes and annotations
related to metatype have been removed since you can now use the standard
metatype annotations. if users need to use old version, then the previous old
4.2.1 annotations can be used, because the dm runtime is compatible with old
and new annotations version.
* removed "dereference" attribute in ServiceDependencyAnnotation, because we
can now infer if the service dependency callbacks accepts a ServiceReference or
a ServiceObjects parameter
Since some incompatible changes have been made, the major version of the
annotation bundle has been bumped to 5.0.0.
*User defined property types examples:*
So far, you could define component service properties using DM @Property
annotation, and component configuration could be declared as user defined
interfaces. You can now declare user-defined annotations which can be used to
specify both service properties and component configuration. It means that
instead of declaring service properties using @Property annotation, you can now
use your own annotations (which must be annotated with the new @PropertyType
annotation, or using the standard @ComponentPropertyType annotation.
For example, let’s assume your write an OSGi r7 jaxrs servlet context which
needs the two following service properties:
{code:java}
osgi.http.whiteboard.context.name
osgi.http.whiteboard.context.path
{code}
Then you can first define your own annotation (but you could also reuse the
default annotations provided by the new jaxrs whiteboard r7 api, from the
org.osgi.service.jaxrs.whiteboard.propertytypes package):
{code:java}
import org.apache.felix.dependencymanager.annotation.PropertyType;
@PropertyType
@interface ServletContext {
String osgi_http_whiteboard_context_name() default AppServletContext.NAME;
String osgi_http_whiteboard_context_path();
}
{code}
In the above, the underscore is mapped to ".", and you can apply the above
annotation on top of your component like this:
{code:java}
@Component
@ServletContext(osgi_http_whiteboard_context_path="/game")
public class AppServletContext extends ServletContextHelper {
}
\{code}
You can also use configuration admin service in order to override the default
service properties:
{code:java}
@Component
@ServletContext(osgi_http_whiteboard_context_path="/game")
public class AppServletContext extends ServletContextHelper {
@ConfigurationDependency(propagate=true, pid="my.pid")
void updated(ServletContext cnf) {
// if some properties are not present in the configuration, then the
ones used in the
// annotation will be used.
// The configuration admin properties, if defined, will override the
default configurations
// defined in the annotations
}
}
\{code}
You can also define multiple property type annotations, and possibly single
valued annotation, like it is the case with standard r7 DS. In this case, you
can use the standard R7 PREFIX_ constants in order to specify the property
prefix, and the property name will be derived from the single valued annotation
(using camel case convention):
{code:java}
@PropertyType
@interface ContextName {
// will map to "osgi.http.whiteboard.context.name" property name
String PREFIX_="osgi.http.whiteboard.";
String value();
}
@PropertyType
@interface ContextPath {
// will map to "osgi.http.whiteboard.context.path" property name
String PREFIX_="osgi.http.whiteboard.";
String value();
}
@Component
@ContextName(AppServletContext.NAME)
@ContextPath("/game")
public class AppServletContext extends ServletContextHelper {
}
\{code}
Now , the following is the same example as above, but also using configuration
admin service in order to override default service properties: Here, as in OSGi
r7 declarative service, you can define a callback method which accepts as
arguments all (or some of) the defined property types:
{code:java}
@Component
@ContextName(AppServletContext.NAME)
@ContextPath("/game")
public class AppServletContext extends ServletContextHelper {
@ConfigurationDependency(propagate=true, pid="my.pid")
void updated(ContextName ctxName, ContextPath ctxPath) {
// if some properties are not present in the configuration, then the
ones used in the annotation will be used.
// The configuration admin properties, if defined, will override the
default configurations defined in the annotations
}
}
\{code}
The following is the same example as above, but this time the configuration
callback can also define a Dictionary in the first argument (in case you want
to also get the raw configuration dictionary:
{code:java}
@Component
@ContextName(AppServletContext.NAME)
@ContextPath("/game")
public class AppServletContext extends ServletContextHelper {
@ConfigurationDependency(propagate=true, pid="my.pid")
void updated(Dictionary<String, Object> rawConfig, ContextName ctxName) {
// if some properties are not present in the configuration, then the
ones used in the annotation will be used.
// The configuration admin properties, if defined, will override the
default configurations defined in the annotations
}
}
\{code}
Empty Marker annotations can also be used: when you define an empty annotation,
it will be mapped to a java.lang.Boolean property type with Boolean.TRUE value.
For example, the following component will be registered with
"osgi.jaxrs.resource" service property with Boolean.TRUE value:
{code:java}
@PropertyType
@interface JaxrsResource {
// will map to "osgi.jaxrs.resource" property name
String PREFIX_="osgi.";
}
@Component(provides = MyResource.class)
@JaxrsResource
public class MyResource {
@Path(“foo”)
@GET
public void getFoo() {
...
}
}
\{code}
User defined property types can also be applied on factory components, for
example, in the following, the service properties are declared using the
user-defined annotations (they will be overriden from the factory
configuratinn, if present in the config):
{code:java}
@Component(factoryPid="my.factory.pid")
@ContextName(AppServletContext.NAME)
@ContextPath("/game")
class Hello implements HelloService {
void updated(ContextName ctxName, ContextPath ctxPath) {
// Configure or reconfigure our component. the default service
// properties will be overriden by the factory configuration (if the
// service properties are defined in the config)
}
}
{code}
*Not backward compatible annotation changes:*
This sections describes what has been removed in the annotation api:
* removed FactoryConfigurationAdapterService annotation, which was too
verbose. when you need to define some factory pid component, just reuse the
@Component annotation and declare the new factoryPid/propagate/updated
attributes that have been added in the @Component annotation
* removed PropertyMetadata annotation: it was related to metatypes, but as of
today, osgi metatypes can be defined using standard metatype annotations. No
need to support this anymore.
* removed ResourceAdapterService and ResourceDependency annotations because it
was needed to depend on some classes from the dependency manager API. The DM
Api should be used directly.
* removed the following attributes from the Component annotation:
-- FACTORY_NAME
-- FACTORY_INSTANCE
-- factorySet
-- factoryMethod
These attributes were used to be able to create component instances multiple
times. Now, simply use factoryPid Component attribute and use standard
Configuration Admin in order to instantiate multiple instances of a given
service (using factory configuration).
* removed @PropertyMetaData annotation, which was related to osgi metatype.
now, you can use standard metatype annotations.
Since some incompatible changes have been made, the major version of the
annotation bundle has been bumped to 5.0.0, but the dm runtime is still
compatible with previous annotations.
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)