@Schedule 无法从 @SessionScoped CDI bean 获取数据
Posted
技术标签:
【中文标题】@Schedule 无法从 @SessionScoped CDI bean 获取数据【英文标题】:@Schedule could not fetch data from @SessionScoped CDI bean 【发布时间】:2020-03-16 16:37:42 【问题描述】:登录后存储在 SessionScoped bean 中的用户数据。 我希望每 5 秒获取存储在会话中的每个帐户并发送到后端。 我的计时器
@Singleton
@Startup
public class FrontendTimer
@Inject
private UserContext userContext;
@Schedule(second = "*/5", minute = "*", hour = "*", persistent = false)
@Asynchronous
public void atSchedule() throws InterruptedException
System.out.println("Get Logged user stored in the session each 5 seconds ");
System.out.println("FR " + userContext.getAccount().toString());
启动调度程序的唯一方法是创建@Startup 和@Singleton 类。 将用户数据保存在前端的唯一方法,将帐户保存到 SessionScoped CDI bean,不推荐使用 JSF 原生 bean。
你会得到如下错误: WELD-001303:范围类型 javax.enterprise.context.SessionScoped 没有活动上下文
项目地址在这里https://github.com/armdev/eap 自己上课https://github.com/armdev/eap/blob/master/eap-web/src/main/java/io/project/app/beans/FrontendTimer.java
基本上我想要一个可以从 Session Scope 获取数据的标准计时器。
【问题讨论】:
抱歉,您的问题完全不清楚。小心澄清。最好用minimal reproducible example 假设 UserContext 是 sessionscoped,如果没有活动用户并且调用了 atSchedule(),它应该选择哪个 UserContext?或者如果有两个用户处于活动状态,因此存在两个 UserContext - 如果两者都应该选择?会话范围仅在处理 servlet 请求的线程中可用。计划的后台作业中没有用户会话上下文。 @Selaron:哇...阅读帖子(不是代码链接)这个问题对我来说完全没有意义。你的评论(问题)说得很清楚。赞美你确实得到了它。 @kukeltje 谢谢。我想我只是快速阅读关键字、代码和错误消息,而不是试图逐字理解所有内容。有时会有所帮助,有时会严重失败._. 【参考方案1】:您当前的方法将无法按预期工作,因为每个调度程序调用都将在与会话完全隔离的上下文中发生(因此出现No active contexts...
错误消息)。
我建议你在这里使用一个简单的反转。在你的应用范围单例中,添加一个简单的List<String> currentSessions
和对应的方法到void add(String account)
和void remove(String account)
。然后@Inject
单例进入会话范围的bean(而不是相反)。最后,添加@WebListener
来处理会话事件。
@Singleton
public class SessionManager
private List<String> currentSessions;
@Schedule(second = "*/5", minute = "*", hour = "*", persistent = false)
@Asynchronous
public void atSchedule() throws InterruptedException
//Do something with currentSessions
public void add(String account)
currentSessions.add(account);
public void remove(String account)
currentSessions.remove(account);
@SessionScoped
public class UserContext implements Serializable
@Inject
private SessionManager sessionManager;
/*
...
*/
public void sessionCreated()
sessionManager.add(account.toString());
public void sessionDestroyed()
sessionManager.remove(account.toString());
@WebListener
public class SessionListener implements HttpSessionListener
@Override
public void sessionCreated(HttpSessionEvent se)
HttpSession session = se.getSession();
FacesContext context = FacesContext.getCurrentInstance();
UserContext userContext = (UserContext) session.getAttribute("userContext");
userContext.sessionCreated();
@Override
public void sessionDestroyed(HttpSessionEvent se)
HttpSession session = se.getSession();
FacesContext context = FacesContext.getCurrentInstance();
UserContext userContext = (UserContext) session.getAttribute("userContext");
userContext.sessionDestroyed();
【讨论】:
是的,完全同意。我使用同样的技术确实能够通过 websockets 向所有登录用户发送消息。 谢谢,我认为这是一个真正的解决方案。以上是关于@Schedule 无法从 @SessionScoped CDI bean 获取数据的主要内容,如果未能解决你的问题,请参考以下文章
请帮忙翻译一下:Effort and schedule slippage for integration & testing