【发布时间】:2014-05-21 01:03:22
【问题描述】:
在完成长时间的用户上传处理后,我需要接收一个事件。我需要为用户会话设置返回值,以便我可以正确地显示它。我正在尝试做一些 CDI 魔术,如下所述:http://piotrnowicki.com/2013/05/asynchronous-cdi-events/#toc-solution-3-ejb-producer-and-cdi-consumer (Async EJB Producer -> CDI Consumer)。
第一次尝试
来电者和接收者:
@SessionScoped
public class UploadController implements Serializable {
private static final long serialVersionUID = 1L;
private final Logger logger = Logger.getLogger(this.getClass());
@EJB
private StatelessBeanLocal statelessBean;
@Inject
private SomeSessionCdi cdi;
private Future<UploadedDTO> futureDto;
public void observeUpload(@Observes(during = TransactionPhase.AFTER_COMPLETION) UploadFinishedEvent event) {
logger.trace("Recived CDI event: %s", event);
// FIXME: without @SessionScoped i'm reaching here, but futureDto == null
cdi.setStateAfterUpload(dto);
}
public void upload(ByteArrayOutputStream baos, User user, UploadedFileInfo info) {
logger.trace("Initiating an async upload processing of %s", info);
futureDto = statelessBean.upload(baos, user);
logger.trace("Initialized an async upload processing of %s", info);
}
}
处理器:
@Stateless
public class StatelessBean implements StatelessBeanLocal {
@Inject
private transient Event<UploadFinishedEvent> eventTrigger;
@Asynchronous
public Future<UploadedDTO> upload(ByteArrayOutputStream baos, User user) {
UploadedEntity entity = Unpacker.unpackBaos(baos);
logger.trace("Uploaded file for: %s", entity);
// [..] Long processing here
// Invoking Thread.sleep(5000); to simulate a long process
Thread.sleep(5000);
UploadedDTO dto = null; // here a real value, of course
logger.debug("Finished processing of upload for: %s", entity);
eventTrigger.fire(new UploadFinishedEventImpl());
logger.trace("After firing a CDI event for finished upload for: %s", entity);
return new AsyncResult<>(dto);
}
// [..]
}
如果 CDI bean 有 @SessionScoped 注释,那么我得到:SEVERE: WELD-000401 Failure while notifying an observer of event org.example.StatelessBean$UploadFinishedEventImpl@54c03555
如果 CDI bean 没有 @SessionScoped 注释,那么我得到了 futureDto == null
第二次尝试
将 EJB bean 更改为更改日志但仍然无效:
更改了无状态 EJB:
@Stateless
public class StatelessBean implements StatelessBeanLocal {
@Inject
private transient Event<UploadFinishedEvent> eventTrigger;
@Resource
private SessionContext sctx;
@Asynchronous
public Future<UploadedDTO> upload(ByteArrayOutputStream baos, User user) {
UploadedEntity entity = Unpacker.unpackBaos(baos);
logger.trace("Uploaded file for: %s", entity);
// [..] Long processing here
// Invoking Thread.sleep(5000); to simulate a long process
Thread.sleep(5000);
UploadedDTO dto = null; // here a real value, of course
logger.debug("Finished processing of upload for: %s", entity);
sctx.getBusinessObject(TemplateSetBeanLocal.class).fireUploadFinished();
logger.trace("After firing a CDI event for finished upload for: %s", entity);
return new AsyncResult<>(dto);
}
@Asynchronous
public void fireUploadFinished() {
logger.debug("Before firing an UploadFinishedEvent: %s", sctx.getCallerPrincipal().toString());
eventTrigger.fire(new UploadFinishedEventImpl());
logger.debug("After firing an UploadFinishedEvent: %s", sctx.getCallerPrincipal().toString());
}
// [..]
}
日志:
FINE:完成上传处理:[sample-0.1.0-SNAPSHOT.zip,application/zip,75,80KB,3cgvet] 最好:触发 CDI 事件以完成上传后:[sample-0.1.0-SNAPSHOT.zip,application/zip,75,80KB,3cgvet] FINE:在触发 UploadFinishedEvent 之前:admin FINE:触发 UploadFinishedEvent 后:admin 严重:没有用于注入 org.example.UploadController 的有效 EE 环境 最好:收到 CDI 事件:org.example.StatelessBean$UploadFinishedEventImpl@72514572有可能吗?
【问题讨论】:
标签: jakarta-ee asynchronous cdi ejb-3.1 weld