Как предоставить текущую сессию vaadin старым потокам пула потоков?
Я столкнулся с проблемой в понимании следующей цитаты VaadinSession.getCurrent()
Получает текущий используемый сеанс. Текущий сеанс определяется автоматически при обработке запросов к серверу и в потоках, запущенных в момент, когда текущий сеанс определен (см. InheritableThreadLocal). В других случаях (например, из фоновых потоков, запущенных каким-либо другим способом) текущий сеанс не определяется автоматически.
Конкретно следующий пункт мне трудно понять,
... в потоках, запущенных в момент, когда определен текущий сеанс (см. InheritableThreadLocal).
Что это значит?
Насколько я понимаю, если поток создается до того, как был определен новый сеанс или в старом сеансе, он не будет ссылаться на текущий вновь созданный сеанс.
В настоящее время у меня есть Thread Pool
и некоторые потоки ссылаются на старый сеанс, который сейчас закрыт, тогда я столкнусь с проблемой использования сеанса в этих потоках.
я использую spring
с vaadin
конкретно @Async
вызовы методов.
@Async
public static methodX() {
//I have used session inside it
}
Проблема, скажем, thread1
был использован для выполнения methodX
Теперь я использовал сессию session1
и после выхода пользователя из системы это session1
будет закрыто.
Теперь, когда новый пользователь входит в систему, которая имеет session2
и выполняет этот метод с thread1
снова тогда этот метод все еще использовал session1
вместо session2
и это создает проблему, когда методы пытаются извлечь данные из закрытого session1
,
Мои вопросы:
- Зачем
Vaadin
не может предоставить или уведомить старые потоки (то есть потоки, принадлежащие старому (закрытому) сеансу) о вновь определенныхSession
? - Каков наилучший способ обеспечить сеанс для этих потоков?
2 ответа
Проблема для фоновых тем VaadinSession
(не путать с HttpSession
) не доступен. После поиска этого в книге Ваадина я пришел к выводу со следующим решением.
Чтобы получить текущую сессию у нас есть VaadinSession.getCurrent()
а также UI.getCurrent().getSession()
оба они возвращают сессию.
Проблема в том, что старые потоки, созданные во время какого-либо другого сеанса, не могут получить доступ к текущему сеансу, как уже указано в цитате. Эта ситуация только поднялась с @Async
звонки.
@Async
public void method() {
//get id from session
}
После загрузки приложения метод может использоваться несколькими запросами vaadin и каждый раз ThreadPool
выполняет задачу
Thread - 1 executed method - used session 1
session 1 closed
session 2 defined
Thread - 1 again used to execute method
Thread - 1 executed method - used session 1 instead of new defined session 2
Теперь, в моем случае для каждого запроса vaadin у нас есть новые UI
пример. Но UI
старый поток считал устаревшим, для которого сессия закрыта.
Я внешне прошел UI
экземпляр этого асинхронного метода, как этот.
@Async
public void method(UI ui) {
UI.setCurrent(ui);
UI.getCurrent().getSession();//Now I have latest session
}
Это было также указано в документации UI.setCurrent(UI ui)
метод,
Разработчик приложения также может использовать этот метод для определения текущего пользовательского интерфейса вне обычной обработки запросов, например, при инициализации пользовательских фоновых потоков.
Это означает, что если вы обрабатываете данные в отдельных потоках, у вас не будет текущего сеанса:
Итак, этот код:
Runtime runtime = Runtime.getRuntime();
final Process process = runtime.exec(action);
new Thread() {
public void run() {
try {
System.out.println(VaadinSession.getCurrent());
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
}.start();
Внутри вашего проекта vaadin будет распечатан старый сеанс, который был у вас при запуске Thread.
редактировать
Я думаю, что Vaadin не может предоставить новый сеанс старым потокам, чтобы избежать проблем с повреждением данных. Я имею в виду, если 5 потоков редактируют одну и ту же сессию, у вас будет проблема...
Решение для вас состоит в том, чтобы предоставить Session всем потокам в вашем пуле, но я действительно не знаю, как этого добиться, и Google пока не дал мне ответа.
Изменить: еще одно возможное решение
Создайте класс для хранения каждой сессии (используя SessionListener), используя HashMap<int, VaadinSession>
статично.
Когда вы создаете свои потоки, присвойте им идентификатор сеанса, который им нужно использовать (идентификатор - это ключ, соответствующий вашему сеансу, который вы хотите использовать в HashMap). И затем каждый раз, когда сеанс редактируется, уничтожается и т. Д., Просто редактируйте его в HashMap
,
Из-за статического поведения этого HashMap вы сможете получать к нему доступ из любых потоков в любое время, единственное, что вам понадобится, это int id, соответствующий вашей сессии в потоке.