diff options
author | Leif Åstrand <legioth@gmail.com> | 2016-12-02 16:17:15 +0200 |
---|---|---|
committer | Denis <denis@vaadin.com> | 2016-12-02 17:17:15 +0300 |
commit | e746963efb1135e256da78cdd8cc24c88fdfd194 (patch) | |
tree | 5f86508bef50b4b7811ec8c7a597e737486449eb | |
parent | 54a6eef91cb2f0b8b7d65661162257711a2d6e2a (diff) | |
download | vaadin-framework-e746963efb1135e256da78cdd8cc24c88fdfd194.tar.gz vaadin-framework-e746963efb1135e256da78cdd8cc24c88fdfd194.zip |
Introduce VaadinServiceInitListener (#18628) (#79)
7 files changed, 280 insertions, 0 deletions
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 index 0000000000..b488c32e5e --- /dev/null +++ b/server/src/main/java/com/vaadin/server/ServiceInitEvent.java @@ -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(); + } + +} diff --git a/server/src/main/java/com/vaadin/server/VaadinService.java b/server/src/main/java/com/vaadin/server/VaadinService.java index 70a60a4f1f..d07413f237 100644 --- a/server/src/main/java/com/vaadin/server/VaadinService.java +++ b/server/src/main/java/com/vaadin/server/VaadinService.java @@ -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,13 +193,41 @@ 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 * called first. This enables overriding this method and using add on the 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 index 0000000000..98959f0571 --- /dev/null +++ b/server/src/main/java/com/vaadin/server/VaadinServiceInitListener.java @@ -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 index 0000000000..4ecb7cf0f0 --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/applicationservlet/ServiceInitListeners.java @@ -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 index 0000000000..d0685ad975 --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/applicationservlet/TestingServiceInitListener.java @@ -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 index 0000000000..ea3d467dab --- /dev/null +++ b/uitest/src/main/resources/META-INF/services/com.vaadin.server.VaadinServiceInitListener @@ -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 index 0000000000..2c9403acdb --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/applicationservlet/ServiceInitListenersTest.java @@ -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); + } + +} |