Field injection, type safe configuration, and more new goodies in Declarative Services

Post on 07-Apr-2017

1.065 views 0 download

Transcript of Field injection, type safe configuration, and more new goodies in Declarative Services

Field injection, type safe configuration, and more new goodies in Declarative

ServicesBJ Hargrave, IBM

a ComponentImpl

a Service Impl

ServiceComponentRuntime Impl

a Servicea ComponentInstance

ComponentDescription

a ComponentConfguration

registered service

tracksdependencies

declares component

created by

controls 0..n

0..n

0..n

references

1..n1

ConfigurationAdmin

0..n

1

0..n

1

1

<<service>>Service ComponentRuntime

Declarative Services• A declarative model for publishing and

consuming OSGi services

• Introduced in Release 4 in 2005, it greatly simplified programming OSGi services

• Service Component Runtime, SCR, is the runtime which implements the spec and manages the service components

Service Component

• A Java class which can optionally be registered as a service and can optionally use services

• Described by XML in the bundle which is processed at runtime by SCR

<?xml version="1.0" encoding="UTF-8"?><scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"

name="example.provider.ExampleImpl" activate="activate"> <implementation class="example.provider.ExampleImpl"/> <service> <provide interface="example.api.Example"/> </service> <reference name="Log" interface="org.osgi.service.log.LogService" bind="setLog"/></scr:component>

Service Component using annotations

• But who wants to write XML?

• So DS 1.2 added support for programming with annotations

• Tools, like , process the annotations into the XML used by SCR at runtime

@Componentpublic class ExampleImpl implements Example {

private Map<String, Object> properties;private LogService log;@Activatevoid activate(Map<String, Object> map) {

properties = map;}@Overridepublic boolean say(String message) {

log.log((int) properties.get("loglevel"), message);return false;

}@Referencevoid setLog(LogService log) {

this.log = log;}

}

Pretty cool!

So what is new in Declarative Services 1.3?

• Field Injection

• Type Safe Configuration with MetaType integration

• Configuration Admin integration improvements

• Multiple PIDs

• Introspection

• And more small improvements we don’t have time to discuss today

• See 112.17 “Changes” in the DS 1.3 spec

Field Injection

Injection

• Method injection

• Constructor injection

• Field injection

@Referencevoid setLog(LogService log) {

this.log = log;}

Field Injection

• Scalar cardinality

• Static policy

• Dynamic policy

@Referenceprivate Example target;

@Referenceprivate volatile Example target;

https://github.com/bjhargrave/osgice2015/blob/master/1ScalarFieldRef/src/example/command/ExampleCommand.java#L17

Field Injection

• Multiple cardinality

• Service type from generic signature

• SCR-managed collection implementation

• Static policy

• Dynamic policy

@Referenceprivate List<Example> targets;

https://github.com/bjhargrave/osgice2015/blob/master/2MultipleFieldRef/src/example/command/ExampleCommand.java#L20

@Referenceprivate volatile List<Example> targets;

Field Injection

• User managed collection

• Can also inject fields of types related to services and collections of those types

@Reference(policy = ReferencePolicy.DYNAMIC)private final List<Example> targets = new CopyOnWriteArrayList<>();

@ReferenceServiceReference<Example> sr;@ReferenceComponentServiceObjects<Example> so;@Reference(service=Example.class)Map<String,Object> props;@ReferenceMap.Entry<Map<String,Object>,Example> tuple;

Type Safe Configuration

Component Properties

• Component properties come from

• Component description

• Configuration Admin configuration

• ComponentFactory.newInstance

<property name=“myport" type="Integer" value="8080"/>

Dictionary<String, Object> props = new Hashtable<>();props.put("myport", Integer.valueOf(8081));cm.getConfiguration("Example").update(props);

Dictionary<String, Object> props = new Hashtable<>();props.put("myport", Integer.valueOf(8082));cf.newInstance(props);

Getting the property values

• Activate method

• But what if the configuration value for myport was of type String? Or type Long?

• Type safety failure in your code

• You also need to handle the case where the property is not set

private int myport;@Activatevoid activate(Map<String, Object> props) {myport = props.containsKey("myport") ? ((Integer) props.get("myport")).intValue() : 8080;

}

Component Property Types

• Define and use your component properties in a type safe manner using annotations!

@interface Props {int myport() default 8080;

}@Componentpublic class ExampleImpl implements Example {private int myport;@Activatevoid activate(Props props) {myport = props.myport();

}}

https://github.com/bjhargrave/osgice2015/blob/master/3TypeSafeConfig/src/example/provider/ExampleImpl.java#L14

Type Safe Configuration and MetaType

Component Property Types integrate with MetaType Service

• Use the new MetaType annotations to define metatype resources and associate them with your component

https://github.com/bjhargrave/osgice2015/blob/master/4TypeSafeConfigWithMetatype/src/example/provider/ExampleImpl.java#L14

@ObjectClassDefinition@interface Props {int myport() default 8080;

}@Designate(ocd=Props.class)@Componentpublic class ExampleImpl implements Example {private int myport;@Activatevoid activate(Props props) {myport = props.myport();

Multiple Configurations

Component properties from Configurations

• DS integrates with Configuration Admin and will get component properties from a configuration with the configuration pid of the component

@ObjectClassDefinition(pid = "Example")@interface Name {String name() default "Default Name";

}@Component(configurationPid = "Example")public class ExampleImpl implements Example {private String name;@Activatevoid activate(Name name) {this.name = name.name();

}}

Sometimes we need to use multiple configurations

• A component may want to use a “system” configuration as well as a specific configuration

@ObjectClassDefinition(pid = “System")@interface Name {

String name() default "Default Name";}@ObjectClassDefinition(pid = "Example")@interface Words {

String hello() default "Hello";String goodbye() default "Goodbye";

}@Component(configurationPid = {“System", "Example"})public class ExampleImpl implements Example {

private String name;private Words words;@Activatevoid activate(Name name, Words words) {

this.name = name.name();this.words = words;

}https://github.com/bjhargrave/osgice2015/blob/master/6MultiplePIDs/src/example/provider/ExampleImpl.java#L13

Introspection

Introspecting the Service Components

• SCR now registers a ServiceComponentRuntime service which provides APIs to introspect the service components managed by SCR

public interface ServiceComponentRuntime {Collection<ComponentDescriptionDTO> getComponentDescriptionDTOs(Bundle... bundles);ComponentDescriptionDTO getComponentDescriptionDTO(Bundle bundle, String name);Collection<ComponentConfigurationDTO> getComponentConfigurationDTOs(ComponentDescriptionDTO

description);boolean isComponentEnabled(ComponentDescriptionDTO description);Promise<Void> enableComponent(ComponentDescriptionDTO description);Promise<Void> disableComponent(ComponentDescriptionDTO description);

}

https://github.com/bjhargrave/osgice2015/blob/master/5Introspection/src/example/command/ExampleCommand.java#L25

SCR Data Transfer Objects

• DTOs are defined for

• Component descriptions - ComponentDescriptionDTO

• Component configurations - ComponentConfigurationDTO

• References - ReferenceDTO, SatisfiedReferenceDTO, UnsatisfiedReferenceDTO

Why isn’t my component active?

• You can use the DTOs to figure out why

• It might be missing a required configuration or have an unsatisfied reference to a service

public class ComponentConfigurationDTO extends DTO {public static final int UNSATISFIED_CONFIGURATION= 1;public static final int UNSATISFIED_REFERENCE = 2;public static final int SATISFIED = 4;public static final int ACTIVE = 8;public ComponentDescriptionDTO description;public int state;public long id;public Map<String, Object> properties;public SatisfiedReferenceDTO[] satisfiedReferences;public UnsatisfiedReferenceDTO[] unsatisfiedReferences;

}

Fin https://github.com/bjhargrave/osgice2015