Reputation:
Project description:
I have a simple demo project with OSGi. The Domain is a weather station which has multiple sensor types. Each sensors sends its data to the weather station. Via an API the data is exposed and visualized on a website via a plot.
Goal:
E.g: I currently have three different sensor types. One for measuring the wind speed, temperature and humidity. The weather station should have multiple wind sensor instances (Cardinality.MULTIPLE).
Status quo:
Currently I am solving this with creation of a WindSpeedSensor and a WindSpeedAdvancedSensor service. I already have implemented a custom command for Apache Karaf where I can send specific configuration commands to my service. So the sensor can be configured to generate measurements in a specific range.
Desired condition:
An optimal solution would be to start additional instances of WindSpeedSensor via Karaf commmand line. The should not be the need of artificial WindSpeedSensors to achieve the goal of multiple services for the WeatherStation class.
Question:
How can I achieve this? I am new to OSGi and declarative services and I am curious how experts in OSGi solve this. Thanks in advance for your time and feedback.
Upvotes: 0
Views: 331
Reputation: 2187
I've only used OSGi with Karaf so this might be somewhat different for other environments.
If you need OSGi Service for each configuration file you can setup such service with declarative service annotations for example like this.
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.metatype.annotations.Designate;
import com.example.service.config.ExampleServiceConfig;
@Component(
immediate = true, service = ExampleService.class,
configurationPolicy = ConfigurationPolicy.REQUIRE,
configurationPid = "com.example.service.ExampleService"
)
@Designate(ocd = ExampleServiceConfig.class, factory = true)
public class ExampleService {
@Activate
public void onServiceActivate(BundleContext context, ExampleServiceConfig config){
System.out.println(config.hello_message());
}
}
Then define type-safe configuration for the service for example like this:
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
@ObjectClassDefinition(name = "ExampleService Configuration")
public @interface ExampleServiceConfig {
String hello_message() default "hello world";
String osgi_jndi_service_name() default "unique.service.name";
}
Since singleton configurations use file names like <configurationPid>.cfg
factory configurations use format <configurationPid>-<InstanceName>.cfg
so to create two instances of ExampleService
above you can create for example following configurations:
com.example.service.ExampleService-InstanceA.cfg
hello.message=Hello from Instance A
osgi.jdni.service.name=InstanceA
com.example.service.ExampleService-InstanceB.cfg
hello.message=Hello from Instance B
osgi.jdni.service.name=InstanceB
At least in Karaf this will create two instances of ExampleService and two configurations with unique guid of some sort (instead of Instance name). To refer to specific service instance you can use target property from reference annotation.
@Reference(
target = "(osgi.jdni.service.name=InstanceA)"
)
ExampleService exampleService;
Upvotes: 1
Reputation: 9384
You can use Factory Configurations (see https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html#service.component-deployment). For each configuration under the factory pid, DS will create a component configuration. This allows one component to be created multiple times based upon factory configurations in Configuration Admin.
Upvotes: 0