The Greedy Policy Option sample provides two portlets that can be added to a Liferay DXP page: Greedy Portlet and Reluctant Portlet.
These two portlets do not provide anything useful out-of-the-box. They are, however, very effective at demonstrating the ability to reference services using greedy and reluctant policy options. You’ll learn how to do this later.
What API(s) and/or code components does this sample highlight?
This sample provides two modules referencing services using greedy and reluctant policy options.
-
service-reference
: Provides an OSGi service interface calledSomeService
, a default implementation of it, and portlets that refer to service instances. One portlet refers to new higher ranked instances of the service automatically. The other portlet is reluctant to use new higher ranked instances and continues to use its bound service. The reluctant portlet can, however, be configured dynamically to use other service instances. -
higher-ranked-service
: Has a higher rankedSomeService
implementation.
Here are each module’s file structures:
-
service-reference/
bnd.bnd
configs/
com.liferay.blade.reluctant.vs.greedy.portlet.portlet.ReluctantPortlet.config
→ReluctantPortlet
configuration file
src/main/java/com/liferay/blade/reluctant/vs/greedy/portlet/
api/
SomeService.java
→ Service interface
constants/
ReluctantPortletVsGreedyPortletKeys.java
→ Portlet constants
portlet/
DefaultSomeService.java
→ Zero ranked service implementationGreedyPortlet.java
→ Refers toSomeService
using a greedy service policy optionReluctantPortletPortlet.java
→ Refers toSomeService
using a reluctant service policy option by default.
-
higher-ranked-service/
bnd.bnd
src/main/java/com/liferay/blade/reluctant/vs/greedy/svc/HigherRankedService.java
→ Service implementation with service ranking value of100
How does this sample leverage the API(s) and/or code component?
Here are the things you can learn using the sample modules:
Let’s walk through the demonstration.
Binding a newly deployed component’s service reference to the highest ranking service instance that’s available initially
On deploying a component that references a service, it binds to the highest ranking service instance that matches its target filter (if specified).
The portlet classes refer to instances of interface SomeService
. The
doSomething
method returns a String
.
public interface SomeService {
public String doSomething();
}
Class DefaultSomeService
implements SomeService
. Its doSomething
method
returns the String
“I am Default!”.
@Component
public class DefaultSomeService implements SomeService {
@Override
public String doSomething() {
return "I am Default!";
}
}
When module’s portlets refer to DefaultSomeService
, they display the String
“I am Default!”.
The ReluctantPortlet
class’s SomeService
reference’s policy option is the
default: static and reluctant. This policy option keeps the reference bound to
its current service instance unless that instance stops or the reference is
reconfigured to refer to a different service instance.
@Component(
immediate = true,
property = {
"com.liferay.portlet.display-category=category.sample",
"com.liferay.portlet.instanceable=true",
"javax.portlet.display-name=Reluctant Portlet",
"javax.portlet.init-param.template-path=/",
"javax.portlet.init-param.view-template=/view.jsp",
"javax.portlet.name=" + ReluctantVsGreedyPortletKeys.Reluctant,
"javax.portlet.resource-bundle=content.Language",
"javax.portlet.security-role-ref=power-user,user"
},
service = Portlet.class
)
public class ReluctantPortlet extends MVCPortlet {
@Override
public void doView(
RenderRequest renderRequest, RenderResponse renderResponse)
throws IOException, PortletException {
renderRequest.setAttribute("doSomething", _someService.doSomething());
super.doView(renderRequest, renderResponse);
}
@Reference
private SomeService _someService;
}
The ReluctantPortlet
’s method doView
sets render request attribute
doSomething
to the value returned from the SomeService
instance’s
doSomething
method (e.g., DefaultService
returns “I am default!”).
The GreedyPortlet
class is similar to ReluctantPortlet
, except its
SomeService
reference’s policy option is static and greedy (i.e.,
ReferencePolicyOption.GREEDY
).
public class GreedyPortlet extends MVCPortlet {
@Override
public void doView(
RenderRequest renderRequest, RenderResponse renderResponse)
throws IOException, PortletException {
renderRequest.setAttribute("doSomething", _someService.doSomething());
super.doView(renderRequest, renderResponse);
}
@Reference (policyOption = ReferencePolicyOption.GREEDY)
private SomeService _someService;
}
The greedy policy option lets the component switch to using a higher ranked
SomeService
instance if one becomes active in the system. The section
Deploying a module with a higher ranked service instance for binding to greedy references immediately
demonstrates this portlet switching to a higher ranked service.
It’s time to see this module’s portlets and service in action.
-
Stop module
higher-ranked-service
if it’s active. -
Deploy the
service-reference
module. -
Add the Reluctant Portlet from the Add → Widgets → Sample category to a site page.
The portlet displays the message “SomeService says I am Default!”–whose latter part comes from the render request attribute set by the
DefaultService
instance. -
Add the Greedy Portlet from the Add → Widgets → Sample category to a site page.
The portlet displays the message “SomeService says I am better, use me!”. Both portlets are referencing a
DefaultService
instance.
Since DefaultService
is the only active SomeService
instance in the system,
the portlets refer to it for their SomeService
fields.
The DefaultService
and portlets Reluctant Portlet and Greedy Portlet are
active. Let’s activate a higher ranked SomeService
instance and see how the
portlets react to it.
Deploying a module with a higher ranked service instance for binding to greedy references immediately
Module higher-ranked-service
provides a SomeService
implementation called
HigherRankedService
. HigherRankedService
’s service ranking is 100
–that’s
100
more than DefaultService
’s ranking 0
. Its doSomething
method returns
the String
“I am better, use me!”.
- Deploy the
higher-ranked-service
module. - Refresh your page that has the portlets Reluctant Portlet and Greedy Portlet.
Reluctant Portlet continues displaying message “SomeService says I am better,
use me!”. It’s “reluctant” to unbind from the DefaultService
instance and
bind to the newly activated HigherRankedService
service.
Greedy Portlet displays a new message “SomeService says I am better, use me!”.
The part of the message “I am better, use me!” comes from the
HigherRankedService
instance to which it refers.
Next, learn how to bind the Reluctant Portlet to a HigherRankedService
instance.
Configuring a component to reference a different service instance dynamically
The Reluctant Portlet is currently bound to a DefaultService
instance. It’s
“reluctant” to unbind from it and bind to a different service. OSGi
Configuration Administration lets you reconfigure service references to filter
on and bind to different service instances.
The service-reference
module’s configuration files and
com.liferay.blade.reluctant.vs.greedy.portlet.portlet.ReluctantPortlet.config
and com.liferay.blade.reluctant.vs.greedy.portlet.portlet.ReluctantPortlet.cfg
configure the ReluctantPortlet
component to use a HigherRankedService
instance.
_someService.target=(component.name=com.liferay.blade.reluctant.vs.greedy.service.HigherRankedService)
The service configuration filters on a service whose component.name
is
com.liferay.blade.reluctant.vs.greedy.service.HigherRankedService
.
Note: For deploying to Liferay DXP 7.2, use file with suffix .config
. For
earlier versions (i.e., Liferay DXP 7.0 Fix Packs earlier than Fix Pack 8 and
Liferay CE Portal 7.0 GA3 or earlier), use the file with suffix .cfg
.
Here are the steps to reconfigure ReluctantPortlet
to use
HigherRankedService
:
- Copy the configuration file to
[Liferay-Home]/osgi/configs
. - Refresh your browser.
Reluctant Portlet displays a new message “SomeService says I am better, use me!”.
Reluctant Portlet is using HigherRankedService
instance instead of a
DefaultService
instance. You’ve configured Reluctant Portlet to use a
HigherRankedService
instance!
Where Is This Sample?
There are three different versions of this sample, each built with a different build tool: