为什么 JSTL-JSF2 在 JSF 2 的视图中存在元数据转换器时不能正常工作



该按钮仅在JSF视图中删除JSTL代码时才调用操作方法,我知道这是生命周期,但我不了解原因/问题。我喜欢逗乐,因为它会导致这种行为。

查看代码工作正常

    <f:metadata>            
<f:viewParam name="idAsociacion" value="#{msgUsuario.asociacion}" converter="#
               {asociacionConverter}"
        converterMessage="#msg['aplicacion.asociacion.error.converter']}" required="true" 
        requiredMessage="#{msg['aplicacion.asociacion.error.required']}" />
<f:viewParam name="idMsg" value="#{msgUsuario.mensajeRespondido}" converter="#
     {mensajeConverter}" converterMessage="#{msg['aplicacion.mensaje.error.converter']}" 
     required="true" requiredMessage="#{msg['aplicacion.mensaje.error.required']}" />
    </f:metadata>
    <ui:decorate template="/WEB-INF/templates/mainUsuario-template.xhtml">
    <ui:define name="title">        
    <h:outputFormat value="#{msg['usuario.escribirMsj.title']}">
        <f:param value="#{msgUsuario.asociacion.nombre}" />
    </h:outputFormat>
    </ui:define>
    <ui:param name="descripcionView" value="#{msg['usuario.escribirMsj.descripcion']}" />
     <ui:define name="content">
<h:panelGroup layout="block"
          id="escribirMensajeContainer"styleClass="escribirMensajeContainer">
    <h:form>
        <p:panelGrid>
        <p:row>
        <p:column>
        <h:outputLabel for="texto" value="#{msg['usuario.escribirMsj.mensaje']}" 
                 styleClass="labelInput" />
        </p:column>
        </p:row>
        <p:row>
        <p:column>
        <p:inputTextarea  autoResize="true" cols="80" rows="15" id="texto" 
             maxlength="500" value="#{msgUsuario.texto}">
        </p:inputTextarea>
            </p:column>
        </p:row>
        <p:row>
    <p:column>
    <h:message for="texto" id="messageMensajeError" styleClass="messageError" />
    </p:column>                         
        </p:row>

        <p:row>         
             <p:column>
    <p:commandButton action="#{msgUsuario.enviar}" 
               alt="#{msg['usuario.escribirMsj.alt.enviar']}" tabindex="2" title="#
      {fn:replace(msg['usuario.escribirMsj.title.enviar'],0,msgUsuario.asociacion.nombre)}" 
       value="#{msg['usuario.escribirMsj.enviar']}" />
</p:column>                         
    </p:row>                            
    </p:panelGrid>
    </h:form>
    </h:panelGroup>         
    </ui:define>
    </ui:decorate>
    </html>

但是,如果我添加 JSTL,我将如何在下面显示。视图呈现正常,因为消息未响应,但按钮从未调用操作方法和视图重新加载。

      <c:choose>
      <c:when test="#{msgUsuario.mensajeRespondido.respondido==false}">
        <h:form>
        <p:panelGrid>
        <p:row>
        <p:column>
        <h:outputLabel for="texto" value="#{msg['usuario.escribirMsj.mensaje']}" 
                 styleClass="labelInput" />
        </p:column>
        </p:row>
        <p:row>
        <p:column>
        <p:inputTextarea  autoResize="true" cols="80" rows="15" id="texto" 
             maxlength="500" value="#{msgUsuario.texto}">
        </p:inputTextarea>
            </p:column>
        </p:row>
        <p:row>
    <p:column>
    <h:message for="texto" id="messageMensajeError" styleClass="messageError" />
    </p:column>                         
        </p:row>

        <p:row>         
             <p:column>
    <p:commandButton action="#{msgUsuario.enviar}" 
               alt="#{msg['usuario.escribirMsj.alt.enviar']}" tabindex="2" title="#
      {fn:replace(msg['usuario.escribirMsj.title.enviar'],0,msgUsuario.asociacion.nombre)}" 
       value="#{msg['usuario.escribirMsj.enviar']}" />
</p:column>                         
    </p:row>                            
    </p:panelGrid>
    </h:form>
    </c:when>
    <c:otherwise>
         <h:outputText value="MESSAGE RESPONSED" />
    </c:otherwise>
    </c:choose>

注意:转换在两种情况下工作正常。

托管豆代码

  @ManagedBean(name="msgUsuario")
  @ViewScoped
  public class EscribirMensajeUsuarioView implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger=Logger.getLogger(EscribirMensajeUsuarioView.class);
private Asociacion asociacion;
private Mensaje mensajeRespondido;
private Usuario usuario;

private String texto;
private boolean usuarioBloqueado;
@ManagedProperty(value="#{mensajeBO}")
private MensajeBO mensajeBo;
@ManagedProperty(value="#{usuarioBO}")
private UsuarioBO usuarioBo;

/* Never invoked with JSTL code in the view */
public String enviar(){
    logger.info("EscribirMensajesUsuarioView.enviar");
    TipoMensaje tipoMensaje=null;
    Mensaje mensaje=this.mensajeRespondido;
    .................
            .................
            .................
      }

/* Getters and Setters */
   }

我读了这个Balusc的评论

"JSF 和 JSTL 不会像你对编码所期望的那样同步运行。JSTL 在视图的构建时(要填充 JSF 组件树时)运行,JSF 在视图组件树的呈现时(生成 HTML 输出时)运行。您可以按如下方式可视化它:JSTL 首先从上到下运行,然后将结果交给 JSF,而 JSF 又再次从上到下运行。

例如,我在 dinamyc 数据表中理解这一点,但在这种情况下并非如此。因为 JSTL 渲染得很好,所以视图是 mensajeRepetido 退出 JSF 树,但按钮不调用该方法。但是,视图重新加载,转换器再次退出 mensajeRepetido

亲切问候。

由于将 JSTL 属性绑定到视图作用域的受管 Bean 属性,因此导致了此问题。仅当部分状态保存处于关闭状态时,此操作才有效。打开部分状态保存(缺省情况下),JSTL 属性将获取其自己的视图范围 Bean 的第二个实例(所有属性都设置为 default!),而不是存储在 JSF 视图状态中并由 JSF 组件使用的实例。

只需使用JSF组件的rendered属性代替通常的方式,并且仅使用JSTL来控制视图的构建,而不是控制视图的呈现。

<h:form rendered="#{not msgUsuario.mensajeRespondido.respondido}">
    ...
<h:form>
<h:panelGroup rendered="#{msgUsuario.mensajeRespondido.respondido}">
     <h:outputText value="MESSAGE RESPONSED" />
</h:panelGroup>      

另请参阅:

  • JSTL in JSF2 Facelets...意义?
  • JSF 2.0 中的通信 - 标记处理程序中的@ViewScoped失败

最新更新