Creating and injecting a custom service in place of an existing service requires three things:
- Understanding the service interface
- The existing service
- The references to the service
Your custom service must implement the service interface, match references you want, and might need to invoke the existing service.
Getting components to adopt your custom service immediately can require reconfiguring their references to the service. Here you’ll flesh out service details to make these decisions.
Gathering Information on a Service
-
Since component service references are extension points, start with following the tutorial Finding Extension Points to determine the service you want to override and components that use that service.
-
Once you know the service and components that use it, use Gogo Shell’s Service Component Runtime (SCR) to inspect the components and get the service and reference details. The Gogo Shell command
scr:info [componentName]
lists the component’s attributes and service references.
Here’s an example scr:info
command and results (abbreviated with ...
) that
describe component override.my.service.reference.OverrideMyServiceReference
(from sample module
override-my-service-reference)
and its reference to a service of type
override.my.service.reference.service.api.SomeService
:
> scr:info override.my.service.reference.OverrideMyServiceReference
...
Component Description:
Name: override.my.service.reference.portlet.OverrideMyServiceReferencePortlet
...
Reference: _someService
Interface Name: override.my.service.reference.service.api.SomeService
Cardinality: 1..1
Policy: static
Policy option: reluctant
Reference Scope: bundle
...
Component Configuration:
ComponentId: 2399
State: active
SatisfiedReference: _someService
Target: null
Bound to: 6840
Properties:
component.id = 2400
component.name = override.my.service.reference.service.impl.SomeServiceImpl
objectClass = [override.my.service.reference.service.api.SomeService]
service.bundleid = 524
service.id = 6840
service.scope = bundle
...
The scr:info
results, like the ones above, contain information relevant to
injecting a custom service. Here’s what you’ll do with the information:
Start with the service interface.
Step 1: Copy the Service Interface Name
The reference’s Interface Name is the service interface’s fully qualified name.
...
Reference: _someService
Interface Name: override.my.service.reference.service.api.SomeService
...
Copy and save the interface name, because it’s the type your custom service must implement.
Step 2: Copy the Existing Service Name
If you want to invoke the existing service along with your custom service, get the existing service name.
The src:info
result’s Component Configuration section lists the existing
service’s fully qualified name. For example, the
OverrideMyServiceReferencePortlet
component’s references _someService
is
bound to a service component whose fully qualified name is
override.my.service.reference.service.impl.SomeServiceImpl
.
Component Configuration:
...
SatisfiedReference: _someService
...
Bound to: 6840
Properties:
...
component.name = override.my.service.reference.service.impl.SomeServiceImpl
Copy the component.name
so you can reference the service in your
custom service.
Here’s an example of referencing the service above.
@Reference (
target = "(component.name=override.my.service.reference.service.impl.SomeServiceImpl)"
)
private SomeService _defaultService;
Step 3: Gather Reference Configuration Details (if reconfiguration is needed)
The service reference’s policy and policy option determine a component’s conditions for adopting a particular service.
-
If the reference’s policy option is
greedy
, it binds to the matching, highest ranking service right away. The reference need not be reconfigured to adopt your service. -
If policy is
static
and its policy option isreluctant
, however, the component requires one of the following conditions to switch from using the existing service it’s referencing to using the matching, highest ranking service (i.e., you’ll rank your custom service highest):- The component is reactivated
- The component’s existing referenced service is unavailable
- The component’s reference is modified so that it does not match the existing service but matches your service
Reconfiguring the reference can be the quickest way for the component to adopt a new service.
Gather these details:
-
Component name: Find this at Component Description → Name. For example,
Component Description: Name: override.my.service.reference.portlet.OverrideMyServiceReferencePortlet ...
-
Reference name: The Reference value (e.g.,
Reference: _someService
). -
Cardinality: Number of service instances the reference can bind to.
After creating your custom service (next), you’ll use the details you collected here to configure the component to use your custom service.
Congratulations on getting the details required for overriding the OSGi service!
Related Topics
OSGi Services and Dependency Injection with Declarative Services