]> source.dussan.org Git - vaadin-framework.git/commitdiff
Introduce VaadinServiceInitListener (#18628) (#79)
authorLeif Åstrand <legioth@gmail.com>
Fri, 2 Dec 2016 14:17:15 +0000 (16:17 +0200)
committerDenis <denis@vaadin.com>
Fri, 2 Dec 2016 14:17:15 +0000 (17:17 +0300)
server/src/main/java/com/vaadin/server/ServiceInitEvent.java [new file with mode: 0644]
server/src/main/java/com/vaadin/server/VaadinService.java
server/src/main/java/com/vaadin/server/VaadinServiceInitListener.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/tests/applicationservlet/ServiceInitListeners.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/tests/applicationservlet/TestingServiceInitListener.java [new file with mode: 0644]
uitest/src/main/resources/META-INF/services/com.vaadin.server.VaadinServiceInitListener [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/applicationservlet/ServiceInitListenersTest.java [new file with mode: 0644]

diff --git a/server/src/main/java/com/vaadin/server/ServiceInitEvent.java b/server/src/main/java/com/vaadin/server/ServiceInitEvent.java
new file mode 100644 (file)
index 0000000..b488c32
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.server;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EventObject;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Event fired to {@link VaadinServiceInitListener} when a {@link VaadinService}
+ * is being initialized.
+ * <p>
+ * This event can also be used to add {@link RequestHandler}s that will be used
+ * by the {@code VaadinService} for handling all requests.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class ServiceInitEvent extends EventObject {
+
+    private List<RequestHandler> addedRequestHandlers = new ArrayList<>();
+
+    /**
+     * Creates a new service init event for a given {@link VaadinService} and
+     * the {@link RequestHandler} that will be used by the service.
+     *
+     * @param service
+     *            the Vaadin service of this request
+     */
+    public ServiceInitEvent(VaadinService service) {
+        super(service);
+    }
+
+    /**
+     * Adds a new request handler that will be used by this service. The added
+     * handler will be run before any of the framework's own request handlers,
+     * but the ordering relative to other custom handlers is not guaranteed.
+     *
+     * @param requestHandler
+     *            the request handler to add, not <code>null</code>
+     */
+    public void addRequestHandler(RequestHandler requestHandler) {
+        Objects.requireNonNull(requestHandler,
+                "Request handler cannot be null");
+
+        addedRequestHandlers.add(requestHandler);
+    }
+
+    /**
+     * Gets an unmodifiable list of all custom request handlers that have been
+     * added for the service.
+     *
+     * @return the current list of added request handlers
+     */
+    public List<RequestHandler> getAddedRequestHandlers() {
+        return Collections.unmodifiableList(addedRequestHandlers);
+    }
+
+    @Override
+    public VaadinService getSource() {
+        return (VaadinService) super.getSource();
+    }
+
+}
index 70a60a4f1f7946818ff6c72d5b197fde9bb404d5..d07413f2379b07a1f2bb000a84943d71eb0bf7cc 100644 (file)
@@ -31,9 +31,11 @@ import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
@@ -191,12 +193,40 @@ public abstract class VaadinService implements Serializable {
      */
     public void init() throws ServiceException {
         List<RequestHandler> handlers = createRequestHandlers();
+
+        ServiceInitEvent event = new ServiceInitEvent(this);
+
+        Iterator<VaadinServiceInitListener> initListeners = getServiceInitListeners();
+        while (initListeners.hasNext()) {
+            initListeners.next().serviceInit(event);
+        }
+
+        handlers.addAll(event.getAddedRequestHandlers());
+
         Collections.reverse(handlers);
+
         requestHandlers = Collections.unmodifiableCollection(handlers);
 
         initialized = true;
     }
 
+    /**
+     * Gets all available service init listeners. A custom Vaadin service
+     * implementation can override this method to discover init listeners in
+     * some other way in addition to the default implementation that uses
+     * {@link ServiceLoader}. This could for example be used to allow defining
+     * an init listener as an OSGi service or as a Spring bean.
+     *
+     * @since
+     *
+     * @return an iterator of available service init listeners
+     */
+    protected Iterator<VaadinServiceInitListener> getServiceInitListeners() {
+        ServiceLoader<VaadinServiceInitListener> loader = ServiceLoader
+                .load(VaadinServiceInitListener.class, getClassLoader());
+        return loader.iterator();
+    }
+
     /**
      * Called during initialization to add the request handlers for the service.
      * Note that the returned list will be reversed so the last handler will be
diff --git a/server/src/main/java/com/vaadin/server/VaadinServiceInitListener.java b/server/src/main/java/com/vaadin/server/VaadinServiceInitListener.java
new file mode 100644 (file)
index 0000000..98959f0
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.server;
+
+import java.io.Serializable;
+import java.util.EventListener;
+import java.util.ServiceLoader;
+
+/**
+ * Listener for {@link VaadinService} initialization events. The listener can
+ * add listeners and request handlers the service.
+ * <p>
+ * Listener instances are by default discovered and instantiated using
+ * {@link ServiceLoader}. This means that all implementations must have a
+ * zero-argument constructor and the fully qualified name of the implementation
+ * class must be listed on a separate line in a
+ * META-INF/services/com.vaadin.server.VaadinServiceInitListener file present in
+ * the jar file containing the implementation class.
+ * <p>
+ * Integrations for specific runtime environments, such as OSGi or Spring, might
+ * also provide other ways of discovering listeners.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public interface VaadinServiceInitListener extends EventListener, Serializable {
+    /**
+     * Run when a {@link VaadinService} instance is initialized.
+     *
+     * @param event
+     *            the service initialization event
+     */
+    void serviceInit(ServiceInitEvent event);
+}
diff --git a/uitest/src/main/java/com/vaadin/tests/applicationservlet/ServiceInitListeners.java b/uitest/src/main/java/com/vaadin/tests/applicationservlet/ServiceInitListeners.java
new file mode 100644 (file)
index 0000000..4ecb7cf
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.applicationservlet;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+
+public class ServiceInitListeners extends AbstractTestUIWithLog {
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        log("Init count: " + TestingServiceInitListener.getInitCount());
+        log("Request count: " + TestingServiceInitListener.getRequestCount());
+    }
+}
diff --git a/uitest/src/main/java/com/vaadin/tests/applicationservlet/TestingServiceInitListener.java b/uitest/src/main/java/com/vaadin/tests/applicationservlet/TestingServiceInitListener.java
new file mode 100644 (file)
index 0000000..d0685ad
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.applicationservlet;
+
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.vaadin.server.RequestHandler;
+import com.vaadin.server.ServiceInitEvent;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinResponse;
+import com.vaadin.server.VaadinServiceInitListener;
+import com.vaadin.server.VaadinSession;
+
+public class TestingServiceInitListener implements VaadinServiceInitListener {
+
+    private static AtomicInteger initCount = new AtomicInteger();
+    private static AtomicInteger requestCount = new AtomicInteger();
+
+    @Override
+    public void serviceInit(ServiceInitEvent event) {
+        initCount.incrementAndGet();
+
+        event.addRequestHandler(new RequestHandler() {
+            @Override
+            public boolean handleRequest(VaadinSession session,
+                    VaadinRequest request, VaadinResponse response)
+                    throws IOException {
+                requestCount.incrementAndGet();
+                return false;
+            }
+        });
+    }
+
+    public static int getInitCount() {
+        return initCount.get();
+    }
+
+    public static int getRequestCount() {
+        return requestCount.get();
+    }
+
+}
diff --git a/uitest/src/main/resources/META-INF/services/com.vaadin.server.VaadinServiceInitListener b/uitest/src/main/resources/META-INF/services/com.vaadin.server.VaadinServiceInitListener
new file mode 100644 (file)
index 0000000..ea3d467
--- /dev/null
@@ -0,0 +1 @@
+com.vaadin.tests.applicationservlet.TestingServiceInitListener
diff --git a/uitest/src/test/java/com/vaadin/tests/applicationservlet/ServiceInitListenersTest.java b/uitest/src/test/java/com/vaadin/tests/applicationservlet/ServiceInitListenersTest.java
new file mode 100644 (file)
index 0000000..2c9403a
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.applicationservlet;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class ServiceInitListenersTest extends SingleBrowserTest {
+
+    @Test
+    public void testServiceInitListenerTriggered() {
+        openTestURL();
+
+        Assert.assertNotEquals(getLogRow(0), 0, extractCount(getLogRow(0)));
+        Assert.assertNotEquals(getLogRow(1), 0, extractCount(getLogRow(1)));
+    }
+
+    private int extractCount(String logRow) {
+        // Assuming row pattern is "label: 1"
+        String substring = logRow.replaceAll("[^:]*:\\s*", "");
+        return Integer.parseInt(substring);
+    }
+
+}