如何正确使用Future <v>?</v>

时间:2013-08-28 22:05:20

标签: java-ee jsf-2 primefaces

以下代码来自支持bean。 async()从视图中调用<f:event listener="#{nextBean.async}" type="preRenderView"/>。由于我不希望此操作延迟视图的呈现,因此它会在EJB中触发@Asynchronous - 带注释的方法,返回Future<Boolean>
只要此操作正在运行,我希望UI被阻止,因此我执行<p:remoteCommand>触发ready(),检查是否有Future - 对象的结果,这意味着异步方法具有完成然后取消阻止UI 问题:异步方法似乎被ready()第二次调用。我怎样才能实现我的目标?

支持bean:

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。

1 个答案:

答案 0 :(得分:2)

很抱歉,但这种方法没有任何意义。

  1. 每个HTTP请求都会触发preRenderView事件。

    • 首次打开页面计为一个HTTP请求。
    • <p:remoteCommand autoRun="true">计为一个HTTP请求。

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

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

  4. 您没有说明您认为将成为解决方案的具体功能要求,因此很难给出合适的答案或推动您朝着正确的方向前进。我想你需要push