All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dellroad.stuff.vaadin23.data.VaadinSessionDataProvider Maven / Gradle / Ivy

The newest version!

/*
 * Copyright (C) 2022 Archie L. Cobbs. All rights reserved.
 */

package org.dellroad.stuff.vaadin23.data;

import com.google.common.base.Preconditions;
import com.vaadin.flow.server.VaadinService;
import com.vaadin.flow.server.VaadinServlet;
import com.vaadin.flow.server.VaadinServletService;
import com.vaadin.flow.server.VaadinSession;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;

import org.dellroad.stuff.vaadin23.servlet.SimpleSpringServlet;
import org.dellroad.stuff.vaadin23.util.VaadinUtil;

/**
 * A {@link DataProvider} that provides an object corresponding to each live {@link VaadinSession}.
 *
 * 

* The sessions are retrieved from the {@link SimpleSpringServlet}, which must be configured with session tracking enabled. * *

* Sessions are represented by {@link SessionInfo}, which may be subclassed to add application-specific information * (e.g., currently logged-in user). * *

* Sessions are orderded by reverse creation time (newest first). * * @see SimpleSpringServlet */ @SuppressWarnings("serial") public class VaadinSessionDataProvider extends AsyncDataProvider { protected final SimpleSpringServlet servlet; protected final Function infoCreator; /** * Constructor. * *

* The {@link infoCreator} gathers whatever information is needed by this instance from the given session, * and may assume that the given session is locked. * *

* If {@link infoCreator} returns null, that session is omitted. * *

* Caller still must configure an async executor; see {@link AsyncDataProvider#AsyncDataProvider()}. * * @param infoCreator extracts data provider information from each session * @throws IllegalStateException if there is no current {@link VaadinSession} associated with the current thread * @throws IllegalArgumentException if the associated {@link VaadinService} is not a {@link VaadinServletService} * @throws IllegalArgumentException if the associated {@link VaadinServlet} is not a {@link SimpleSpringServlet} * @throws IllegalArgumentException if {@code infoCreator} is null */ public VaadinSessionDataProvider(Function infoCreator) { this(null, infoCreator); } /** * Constructor. * *

* The {@link infoCreator} gathers whatever information is needed by this instance from the given session, * and may assume that the given session is locked. * *

* If {@link infoCreator} returns null, that session is omitted. * * @param executor the executor used to execute async load tasks * @param infoCreator extracts data provider information from each session * @throws IllegalStateException if there is no current {@link VaadinSession} associated with the current thread * @throws IllegalArgumentException if the associated {@link VaadinService} is not a {@link VaadinServletService} * @throws IllegalArgumentException if the associated {@link VaadinServlet} is not a {@link SimpleSpringServlet} * @throws IllegalArgumentException if {@code infoCreator} is null */ public VaadinSessionDataProvider(Function> executor, Function infoCreator) { Preconditions.checkArgument(infoCreator != null, "null infoCreator"); this.servlet = SimpleSpringServlet.forSession(this.getAsyncTaskManager().getVaadinSession()); this.infoCreator = infoCreator; if (executor != null) this.getAsyncTaskManager().setAsyncExecutor(executor); } /** * Load or reload this data provider. * *

* If there is already an async load in progress, this method will {@link #cancel cancel()} it first. * You can check this ahead of time via {@link #isBusy}. * * @return unique ID for this load attempt * @throws IllegalStateException if this instance is already in the process of reloading * @throws IllegalStateException if this instance's {@link VaadinSession} is not locked */ public void reload() { this.load(id -> this.buildSessionList().stream()); } // ListDataProvider /** * Get the {@link SessionInfo}'s currently in this container. */ @Override public List getItems() { return (List)super.getItems(); } /** * {@inheritDoc} * *

* The implementation in {@code VaadinSessionDataProvider} returns {@code item.getId()} * if {@code item} is not null, otherwise null. * * @param item data item */ @Override public String getId(T item) { return item != null ? item.getId() : null; } /** * Build the list of sessions. * *

* @throws IllegalStateException if any session lock is held */ protected List buildSessionList() throws InterruptedException { // Sanity check VaadinUtil.assertNoSession(); // Grab list of live sessions from servlet final List sessionList = this.servlet.getSessions(); // Sort by reverse creation time sessionList.sort(Comparator. comparingLong(otherSession -> otherSession.getSession().getCreationTime()).reversed() .thenComparing(otherSession -> otherSession.getSession().getId())); // Extract session info, locking each session while we do it final ArrayList sessionInfoList = new ArrayList<>(sessionList.size()); final AtomicReference sessionInfoRef = new AtomicReference<>(); for (VaadinSession otherSession : sessionList) { if (Thread.interrupted()) // we got canceled throw new InterruptedException(); otherSession.accessSynchronously(() -> sessionInfoRef.set(infoCreator.apply(otherSession))); final T sessionInfo = sessionInfoRef.get(); if (sessionInfo != null) sessionInfoList.add(sessionInfo); } // Done return sessionInfoList; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy