aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/src/main/java/com/vaadin/server/ConnectorIdGenerationEvent.java75
-rw-r--r--server/src/main/java/com/vaadin/server/ConnectorIdGenerator.java56
-rw-r--r--server/src/main/java/com/vaadin/server/ServiceInitEvent.java36
-rw-r--r--server/src/main/java/com/vaadin/server/VaadinService.java77
-rw-r--r--server/src/main/java/com/vaadin/server/VaadinSession.java18
-rw-r--r--server/src/test/java/com/vaadin/server/MockVaadinSession.java6
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/abstractsinglecomponentcontainer/RemoveFromParentLockingTest.java13
-rw-r--r--uitest/src/main/java/com/vaadin/tests/applicationservlet/ServiceInitListeners.java2
-rw-r--r--uitest/src/main/java/com/vaadin/tests/applicationservlet/TestingServiceInitListener.java16
-rw-r--r--uitest/src/test/java/com/vaadin/tests/applicationservlet/ServiceInitListenersTest.java1
10 files changed, 287 insertions, 13 deletions
diff --git a/server/src/main/java/com/vaadin/server/ConnectorIdGenerationEvent.java b/server/src/main/java/com/vaadin/server/ConnectorIdGenerationEvent.java
new file mode 100644
index 0000000000..5cfba15e97
--- /dev/null
+++ b/server/src/main/java/com/vaadin/server/ConnectorIdGenerationEvent.java
@@ -0,0 +1,75 @@
+/*
+ * 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.EventObject;
+
+import com.vaadin.shared.Connector;
+
+/**
+ * Event object containing information related to connector id generation.
+ *
+ * @author Vaadin Ltd
+ * @since 8.1
+ */
+public class ConnectorIdGenerationEvent extends EventObject {
+
+ private final VaadinSession session;
+ private final Connector connector;
+
+ /**
+ * Creates a new event for the given session and connector.
+ *
+ * @param session
+ * the session for which a connector id is needed, not
+ * <code>null</code>
+ * @param connector
+ * the connector that should get an id, not <code>null</code>
+ */
+ public ConnectorIdGenerationEvent(VaadinSession session,
+ Connector connector) {
+ super(session.getService());
+
+ assert session != null;
+ assert connector != null;
+
+ this.session = session;
+ this.connector = connector;
+ }
+
+ /**
+ * Gets the session for which connector id is needed.
+ *
+ * @return the session, not <code>null</code>
+ */
+ public VaadinSession getSession() {
+ return session;
+ }
+
+ /**
+ * Gets the connector that should get an id.
+ *
+ * @return the connector, not <code>null</code>
+ */
+ public Connector getConnector() {
+ return connector;
+ }
+
+ @Override
+ public VaadinService getSource() {
+ return (VaadinService) super.getSource();
+ }
+}
diff --git a/server/src/main/java/com/vaadin/server/ConnectorIdGenerator.java b/server/src/main/java/com/vaadin/server/ConnectorIdGenerator.java
new file mode 100644
index 0000000000..c40b9cfbd6
--- /dev/null
+++ b/server/src/main/java/com/vaadin/server/ConnectorIdGenerator.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.server;
+
+import java.io.Serializable;
+
+/**
+ * Callback for generating the id for new connectors. A generator can be
+ * registered to be used with an application by overriding
+ * {@link VaadinService#initConenctorIdGenerator(java.util.List)} or by calling
+ * {@link ServiceInitEvent#addConnectorIdGenerator(ConnectorIdGenerator)} from a
+ * {@link VaadinServiceInitListener}.
+ *
+ * @author Vaadin Ltd
+ * @since 8.1
+ */
+@FunctionalInterface
+public interface ConnectorIdGenerator extends Serializable {
+ /**
+ * Generates a connector id for a connector.
+ *
+ * @param event
+ * the event object that has a reference to the connector and the
+ * session, not <code>null</code>
+ * @return the connector id to use for the connector, not <code>null</code>
+ */
+ public String generateConnectorId(ConnectorIdGenerationEvent event);
+
+ /**
+ * Generates a connector id using the default logic by using
+ * {@link VaadinSession#getNextConnectorId()}.
+ *
+ * @param event
+ * the event object that has a reference to the connector and the
+ * session, not <code>null</code>
+ * @return the connector id to use for the connector, not <code>null</code>
+ */
+ public static String generateDefaultConnectorId(
+ ConnectorIdGenerationEvent event) {
+ assert event != null;
+ return event.getSession().getNextConnectorId();
+ }
+}
diff --git a/server/src/main/java/com/vaadin/server/ServiceInitEvent.java b/server/src/main/java/com/vaadin/server/ServiceInitEvent.java
index 482c23dd23..1bd5e1b78f 100644
--- a/server/src/main/java/com/vaadin/server/ServiceInitEvent.java
+++ b/server/src/main/java/com/vaadin/server/ServiceInitEvent.java
@@ -35,6 +35,7 @@ public class ServiceInitEvent extends EventObject {
private List<RequestHandler> addedRequestHandlers = new ArrayList<>();
private List<DependencyFilter> addedDependencyFilters = new ArrayList<>();
+ private List<ConnectorIdGenerator> addedConnectorIdGenerators = new ArrayList<>();
/**
* Creates a new service init event for a given {@link VaadinService} and
@@ -99,6 +100,41 @@ public class ServiceInitEvent extends EventObject {
return Collections.unmodifiableList(addedDependencyFilters);
}
+ /**
+ * Adds as connector id generator to be used by this service. By default,
+ * the service will fail to deploy if more than one connector id generator
+ * has been registered.
+ *
+ * @param connectorIdGenerator
+ * the connector id generator to add, not <code>null</code>
+ *
+ * @since 8.1
+ */
+ public void addConnectorIdGenerator(
+ ConnectorIdGenerator connectorIdGenerator) {
+ Objects.requireNonNull(connectorIdGenerator,
+ "Connector id generator cannot be null");
+
+ /*
+ * We're collecting all generators so that a custom service
+ * implementation can pick which one to use even though the default
+ * implementation throws if there are more than one.
+ */
+ addedConnectorIdGenerators.add(connectorIdGenerator);
+ }
+
+ /**
+ * Gets an unmodifiable list of all connector id generators that have been
+ * added for the service.
+ *
+ * @return the current list of added connector id generators
+ *
+ * @since 8.1
+ */
+ public List<ConnectorIdGenerator> getAddedConnectorIdGenerators() {
+ return Collections.unmodifiableList(addedConnectorIdGenerators);
+ }
+
@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 649826a5d6..65ef09f2a3 100644
--- a/server/src/main/java/com/vaadin/server/VaadinService.java
+++ b/server/src/main/java/com/vaadin/server/VaadinService.java
@@ -136,6 +136,7 @@ public abstract class VaadinService implements Serializable {
private Iterable<RequestHandler> requestHandlers;
private Iterable<DependencyFilter> dependencyFilters;
+ private ConnectorIdGenerator connectorIdGenerator;
private boolean atmosphereAvailable = checkAtmosphereSupport();
@@ -209,6 +210,11 @@ public abstract class VaadinService implements Serializable {
dependencyFilters = Collections.unmodifiableCollection(
initDependencyFilters(event.getAddedDependencyFilters()));
+
+ connectorIdGenerator = initConenctorIdGenerator(
+ event.getAddedConnectorIdGenerators());
+ assert connectorIdGenerator != null;
+
initialized = true;
}
@@ -1477,6 +1483,49 @@ public abstract class VaadinService implements Serializable {
}
/**
+ * Determines the connector id generator to use for the application.
+ * <p>
+ * The connector id generator creates a unique id for each connector
+ * attached to a UI.
+ * <p>
+ * The framework collects generators from the {@link SessionInitEvent} where
+ * session init listeners can add them. This method is called with the
+ * combined list to determine one generator to use.
+ * <p>
+ * If the list is empty, a default implementation based on
+ * {@link VaadinSession#getNextConnectorId()} is used. If the list contains
+ * one item, it is used. If there are multiple generators in the list, an
+ * exception is thrown.
+ *
+ * @since 8.1
+ * @param addedConnectorIdGenerators
+ * a list of connector id generators collected from the session
+ * init event, not <code>null</code>
+ * @return the connector id generator to use, not <code>null</code>
+ *
+ * @throws ServiceException
+ * if something went wrong while determining the filters, e.g.
+ * if there are multiple implementations to choose from
+ *
+ */
+ protected ConnectorIdGenerator initConenctorIdGenerator(
+ List<ConnectorIdGenerator> addedConnectorIdGenerators)
+ throws ServiceException {
+ assert addedConnectorIdGenerators != null;
+
+ switch (addedConnectorIdGenerators.size()) {
+ case 0:
+ return ConnectorIdGenerator::generateDefaultConnectorId;
+ case 1:
+ return addedConnectorIdGenerators.get(0);
+ default:
+ throw new ServiceException(
+ "Cannot start application since there are multiple connector id generators. Remove redundant implementations from the classpath or override VaadinService.initConenctorIdGenerator to explicitly select one to use. The found generators are: "
+ + addedConnectorIdGenerators);
+ }
+ }
+
+ /**
* Gets the filters which all resource dependencies are passed through
* before being sent to the client for loading.
*
@@ -2149,4 +2198,32 @@ public abstract class VaadinService implements Serializable {
return VaadinSession.class.getName() + "." + getServiceName();
}
+ /**
+ * Generates a unique id to use for a newly attached connector.
+ *
+ * @see ConnectorIdGenerator
+ * @see #initConenctorIdGenerator(List)
+ *
+ * @since 8.1
+ *
+ * @param session
+ * the session to which the connector has been attached, not
+ * <code>null</code>
+ * @param connector
+ * the attached connector for which to generate an id, not
+ * <code>null</code>
+ * @return a string id that is unique within the session, not
+ * <code>null</code>
+ */
+ public String generateConnectorId(VaadinSession session,
+ ClientConnector connector) {
+ assert session.getService() == this;
+ String connectorId = connectorIdGenerator.generateConnectorId(
+ new ConnectorIdGenerationEvent(session, connector));
+
+ assert connectorId != null;
+
+ return connectorId;
+ }
+
}
diff --git a/server/src/main/java/com/vaadin/server/VaadinSession.java b/server/src/main/java/com/vaadin/server/VaadinSession.java
index de5c192846..fdc8a28b8b 100644
--- a/server/src/main/java/com/vaadin/server/VaadinSession.java
+++ b/server/src/main/java/com/vaadin/server/VaadinSession.java
@@ -754,11 +754,25 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* A connector that has not yet been assigned an id.
* @return A new id for the connector
*
- * @deprecated As of 7.0. Will likely change or be removed in a future
- * version
+ * @deprecated As of 7.0. Use
+ * {@link VaadinService#generateConnectorId(VaadinSession, ClientConnector)}
+ * instead.
*/
@Deprecated
public String createConnectorId(ClientConnector connector) {
+ return service.generateConnectorId(this, connector);
+ }
+
+ /**
+ * Gets the next unused numerical id for connector ids.
+ *
+ * @since 8.1
+ *
+ * @return the next unused numerical id for connector ids, not
+ * <code>null</code>
+ *
+ */
+ public String getNextConnectorId() {
assert hasLock();
return String.valueOf(connectorIdSequence++);
}
diff --git a/server/src/test/java/com/vaadin/server/MockVaadinSession.java b/server/src/test/java/com/vaadin/server/MockVaadinSession.java
index 07854560b3..0dc5010b1a 100644
--- a/server/src/test/java/com/vaadin/server/MockVaadinSession.java
+++ b/server/src/test/java/com/vaadin/server/MockVaadinSession.java
@@ -64,6 +64,12 @@ public class MockVaadinSession extends VaadinSession {
referenceKeeper.remove();
}
+ @Override
+ public String createConnectorId(ClientConnector connector) {
+ // Don't delegate to service which may be null or a broken mock
+ return getNextConnectorId();
+ }
+
private int closeCount;
private final ReentrantLock lock = new ReentrantLock();
diff --git a/server/src/test/java/com/vaadin/tests/server/component/abstractsinglecomponentcontainer/RemoveFromParentLockingTest.java b/server/src/test/java/com/vaadin/tests/server/component/abstractsinglecomponentcontainer/RemoveFromParentLockingTest.java
index 2da2d6aede..f963152960 100644
--- a/server/src/test/java/com/vaadin/tests/server/component/abstractsinglecomponentcontainer/RemoveFromParentLockingTest.java
+++ b/server/src/test/java/com/vaadin/tests/server/component/abstractsinglecomponentcontainer/RemoveFromParentLockingTest.java
@@ -15,14 +15,12 @@
*/
package com.vaadin.tests.server.component.abstractsinglecomponentcontainer;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import com.vaadin.server.MockVaadinSession;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinSession;
import com.vaadin.ui.UI;
@@ -37,14 +35,7 @@ public class RemoveFromParentLockingTest {
}
private static VerticalLayout createTestComponent() {
- VaadinSession session = new VaadinSession(null) {
- private final ReentrantLock lock = new ReentrantLock();
-
- @Override
- public Lock getLockInstance() {
- return lock;
- }
- };
+ VaadinSession session = new MockVaadinSession(null);
session.getLockInstance().lock();
try {
diff --git a/uitest/src/main/java/com/vaadin/tests/applicationservlet/ServiceInitListeners.java b/uitest/src/main/java/com/vaadin/tests/applicationservlet/ServiceInitListeners.java
index 16e4609267..5c649a26b3 100644
--- a/uitest/src/main/java/com/vaadin/tests/applicationservlet/ServiceInitListeners.java
+++ b/uitest/src/main/java/com/vaadin/tests/applicationservlet/ServiceInitListeners.java
@@ -24,5 +24,7 @@ public class ServiceInitListeners extends AbstractTestUIWithLog {
protected void setup(VaadinRequest request) {
log("Init count: " + TestingServiceInitListener.getInitCount());
log("Request count: " + TestingServiceInitListener.getRequestCount());
+ log("Connector id count: "
+ + TestingServiceInitListener.getConnectorIdCount());
}
}
diff --git a/uitest/src/main/java/com/vaadin/tests/applicationservlet/TestingServiceInitListener.java b/uitest/src/main/java/com/vaadin/tests/applicationservlet/TestingServiceInitListener.java
index d0685ad975..d100108c3c 100644
--- a/uitest/src/main/java/com/vaadin/tests/applicationservlet/TestingServiceInitListener.java
+++ b/uitest/src/main/java/com/vaadin/tests/applicationservlet/TestingServiceInitListener.java
@@ -18,6 +18,8 @@ package com.vaadin.tests.applicationservlet;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
+import com.vaadin.server.ConnectorIdGenerationEvent;
+import com.vaadin.server.ConnectorIdGenerator;
import com.vaadin.server.RequestHandler;
import com.vaadin.server.ServiceInitEvent;
import com.vaadin.server.VaadinRequest;
@@ -29,6 +31,7 @@ public class TestingServiceInitListener implements VaadinServiceInitListener {
private static AtomicInteger initCount = new AtomicInteger();
private static AtomicInteger requestCount = new AtomicInteger();
+ private static AtomicInteger connectorIdCount = new AtomicInteger();
@Override
public void serviceInit(ServiceInitEvent event) {
@@ -43,6 +46,15 @@ public class TestingServiceInitListener implements VaadinServiceInitListener {
return false;
}
});
+
+ event.addConnectorIdGenerator(new ConnectorIdGenerator() {
+ @Override
+ public String generateConnectorId(
+ ConnectorIdGenerationEvent event) {
+ connectorIdCount.incrementAndGet();
+ return ConnectorIdGenerator.generateDefaultConnectorId(event);
+ }
+ });
}
public static int getInitCount() {
@@ -53,4 +65,8 @@ public class TestingServiceInitListener implements VaadinServiceInitListener {
return requestCount.get();
}
+ public static int getConnectorIdCount() {
+ return connectorIdCount.get();
+ }
+
}
diff --git a/uitest/src/test/java/com/vaadin/tests/applicationservlet/ServiceInitListenersTest.java b/uitest/src/test/java/com/vaadin/tests/applicationservlet/ServiceInitListenersTest.java
index d97f668967..a23a6f1a1f 100644
--- a/uitest/src/test/java/com/vaadin/tests/applicationservlet/ServiceInitListenersTest.java
+++ b/uitest/src/test/java/com/vaadin/tests/applicationservlet/ServiceInitListenersTest.java
@@ -28,6 +28,7 @@ public class ServiceInitListenersTest extends SingleBrowserTest {
Assert.assertNotEquals(getLogRow(0), 0, extractCount(getLogRow(0)));
Assert.assertNotEquals(getLogRow(1), 0, extractCount(getLogRow(1)));
+ Assert.assertNotEquals(getLogRow(2), 0, extractCount(getLogRow(2)));
}
private int extractCount(String logRow) {