1

当线程中发生异常时,我想在浏览器中显示友好的错误消息。我在 xhtml 页面中有(类似于 h:message)。只要消息来自同一个线程,它就会显示消息,但在这种情况下不起作用。如何在不持有线程的情况下使其工作,因为该方法应该异步执行?

public void start(final Land lan)
    {
        try {
            Future future = executor.submit(new Callable(){
                @Override
                public Object call() {
                    try {
                        conversion.processLand(lan);
                        LOG.debug("Finished the execution serverion");
                        uploadLandPages(lan.getPages(),
                                lan.getLandOID());
                    }catch(LanException doc){
                        LOG.error("LanException is caused due to "+doc.getMessage());
                        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,"File Conversion Issue","Unfortunately we cannot convert this file, please try again later"));
                    } catch (ApplicationException apx) {
                        LOG.error("ApplicationException is caused due to "+apx.getMessage());
                        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,"File Conversion Issue", "We have successfully converted the file but couldn't save in our server"));
                    }

                    return null;
                }
            });
        } catch(Exception e){
            LOG.error("Exception caused in the thread which converts the doc due to {}",e.getMessage());
            throw new RuntimeException("Couldn't create the Conversion thread");
        }
            finally {
            executor.shutdown();
        }
    }
4

1 回答 1

4

它不起作用,因为消息必须进入 HTTP 响应。当您离开服务于 HTTP 请求的线程以异步运行时,您显然会失去对 HTTP 响应的控制。更重要的FacesContext是,在其他线程中根本不可用。特定代码只会以NullPointerException.

你基本上有两个选择:

  1. 使用轮询。你可以使用<p:poll>它。只要不存在非空消息,就会间隔轮询会话范围的 bean。然后删除并显示它并停止轮询。执行器服务应该将消息设置为该会话范围 bean 的属性。

  2. 使用推。您可以为此使用<p:socket>(PrimePush)。执行者应该在一个唯一的频道名称上设置消息,该频道名称由(对当前用户唯一!或者它可能反映给所有用户)PushContext#push()标识。<p:socket channel>


与具体问题无关,因为您似乎已经在使用 Java EE @Asynchronous,如果可能的话,我建议使用 EJB 方法而不是执行器服务。这样,线程由容器本身管理和池化。

于 2013-06-18T14:04:47.063 回答