The Topic API provides the CollaborationList data structure to store ordered values and subscribe to their changes. You can get a CollaborationList by its name in the Topic connection activation callback.
Source code
CollaborationListExample.java
package com.vaadin.demo.collaboration;
import com.vaadin.collaborationengine.CollaborationEngine;
import com.vaadin.collaborationengine.CollaborationList;
import com.vaadin.collaborationengine.ListOperation;
import com.vaadin.collaborationengine.ListOperationResult;
import com.vaadin.collaborationengine.ListKey;
import com.vaadin.collaborationengine.UserInfo;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
public class CollaborationListExample extends VerticalLayout {
public CollaborationListExample() {
// NOTE: Use the user id of the logged-in user
// instead
String userId = System.identityHashCode(UI.getCurrentOrThrow()) + "";
UserInfo localUser = new UserInfo(userId, "User " + userId);
CollaborationEngine.getInstance().openTopicConnection(this, "my-topic",
localUser, connection -> {
CollaborationList list = connection.getNamedList("my-list");
ListOperationResult<Void> result = list.insertLast("foo");
result.getCompletableFuture().thenAccept(v -> {
// do something when the insertion completes
});
ListKey key = result.getKey();
// Replace an item using its key
list.set(key, "bar");
// Get an item value using its key
String bar = list.getItem(key, String.class);
// Insert an item at the end of the list
// Only succeeds if key is currently last
ListOperation operation1 = ListOperation.insertLast("baz")
.ifLast(key);
ListOperationResult<Boolean> result1 = list
.apply(operation1);
ListKey key1 = result1.getKey();
// Insert an item before key1
// Only succeeds if key1 is currently last
ListOperation operation2 = ListOperation
.insertBefore(key1, "qux").ifLast(key1);
ListOperationResult<Boolean> result2 = list
.apply(operation2);
ListKey key2 = result2.getKey();
// Insert an item between two keys
// Only succeeds if the keys are consecutive
ListOperation operation3 = ListOperation.insertBetween(key2,
key1, "xyz");
ListOperationResult<Boolean> result3 = list
.apply(operation3);
// Remove an item using its key
list.remove(key);
return null;
});
}
}
When you’ve gotten the list instance, you can insert values at the end of the list with the insertLast() method.
Source code
CollaborationListExample.java
package com.vaadin.demo.collaboration;
import com.vaadin.collaborationengine.CollaborationEngine;
import com.vaadin.collaborationengine.CollaborationList;
import com.vaadin.collaborationengine.ListOperation;
import com.vaadin.collaborationengine.ListOperationResult;
import com.vaadin.collaborationengine.ListKey;
import com.vaadin.collaborationengine.UserInfo;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
public class CollaborationListExample extends VerticalLayout {
public CollaborationListExample() {
// NOTE: Use the user id of the logged-in user
// instead
String userId = System.identityHashCode(UI.getCurrentOrThrow()) + "";
UserInfo localUser = new UserInfo(userId, "User " + userId);
CollaborationEngine.getInstance().openTopicConnection(this, "my-topic",
localUser, connection -> {
CollaborationList list = connection.getNamedList("my-list");
ListOperationResult<Void> result = list.insertLast("foo");
result.getCompletableFuture().thenAccept(v -> {
// do something when the insertion completes
});
ListKey key = result.getKey();
// Replace an item using its key
list.set(key, "bar");
// Get an item value using its key
String bar = list.getItem(key, String.class);
// Insert an item at the end of the list
// Only succeeds if key is currently last
ListOperation operation1 = ListOperation.insertLast("baz")
.ifLast(key);
ListOperationResult<Boolean> result1 = list
.apply(operation1);
ListKey key1 = result1.getKey();
// Insert an item before key1
// Only succeeds if key1 is currently last
ListOperation operation2 = ListOperation
.insertBefore(key1, "qux").ifLast(key1);
ListOperationResult<Boolean> result2 = list
.apply(operation2);
ListKey key2 = result2.getKey();
// Insert an item between two keys
// Only succeeds if the keys are consecutive
ListOperation operation3 = ListOperation.insertBetween(key2,
key1, "xyz");
ListOperationResult<Boolean> result3 = list
.apply(operation3);
// Remove an item using its key
list.remove(key);
return null;
});
}
}
Since the insertion is asynchronous, the method returns a result object from which you can get a CompletableFuture that you can use to determine when the insertion has been done.
Source code
CollaborationListExample.java
package com.vaadin.demo.collaboration;
import com.vaadin.collaborationengine.CollaborationEngine;
import com.vaadin.collaborationengine.CollaborationList;
import com.vaadin.collaborationengine.ListOperation;
import com.vaadin.collaborationengine.ListOperationResult;
import com.vaadin.collaborationengine.ListKey;
import com.vaadin.collaborationengine.UserInfo;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
public class CollaborationListExample extends VerticalLayout {
public CollaborationListExample() {
// NOTE: Use the user id of the logged-in user
// instead
String userId = System.identityHashCode(UI.getCurrentOrThrow()) + "";
UserInfo localUser = new UserInfo(userId, "User " + userId);
CollaborationEngine.getInstance().openTopicConnection(this, "my-topic",
localUser, connection -> {
CollaborationList list = connection.getNamedList("my-list");
ListOperationResult<Void> result = list.insertLast("foo");
result.getCompletableFuture().thenAccept(v -> {
// do something when the insertion completes
});
ListKey key = result.getKey();
// Replace an item using its key
list.set(key, "bar");
// Get an item value using its key
String bar = list.getItem(key, String.class);
// Insert an item at the end of the list
// Only succeeds if key is currently last
ListOperation operation1 = ListOperation.insertLast("baz")
.ifLast(key);
ListOperationResult<Boolean> result1 = list
.apply(operation1);
ListKey key1 = result1.getKey();
// Insert an item before key1
// Only succeeds if key1 is currently last
ListOperation operation2 = ListOperation
.insertBefore(key1, "qux").ifLast(key1);
ListOperationResult<Boolean> result2 = list
.apply(operation2);
ListKey key2 = result2.getKey();
// Insert an item between two keys
// Only succeeds if the keys are consecutive
ListOperation operation3 = ListOperation.insertBetween(key2,
key1, "xyz");
ListOperationResult<Boolean> result3 = list
.apply(operation3);
// Remove an item using its key
list.remove(key);
return null;
});
}
}
The result object also provides the ListKey of the inserted item, which you can use to replace the item itself, get its current value, or remove it from the list.
Source code
CollaborationListExample.java
package com.vaadin.demo.collaboration;
import com.vaadin.collaborationengine.CollaborationEngine;
import com.vaadin.collaborationengine.CollaborationList;
import com.vaadin.collaborationengine.ListOperation;
import com.vaadin.collaborationengine.ListOperationResult;
import com.vaadin.collaborationengine.ListKey;
import com.vaadin.collaborationengine.UserInfo;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
public class CollaborationListExample extends VerticalLayout {
public CollaborationListExample() {
// NOTE: Use the user id of the logged-in user
// instead
String userId = System.identityHashCode(UI.getCurrentOrThrow()) + "";
UserInfo localUser = new UserInfo(userId, "User " + userId);
CollaborationEngine.getInstance().openTopicConnection(this, "my-topic",
localUser, connection -> {
CollaborationList list = connection.getNamedList("my-list");
ListOperationResult<Void> result = list.insertLast("foo");
result.getCompletableFuture().thenAccept(v -> {
// do something when the insertion completes
});
ListKey key = result.getKey();
// Replace an item using its key
list.set(key, "bar");
// Get an item value using its key
String bar = list.getItem(key, String.class);
// Insert an item at the end of the list
// Only succeeds if key is currently last
ListOperation operation1 = ListOperation.insertLast("baz")
.ifLast(key);
ListOperationResult<Boolean> result1 = list
.apply(operation1);
ListKey key1 = result1.getKey();
// Insert an item before key1
// Only succeeds if key1 is currently last
ListOperation operation2 = ListOperation
.insertBefore(key1, "qux").ifLast(key1);
ListOperationResult<Boolean> result2 = list
.apply(operation2);
ListKey key2 = result2.getKey();
// Insert an item between two keys
// Only succeeds if the keys are consecutive
ListOperation operation3 = ListOperation.insertBetween(key2,
key1, "xyz");
ListOperationResult<Boolean> result3 = list
.apply(operation3);
// Remove an item using its key
list.remove(key);
return null;
});
}
}
Advanced List Operations
The ListOperation class allows you to prepare a list operation that can then be applied to the list using the CollaborationList::apply method.
The reason you may want to use this class is to define certain conditions that must be met when the operation is attempted. If a condition isn’t met, the operation isn’t completed. This is useful to protect against duplicate operations.
The ListOperation has several static and conditional methods for inserting values:
Method
Type
Description
insertFirst()
static
Inserted at the beginning of the list.
insertLast()
static
Inserted at the end of the list.
insertBefore()
static
Inserted immediately before a specified key.
insertAfter()
static
Inserted immediately after a specified key.
insertBetween()
static
Shorthand for insertAfter(value, keyBefore).ifNext(keyBefore, keyAfter).
ifFirst(key)
conditional
The specified key must be the first in the list.
ifLast(key)
conditional
Must be the last in the list.
ifPrev(key, keyPrev)
conditional
The specified keyPrev must be immediately before key.
ifNext(key, keyNext)
conditional
The specified keyNext must be immediately after key.
ifEmpty()
conditional
The list must have no entries.
ifNotEmpty()
conditional
The list must have at least one entry.
The example here shows how some of these methods might be used:
Source code
CollaborationListExample.java
package com.vaadin.demo.collaboration;
import com.vaadin.collaborationengine.CollaborationEngine;
import com.vaadin.collaborationengine.CollaborationList;
import com.vaadin.collaborationengine.ListOperation;
import com.vaadin.collaborationengine.ListOperationResult;
import com.vaadin.collaborationengine.ListKey;
import com.vaadin.collaborationengine.UserInfo;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
public class CollaborationListExample extends VerticalLayout {
public CollaborationListExample() {
// NOTE: Use the user id of the logged-in user
// instead
String userId = System.identityHashCode(UI.getCurrentOrThrow()) + "";
UserInfo localUser = new UserInfo(userId, "User " + userId);
CollaborationEngine.getInstance().openTopicConnection(this, "my-topic",
localUser, connection -> {
CollaborationList list = connection.getNamedList("my-list");
ListOperationResult<Void> result = list.insertLast("foo");
result.getCompletableFuture().thenAccept(v -> {
// do something when the insertion completes
});
ListKey key = result.getKey();
// Replace an item using its key
list.set(key, "bar");
// Get an item value using its key
String bar = list.getItem(key, String.class);
// Insert an item at the end of the list
// Only succeeds if key is currently last
ListOperation operation1 = ListOperation.insertLast("baz")
.ifLast(key);
ListOperationResult<Boolean> result1 = list
.apply(operation1);
ListKey key1 = result1.getKey();
// Insert an item before key1
// Only succeeds if key1 is currently last
ListOperation operation2 = ListOperation
.insertBefore(key1, "qux").ifLast(key1);
ListOperationResult<Boolean> result2 = list
.apply(operation2);
ListKey key2 = result2.getKey();
// Insert an item between two keys
// Only succeeds if the keys are consecutive
ListOperation operation3 = ListOperation.insertBetween(key2,
key1, "xyz");
ListOperationResult<Boolean> result3 = list
.apply(operation3);
// Remove an item using its key
list.remove(key);
return null;
});
}
}