隐式导航不起作用

Posted

技术标签:

【中文标题】隐式导航不起作用【英文标题】:Implicit Navigation doesn't work 【发布时间】:2015-11-15 00:59:14 【问题描述】:

我的 JSF 应用程序中有一个 @ConversationScoped CDI 托管 Bean,使用在 Wildfly 8.2.1 上运行的 Primefaces 5.2。隐式导航在我的应用程序中只工作一次。首先,我的 index.xhtml 有一个按钮,可以调用我的托管 bean CiudadManagedBean:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"
      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"> 

<ui:composition template="/plantilla/template.xhtml">

    <ui:define name="contenido">
    <h:form>
        <p:commandButton action="#ciudadMB.cargarCiudades()"
        value="Mostrar ciudades" />
    </h:form>
    </ui:define>
 </ui:composition>
</html>

接下来,这里是 CiudadesManagedBean。如您所见,我开始使用@PostConstruct 方法进行对话,当我从 index.xhtml 调用 cargarCiudades 时,它会加载一个列表,最后它会加载 ciudades/lista.xhtml:

package com.saplic.fut.beans;

import java.io.Serializable;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Inject;
import javax.inject.Named;

import com.saplic.fut.daos.CiudadDAO;
import com.saplic.fut.entity.Ciudad;

@Named(value="ciudadMB")
@ConversationScoped
public class CiudadManagedBean implements Serializable 

    private static final long serialVersionUID = 7339176875158769385L;

    private Ciudad instance;
    private List<Ciudad> cities;
    private Integer idCity;

    @Inject
    private CiudadDAO ciudadDAO;

    @Inject
    private Conversation conversation;

    @PostConstruct
    public void inicializarConversacion() 
        if(conversation.isTransient())
            conversation.begin();
    

    public Ciudad getInstance() 
        return instance;
    

    public String cargarCiudades() 
        setCities(ciudadDAO.cargarCiudades());
        return "ciudades/lista";
    

    public String cargar() 
        Ciudad flt = new Ciudad();
        flt.setId(getIdCity());
        setInstance(ciudadDAO.cargarDetalle(flt));
        if(getInstance() == null)
            setInstance(new Ciudad());
        return "ciudades/detalle";
    

    public String guardar() 
        ciudadDAO.guardar(getInstance());
        setCities(ciudadDAO.cargarCiudades());
        return "ciudades/lista";
    

    public String actualizar() 
        ciudadDAO.actualizar(getInstance());
        setCities(ciudadDAO.cargarCiudades());
        return "ciudades/lista";
    

    public String eliminar() 
        ciudadDAO.guardar(getInstance());
        setCities(ciudadDAO.cargarCiudades());
        return "ciudades/lista";
    

    public void setInstance(Ciudad instance) 
        this.instance = instance;
    

    public List<Ciudad> getCities() 
        return cities;
    

    public void setCities(List<Ciudad> cities) 
        this.cities = cities;
    

    public Integer getIdCity() 
        return idCity;
    

    public void setIdCity(Integer idCity) 
        this.idCity = idCity;
    


最后,我调用我的方法 cargar() 的 xhtml。我想调用该方法,然后加载 ciudades/detalle.xhtml,因为这是我的表单。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"
      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"> 

<ui:composition template="/plantilla/template.xhtml">

    <ui:define name="contenido">
    <h:form id="frm1">

        <p:dataTable id="tablita" resizableColumns="true" rowIndexVar="rowIdx"
        paginator="true" rows="10" paginatorPosition="bottom" value="#ciudadMB.cities"
        var="ciu" >
            <p:column headerText="Código pais">
                <p:outputLabel value="#ciu.codigoPais" />
            </p:column>
            <p:column headerText="Distrito">
                <p:outputLabel value="#ciu.distrito" />
            </p:column>
            <p:column headerText="Nombre">
                <p:outputLabel value="#ciu.nombre" />
            </p:column>
            <p:column headerText="Población">
                <p:outputLabel value="#ciu.poblacion" />
            </p:column>
            <p:column headerText="Accion">
                <p:commandLink action="#ciudadMB.cargar()" ajax="false" value="Ver" process="@form">
                    <f:setPropertyActionListener value="#ciu.id" target="#ciudadMB.idCity" />
                </p:commandLink>
            </p:column>
        </p:dataTable>
    </h:form>
    </ui:define>
 </ui:composition>
</html>

当我单击数据表中的链接时,它会调用 ciudadMB.cargar() 并执行其中的代码,但它会忽略返回 "ciudades/detalle" 。因此,隐式导航第一次起作用(当我在 index.xhtml 上并单击按钮时,它会将我带到 lista.xhtml)但是当我单击链接以转到 detlle.xhtml 时,它会忽略它。它只是刷新 lista.xhtml。另外,我尝试过使用 @SessionScoped 和 @RequestScoped(总是使用 javax.enterprise.context 注释而不是 JSF 注释,并删除 Conversation 对象和初始化)。

使用@SessionScoped 它具有相同的行为。分页工作没有问题,但是当我单击数据表内的 commandLink 时,它会调用操作方法但忽略字符串返回。

使用@RequestScoped,如果我单击commandLink,它会刷新页面但不会调用操作方法。如果我在数据表之外放置一个虚拟的 commandLink,它会调用 action 方法,但它会再次忽略 String 返回。

为什么?是一些 CDI 问题吗?问候。

编辑:我还将注释更改为 导入 javax.faces.bean.ManagedBean; 导入 javax.faces.bean.SessionScoped; 检查它是否与 CDI 注释有关,但它也不起作用,所以这不是 CDI 的问题。我是否必须在我的配置中激活某些东西才能使其工作?这是在 Wildfly 8.2.1 上运行的 Eclipse Dynamic Web Project 3.1、JPA 2.1 和 JSF 2.2。这是我的 web.xml 配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>SistemaFutJsf</display-name>
  <welcome-file-list>
    <welcome-file>index.xhtml</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/</url-pattern>
    <url-pattern>*.xhtml</url-pattern>
  </servlet-mapping>
  <context-param>
    <param-name>primefaces.THEME</param-name>
    <param-value>cupertino</param-value>
  </context-param>
</web-app>

faces-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<faces-config
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
    version="2.2">

</faces-config>

还有 CDI beans.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       version="1.1" bean-discovery-mode="annotated">

</beans>

【问题讨论】:

您暗示它可以与 JSF 托管 bean 一起正常工作。但是你没有在你的问题中明确证实这一点。请说清楚。此外,您的 bean 实际上是会话范围的,而不是会话范围的。这令人困惑。 对不起,你是对的。我更改为@SessionScoped 以检查它是否是@ConversationScopes 特有的问题,但它也不起作用。我会纠正我的问题。 好的,总结一下,不管bean管理框架如何,也不管bean范围如何,在任何情况下都正确调用了action方法,但是导航结果的返回字符串被完全忽略了,因为它回到同一页面? 没错,它进入了同一页面。在控制台输出中,我没有得到任何输出表明我的字符串返回错误或 xhtml 页面 (ciudades/detalle.xhtml) 不存在。我可以看到刷新,因为我使用的是 ajax="false"。编辑:使用 CDI @RequestScoped,数据表内的 commandLink 不会调用操作方法,但在它之外,它会调用 这里是下载源代码的链接infotomb.com/mx2i6.rar(现在它有JSF注释而不是CDI注释) 【参考方案1】:

您正在使用相对导航。试试

return "detalle";

而不是

return "ciudades/detalle";

或者改用绝对导航:

return "/ciudades/detalle";

【讨论】:

但这意味着我无法在文件夹中分类我的 xhtml,例如,如果我有 /ciudades/detalle 和 /paises/detalle 会发生什么? @BalusC 你能调解这个问题吗?奥斯卡卡尔德隆,我给了你问题的解决方案。你拒绝它基于一个额外的必要条件,无论如何我在最后一行“或者使用绝对导航代替。”。 对不起@lametaweb,我没听明白,当你谈到“绝对导航”时,你是在谈论添加斜线。 谢谢。我已经完成了显示绝对路径的答案。【参考方案2】:

最后,我尝试了一些东西:我的 web.xml 文件中没有设置 JSF 参数“PROJECT_STAGE”,所以我将其设置为开发模式:

<context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
</context-param>

在那之后,我又试了一次,我得到了这个错误:

09:58:58,487 WARNING [javax.enterprise.resource.webcontainer.jsf.application] (default task-21) JSF1064: Unable to find or serve resource, /ciudades/ciudades/detalle.xhtml.

问题是我使用的是相对路径。第一次,从 index.xhtml 移动到 ciudades/lista.xhtml,它没有问题,因为我在根路径 (http:localhost:8094/SistemaFutJsf),但在那之后,当我试图去 ciudades/ detalle.xhtml,应用程序上下文是这样的(http:localhost:8094/SistemaFutJsf/ciudades),因此它找不到/ciudades/ciudades/detalle.xhtml。

因此,解决方案是添加一个斜杠 (/) 以使路径成为绝对路径,如下所示:

public String cargarCiudades() 
        setCities(ciudadDAO.cargarCiudades());
        return "/ciudades/lista";
    

    public String cargar() 
        Ciudad flt = new Ciudad();
        flt.setId(getIdCity());
        setInstance(ciudadDAO.cargarDetalle(flt));
        if(getInstance() == null)
            setInstance(new Ciudad());
        return "/ciudades/detalle";
    

【讨论】:

以上是关于隐式导航不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Makefile 隐式规则不起作用

UPI 隐式意图选择器在 Redmi 设备上不起作用

使用属性键路径为 SCNCamera.fStop 设置动画不起作用,仅在隐式 SCNTransaction 内

粘性导航栏不起作用

从非常量到常量模板参数的隐式转换在 boost::optional 中不起作用

为啥我的导航栏按钮不起作用(我只是一个初学者,对不起......)