2017-10-02 1 views
1

私はJSF 2.3の新機能を味わってみました。魅力的なのはwebsocketです。JSF 2.3 websocketがf:ajax actionlisenterでAjaxとどのように動作するのですか?

私はmojarraテストとJSF 2.3固有の@Push javadocからいくつかのサンプルコードを読みました。

f:websocketf:ajaxを使用すると問題が発生しました。

のFaceletsテンプレートは次のとおりです。

<h:panelGroup id="messagePanel" layout="block"> 
     <ul> 
      <ui:repeat value="#{ajaxBean.messages}" var="m"> 
       <li>#{m}</li> 
      </ui:repeat> 
     </ul> 
    </h:panelGroup> 

    <h:form id="form"> 
     <h:commandButton 
      id="sendMessage" 
      action="#{ajaxBean.sendMessage()}" 
      value="Send Ajax Message"> 
      <f:ajax/> 
     </h:commandButton> 
    </h:form> 
    <h:form> 
     <f:websocket channel="ajaxChannel" scope="view"> 
      <f:ajax event="ajaxEvent" render=":messagePanel" /> 
     </f:websocket> 
    </h:form> 
    <h:form> 
     <f:websocket channel="ajaxListenerChannel" scope="view"> 
      <f:ajax event="ajaxListenerEvent" listener="#{ajaxBean.ajaxPushed}" render=":messagePanel" /> 
     </f:websocket> 
    </h:form> 

    <f:websocket channel="commandScriptChannel" scope="view" onmessage="onCommandScript"/> 
    <h:form> 
     <h:commandScript name="onCommandScript" action="#{ajaxBean.commandScriptExecuted()}" render=":messagePanel"/> 
    </h:form> 

とバックエンドBeanは次のとおりです。

@ViewScoped 
@Named("ajaxBean") 
public class AjaxBean implements Serializable { 

    private static final Logger LOG = Logger.getLogger(AjaxBean.class.getName()); 

    @Inject 
    @Push 
    PushContext ajaxChannel; 

    @Inject 
    @Push 
    PushContext ajaxListenerChannel; 

    @Inject 
    @Push 
    PushContext commandScriptChannel; 

    private List<String> messages = new ArrayList<>(); 

    public void ajaxPushed(AjaxBehaviorEvent e) throws AbortProcessingException{ 
     LOG.log(Level.INFO, "ajax pushed: " + e.toString()); 

     messages.add("ajaxListenerEvent is sent at: " + LocalDateTime.now()); 

     ajaxListenerChannel.send("ajaxListenerEvent"); 
    } 

    public void commandScriptExecuted() { 
     LOG.log(Level.INFO, "commandScriptExecuted pushed."); 

     messages.add("commandScriptExecuted message is sent at: " + LocalDateTime.now()); 

     commandScriptChannel.send("onCommandScript"); 
    } 

    public void sendMessage() { 
//  LOG.log(Level.INFO, "ajax pushed by button: " + e.toString()); 

     messages.add("ajaxEvent is sent at: " + LocalDateTime.now()); 

     ajaxChannel.send("ajaxEvent"); 
    } 

    public List<String> getMessages() { 
     return messages; 
    } 

    public void setMessages(List<String> messages) { 
     this.messages = messages; 
    } 

} 

結果は、必要に応じて最初のボタンは、Ajaxの出力をトリガすることができます。しかし、f:リスナーとのajaxは動作しません.h:commandScriptもここでは動作しません。

これを修正するにはどうすればよいですか?

+0

あなたのコードでは、明示的にそれらのチャンネルにプッシュしているところはありませんか?さらに、それらのチャンネルは、独自のajax /コマンドリスナーによってのみプッシュされます!私はあなたが達成しようとしていることを理解していません。 – BalusC

+0

@BalusC f:ajax 'listener'に** push **アクションを追加し、h:commandScript' action'を追加しました。 '@ Push' javadocは複雑なUIを扱うためにf:ajaxを使ったf:websocketの使い方を説明しています。私はf:webocketとf:ajaxまたはh:commandScriptを使用して、バックエンドアクションを実行してコンテンツを自動的に追加します。この目的をアーカイブすることはできますか?または私はf:webscoket/f:ajaxの使い方を誤解しています。 – Hantsy

+0

@BalusC [コード](https://github.com/hantsy/ee8-sandbox/tree/master/jsf-websocket)を更新しました。余分なボタンを使用してajax信号をチャンネルにプッシュすると動作します。 – Hantsy

答えて

3

具体的な問題は、コード内に明示的にプッシュメッセージを送信していないためです。あなたの試みが何らかの形で可能だった場合、websocketはプッシュメッセージを無限ループで送信し続けます。これは意味をなさない。

プッシュメッセージを明示的に送信するには、<h:commandButton>と同じようにコードに明示的にpush.send(message)をコールさせる必要があります。

<h:form> 
    <h:commandButton value="Send push message" action="#{bean.sendPushMessage}"> 
     <f:ajax /> 
    </h:commandButton> 
</h:form> 
<h:form> 
    <f:websocket channel="pushWithAjaxUpdate" scope="view"> 
     <f:ajax event="updateMessages" listener="#{bean.updateMessages}" render=":messages" /> 
    </f:websocket> 
</h:form> 
<h:panelGroup id="messages" layout="block"> 
    <ul> 
     <ui:repeat value="#{bean.messages}" var="message"> 
      <li>#{message}</li> 
     </ui:repeat> 
    </ul> 
</h:panelGroup> 

@Inject @Push 
private PushContext pushWithAjaxUpdate; 

public void sendPushMessage() { 
    messages.add("Push message is sent at: " + LocalDateTime.now()); 
    pushWithAjaxUpdate.send("updateMessages"); 
} 

public void updateMessages() { 
    messages.add("Ajax event is received at: " + LocalDateTime.now()); 
} 

私はあなただけで実験していることを理解し、上記のアプローチは、いずれかの実世界のコードでは意味がありませんと言うべきです。 <f:websocket>は、この特定の使用例では余計であり、<h:commandButton><f:ajax listener="...">を使用するだけで十分です。実際のコードでは、プッシュが同じページのコマンドボタンによって同期的に呼び出されるのではなく、という非同期的には、ビジネスイベントによって呼び出されるということになります。そうでなければ、Ajaxレスポンス自体の結果を返すことができます。これにより、サーバーへの追加のラウンドトリップが節約されます。

+0

ありがとう、私はすでにこの方法を試していた。 – Hantsy

関連する問題