Nobody?Итак, это мое решение.Я не уверен, если это большой жирный обходной путь или просто способ сделать это.
Так как метод @Asynchronous не может получить доступ к контексту сеанса, и, следовательно, также нет сессионных компонентов (по крайней мере, я не знаю, как, я всегда получал ConcurrentModificationErrors или подобные), я создал Singleton ProgressEJB, который содержит HashMap:
@Singleton @LocalBean @Startup
public class ProgressEJB {
private HashMap<String, Integer> progressMap = new HashMap<String, Integer>
// getters and setters
}
Эта хэш-карта должна отображать SessionId (String) в целочисленное значение (прогресс 0-> 100).Таким образом, пользовательский сеанс связан с прогрессом.В моем EmailEJB я внедряю этот ProgressEJB, а в своем методе @Asynchronous я увеличиваю значение каждый раз, когда отправляется электронное письмо:
@Stateful @LocalBean
public class EmailEJB {
@Inject
private ProgressEJB progress;
// Mail-Settings
...
@Asynchronous
public void sendEmails(user:User, message:Message, sessionId:String) {
progress.progressMap.put(sessionId, 0);
for (int i=0; i<mails.size; i++) {
sendMail(mails[i])
progress.getProgressMap().put(sessionId, (i / mails.size) * 100)
}
progress.getProgressMap().remove(sessionId);
}
Идентификатор сеанса приходит из моего управляемого (Weld) компонентапри вызове функции:
@SessionScoped
@Named
public class EmailManager {
@Inject
private ProgressEJB progress;
@Inject
private FacesContext facesContext;
private String sessionId;
@PostConstruct
private void setSessionId() {
this.sessionId = ((HttpSession)facesContext.getExternalContext().getSession(false)).getId();
}
public Integer getProgress() {
if (progress.getProgressMap().get(sessionId) == null)
return 100;
else
return progress.getProgressMap().get(sessionId);
}
}
Теперь я могу получить доступ к прогрессу из EmailManager из моего представления JSF с помощью Ajax Polling, сообщая пользователю, сколько писем уже отправлено.Только что проверил это с 2 пользователями, кажется, работает.