]> source.dussan.org Git - vaadin-framework.git/commitdiff
Enable Declarative Services in OSGi portlet UI (#9879)
authorMirjan Merruko <mirjan@vaadin.com>
Tue, 29 Aug 2017 09:16:14 +0000 (12:16 +0300)
committerHenri Sara <henri.sara@gmail.com>
Tue, 29 Aug 2017 09:16:14 +0000 (12:16 +0300)
If the UI scope is not prototype, show a warning that declarative services are not available in the UI.

Fixes #9589

documentation/portal/portal-osgi.asciidoc
liferay-integration/src/main/java/com/vaadin/osgi/liferay/OsgiUIProvider.java
liferay-integration/src/main/java/com/vaadin/osgi/liferay/PortletUIServiceTrackerCustomizer.java
liferay-integration/src/main/java/com/vaadin/osgi/liferay/VaadinPortletProvider.java

index 0f31698f7e9c8b2da04be1f9119d73ce22d4ad8e..3381989d568ac7a4476c381765b1268b0a4a6bf7 100644 (file)
@@ -8,7 +8,7 @@ layout: page
 = OSGi Portlets on Liferay 7
 
 Lifeary 7 supports modular portlet development using OSGi, and enables e.g.
-using multiple different Vaadin versions in different portlets on a page. 
+using multiple different Vaadin versions in different portlets on a page.
 
 For general OSGi considerations with Vaadin Framework such as packaging and
 bundle manifests, and how to publish static resources such as themes and
@@ -31,7 +31,7 @@ and configure it to use the correct static resources.
 ----
 @Theme(MyTheme.THEME_NAME)
 @VaadinLiferayPortletConfiguration(name = "Vaadin.Tutorial.1", displayName = "Vaadin Tutorial App")
-@Component(service = UI.class)
+@Component(service = UI.class, scope = ServiceScope.PROTOTYPE)
 public class MyUI extends UI {
   ...
 }
@@ -43,6 +43,15 @@ property files that plain JSR-362 portlets require.
 Alternatively, the property [literal]#com.vaadin.osgi.liferay.portlet-ui=true#
 can be used when publishing a UI as an OSGi service to publish the UI as a portlet.
 
+The scope of the service should be set to [literal]#ServiceScope.PROTOTYPE#, as new instances
+of the UI will be needed. When this scope set, declarative services annotations can
+be used to get references to other services within a UI instance.
+
+This is not an absolute requirement if you are not using other declarative services
+annotations in your UI besides the [interfacename]#@Component#. If the scope is not
+set to prototype a warning will be logged and the constructor of the UI will be used
+when new instances are needed.
+
 [source, java]
 ----
 @Theme(MyTheme.THEME_NAME)
@@ -51,7 +60,8 @@ can be used when publishing a UI as an OSGi service to publish the UI as a portl
         "javax.portlet.name=my.vaadin.app.app.1.0.0",
         "javax.portlet.display-name=Tutorial Portlet",
         "javax.portlet.security-role-ref=power-user,user",
-        "com.vaadin.osgi.liferay.portlet-ui=true"})
+        "com.vaadin.osgi.liferay.portlet-ui=true"},
+        scope = ServiceScope.PROTOTYPE)
 public class MyUI extends UI {
   ...
 }
index 072dcbdc02cd91b0ea2fecd6d37fa401e7b9bf67..bdf50aa0d1a5333569df012c4a6aa7c5869432d7 100644 (file)
  */
 package com.vaadin.osgi.liferay;
 
+import java.util.Optional;
+
+import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceObjects;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
 
 import com.vaadin.server.UIClassSelectionEvent;
+import com.vaadin.server.UICreateEvent;
 import com.vaadin.server.UIProvider;
 import com.vaadin.ui.UI;
 
@@ -34,12 +40,26 @@ import com.vaadin.ui.UI;
 @SuppressWarnings("serial")
 public class OsgiUIProvider extends UIProvider {
     private Class<UI> uiClass;
+    private ServiceObjects<UI> serviceObjects;
+    private boolean prototype;
+    private Optional<LogService> logService;
 
     @SuppressWarnings("unchecked")
-    public OsgiUIProvider(ServiceObjects<UI> serviceObjects) {
+    public OsgiUIProvider(ServiceObjects<UI> serviceObjects,
+            Optional<LogService> logService) {
         super();
+        this.serviceObjects = serviceObjects;
+        this.logService = logService;
+
         UI ui = serviceObjects.getService();
+
+        ServiceReference<UI> reference = serviceObjects.getServiceReference();
+        Object property = reference.getProperty(Constants.SERVICE_SCOPE);
+
+        prototype = Constants.SCOPE_PROTOTYPE.equals(property);
+
         uiClass = (Class<UI>) ui.getClass();
+
         serviceObjects.ungetService(ui);
     }
 
@@ -48,6 +68,22 @@ public class OsgiUIProvider extends UIProvider {
         return uiClass;
     }
 
+    @Override
+    public UI createInstance(UICreateEvent event) {
+        if (prototype) {
+            UI ui = serviceObjects.getService();
+            ui.addDetachListener(e -> {
+                serviceObjects.ungetService(ui);
+            });
+            return ui;
+        }
+        logService.ifPresent(log -> {
+            log.log(LogService.LOG_WARNING,
+                    "UI services should have a prototype scope! Creating UI instance using the default constructor!");
+        });
+        return super.createInstance(event);
+    }
+
     public String getDefaultPortletName() {
         return uiClass.getName();
     }
index 077730d2a85f4ba829face5ee21bf14838e0d6c0..607d5e33a06ab7c9b1c0aec5cf29462ee824c0c1 100644 (file)
@@ -19,6 +19,7 @@ import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Map;
+import java.util.Optional;
 
 import javax.portlet.Portlet;
 
@@ -27,6 +28,7 @@ import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceObjects;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.log.LogService;
 import org.osgi.util.tracker.ServiceTrackerCustomizer;
 
 import com.vaadin.osgi.resources.VaadinResourceService;
@@ -60,9 +62,12 @@ class PortletUIServiceTrackerCustomizer
 
     private Map<ServiceReference<UI>, ServiceRegistration<Portlet>> portletRegistrations = new HashMap<ServiceReference<UI>, ServiceRegistration<Portlet>>();
     private VaadinResourceService service;
+    private Optional<LogService> logService;
 
-    PortletUIServiceTrackerCustomizer(VaadinResourceService service) {
+    PortletUIServiceTrackerCustomizer(VaadinResourceService service,
+            LogService logService) {
         this.service = service;
+        this.logService = Optional.ofNullable(logService);
     }
 
     @Override
@@ -102,7 +107,8 @@ class PortletUIServiceTrackerCustomizer
         ServiceObjects<UI> serviceObjects = bundleContext
                 .getServiceObjects(reference);
 
-        OsgiUIProvider uiProvider = new OsgiUIProvider(serviceObjects);
+        OsgiUIProvider uiProvider = new OsgiUIProvider(serviceObjects,
+                logService);
 
         Dictionary<String, Object> properties = null;
         if (configuration != null) {
index 78d0bff3833edb67896f0559f7017ca5df965ff6..b95f0b591ee170f67aab3c6518f72e8376241f6d 100644 (file)
  */
 package com.vaadin.osgi.liferay;
 
+import java.util.Optional;
+
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceObjects;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.log.LogService;
 import org.osgi.util.tracker.ServiceTracker;
 
 import com.vaadin.osgi.resources.OsgiVaadinResources;
@@ -37,11 +42,12 @@ import com.vaadin.ui.UI;
  *
  * @since 8.1
  */
-@Component(immediate = true)
+@Component
 public class VaadinPortletProvider {
 
     private ServiceTracker<UI, ServiceObjects<UI>> serviceTracker;
     private PortletUIServiceTrackerCustomizer portletUIServiceTrackerCustomizer;
+    private LogService logService;
 
     @Activate
     void activate(ComponentContext componentContext) throws Exception {
@@ -49,12 +55,21 @@ public class VaadinPortletProvider {
         VaadinResourceService service = OsgiVaadinResources.getService();
 
         portletUIServiceTrackerCustomizer = new PortletUIServiceTrackerCustomizer(
-                service);
+                service, logService);
         serviceTracker = new ServiceTracker<UI, ServiceObjects<UI>>(
                 bundleContext, UI.class, portletUIServiceTrackerCustomizer);
         serviceTracker.open();
     }
 
+    @Reference(cardinality = ReferenceCardinality.OPTIONAL)
+    void setLogService(LogService logService) {
+        this.logService = logService;
+    }
+
+    void unsetLogService(LogService logService) {
+        this.logService = null;
+    }
+
     @Deactivate
     void deactivate() {
         if (serviceTracker != null) {
@@ -62,6 +77,5 @@ public class VaadinPortletProvider {
             portletUIServiceTrackerCustomizer.cleanPortletRegistrations();
             portletUIServiceTrackerCustomizer = null;
         }
-
     }
 }