0

下面的代码来自一个支持 bean。async()从视图中被 调用<f:event listener="#{nextBean.async}" type="preRenderView"/>。由于我不希望此操作延迟视图的呈现,因此它会触发@AsynchronousEJB 中的 -annotated 方法返回Future<Boolean>.
只要此操作正在运行,我就希望 UI 被阻止,因此我执行一个<p:remoteCommand>触发ready()检查是否有Future-Object 的结果,这意味着异步方法已完成,然后解除对 UI 的阻止。
问题:异步方法似乎被ready(). 我怎样才能实现我想要做的事情?

后备豆:

package mypackage;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.java.Log;

@ManagedBean
@ViewScoped
@Getter
@Setter
public class NextBean {

    @EJB private AsyncBean asyncBean;
    private Future<Boolean> ready;

    public void async() {
        ready = asyncBean.async();
    }

    public void ready() {
        try {
            while (ready.get() != true) {
                Thread.sleep(300);
            }
        } catch (InterruptedException | ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

Facelets 代码:

<html xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body id="wholeView">
    <f:metadata>
        <f:event listener="#{nextBean.async}" type="preRenderView"></f:event>
    </f:metadata>
        <p:blockUI id="blockui" block=":wholeView" widgetVar="blockUI">
            please wait
    </p:blockUI>
    <h:form>
    <p:remoteCommand onstart="blockUI.show();"
        name="doIt"
        id="dooo"
        process="@this"
        action="#{nextBean.ready}"
        oncomplete="blockUI.hide();"
        autoRun="true"
    />

    </h:form>
    CONTENT
</h:body>
</html>

EJB:

package mypackage;

import java.util.concurrent.Future;

import javax.ejb.AsyncResult;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;

import lombok.extern.java.Log;

@Stateless
@Log
public class AsyncBean {

    @Asynchronous
    public Future<Boolean> async(){
        try {
            Thread.sleep(3000);
            return new AsyncResult<Boolean>(true);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }

}

更新:
1. 用户被引导到外部页面的视图(作为支付过程的一部分)。
2. 请求视图业务逻辑应该被执行,它不应该延迟视图的呈现,而是在业务逻辑执行时阻塞它的 UI。

4

1 回答 1

2

对不起,但这种方法没有任何意义。

  1. preRenderView事件在每个 HTTP 请求上触发。

    • 第一次打开页面算作一个 HTTP 请求。
    • <p:remoteCommand autoRun="true">算作一个 HTTP 请求。

    因此,实际上,当您打开此页面时,会触发 2 个 HTTP 请求。这解释了为什么preRenderView会调用两次侦听器方法。

  2. @Asynchronous在这种情况下完全没用。您正在调用与调用该方法Future#get()的线程完全相同的线程。@Asynchronous在通话和Future#get(). 基本上,您正在阻塞当前线程并告诉它等到另一个线程完成。当前线程基本无所事事,不能用于其他任务,这是一个很大的浪费。这有什么意义?为什么不通过删除在当前线程中完成工作@Asynchronous

您没有说明您认为将是解决方案的具体功能要求,因此很难给出合适的答案或将您推向正确的方向。我猜你需要push

于 2013-08-29T01:44:08.343 回答