In many cases, assigning your custom service (service) a higher ranking convinces components to unbind from their current service and bind to yours. In other cases, components keep using their current service. Why is that? And how do you make components adopt your service? The component’s service reference policy option is the key to determining the service.
Here are the policy options:
greedy
: The component uses the matching, highest ranking service as soon
as it’s available.
reluctant
: The component uses the matching, highest ranking service
available in the following events:
- the component is (re)activated
- the component’s existing referenced service becomes unavailable
- the component’s reference is modified so that it no longer matches the existing bound service
In short, references with greedy policy options adopt your higher ranking service right away, while ones with reluctant policy options require particular events. What’s great is that Liferay DXP’s Configuration Admin lets you use configuration files (config files) or the API to swap in service reference changes on the fly. Here you’ll use a config file to reconfigure a service reference to use your custom service immediately.
This tutorial uses example modules override-my-service-reference
and
overriding-service-reference
to demonstrate reconfiguring a service reference,
binding the component to a different service. You can download the modules and
build them using Gradle (bundled with each module) or you can apply the tutorial
steps to configure your own customization. Executing gradlew jar
in each
example module root generates the module JAR to the build/libs
folder.
-
override-my-service-reference
(download): This module’s portlet componentOverrideMyServiceReferencePortlet
’s field_someService
references a service of typeSomeService
. The reference’s policy is static and reluctant. By default, it binds to an implementation calledSomeServiceImpl
. -
overriding-service-reference
(download): Provides a customSomeService
implementation calledCustomServiceImpl
. The module’s configuration file overridesOverrideMyServiceReferencePortlet
’sSomeService
reference so that it binds toCustomServiceImpl
.
You’re ready to reconfigure a component’s service reference to target your custom service.
Reconfiguring the Service Reference
Liferay DXP’s Configuration Admin lets you use configuration files to swap in service references on the fly.
-
Create a system configuration file named after the referencing component. Follow the name convention
[component].config
, replacing[component]
with the component name. The configuration file name for the example componentoverride.my.service.reference.portlet.OverrideMyServiceReferencePortlet
is:override.my.service.reference.portlet.OverrideMyServiceReferencePortlet.config
-
In the configuration file, add a reference target entry that filters on your custom service. Follow this format for the entry:
[reference].target=[filter]
Replace
[reference]
with the name of the reference you’re overriding. Replace[filter]
with service properties that filter on your custom service.This example filters on the
component.name
service property:_someService.target="(component.name\=overriding.service.reference.service.CustomServiceImpl)"
This example filters on the
service.vendor
service property:_someService.target="(service.vendor\=Acme, Inc.)"
-
Optionally, you can add a
cardinality.minimum
entry to specify the number of services the reference can use. Here’s the format:[reference].cardinality.minimum=[int]
Here’s an example cardinality minimum:
_someService.cardinality.minimum=1
-
Deploy the configuration by copying the configuration file into the folder
[Liferay_Home]/osgi/configs
.
Executing scr:info
on your component shows that the custom service is now
bound to the reference.
For example, executing
scr:info override.my.service.reference.portlet.OverrideMyServiceReferencePortlet
reports the following information:
...
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: (component.name=overriding.service.reference.CustomServiceImpl)
Bound to: 6841
Properties:
_defaultService.target = (component.name=overriding.service.reference.service.CustomServiceImpl)
component.id = 2398
component.name = overriding.service.reference.service.CustomServiceImpl
objectClass = [override.my.service.reference.service.api.SomeService]
service.bundleid = 525
service.id = 6841
service.scope = bundle
Component Configuration Properties:
_someService.target = (component.name=overriding.service.reference.service.CustomServiceImpl)
...
The example component’s _someService
reference targets the custom service
component overriding.service.reference.service.CustomServiceImpl
.
CustomServiceImpl
references default service SomeServiceImpl
to delegate
work to it.
Figure 1: Because the example component's service reference is overridden by the configuration file deployment, the portlet indicates it's calling the custom service.
Liferay DXP processed the configuration file and injected the service reference, which in turn bound the custom service to the referencing component!
Related Topics
OSGi Services and Dependency Injection with Declarative Services