In an OSGi @Component Portlet, I can access a Liferay local service using OSGi declarative services:
@Reference
private MyExampleLocalService myExampleService;
Beyond injecting the service into my portlet, @Reference also ensures that Liferay will not start my portlet until MyExampleLocalService is available.
In Liferay, I can also deploy portlets in a WAR without @Component or access to declarative services. I know I can access services there using the static utilities like MyExampleLocalServiceUtil.getService(), but this puts my application at risk for a NullPointerException since my portlet may be started before MyExampleLocalService is available.
I’ve tried using @Inject and/or @Reference to inject the service, but that doesn’t work since this is not a @Component portlet. @Inject throws an exception and @Reference doesn’t have any effect.
Liferay’s local services are all OSGi services, so if at all possible, you should obtain your service dependencies via OSGi
@Referenceor OSGi + CDI@Reference@Inject(works for Portlet 3.0 portlets). With those annotations, OSGi will manage your portlet, starting the portlet and injecting the services once they become available and shutting down the portlet as services become unavailable.1 However, if you aren’t creating a CDI or OSGi based portlet, you cannot use these preferred methods. For exampl, legacy Portlet 2.0 portlets deployed in a WAR and Spring Portlets cannot utilize declarative services.Instead these portlets should order to access Liferay local services in a non-OSGi portlet, you should use OSGi
ServiceTrackers.ServiceTrackerhaswaitForServiceandgetServicemethods for obtaining services. If you want to wait for the service (with a timeout), you can callwaitForServiceany time after portlet initialization has completed. Otherwise you can callgetService()any time to obtain the service ornullif the service isn’t available.Do not call
ServiceTracker#waitForServicein your portlet’sinitmethod! This can cause an intermittent deadlock since Liferay only deploys one bundle/app at a time. If your portlet is deploying and waiting for a service ininit, it can prevent the dependency service bundle from completing deployment. But the portlet will never finish deploying because it needs the dependency. Eventually the waiting portlet will time out, but I think there may also be bugs around this because the deadlock appears to persist even after the portlet times out of waiting.Here’s some example code to obtain and use a service:
This method for obtaining services should work for any non-OSGi Liferay portlets such as Portlet 2.0 portlets, Spring portlets, and JSF portlets (with JSF you might prefer to obtain the
BundleContextfrom theExternalContext). This method works for any OSGi services, not just Liferay’s local services.