隐式导航不起作用
Implicit Navigation doesn't work
我的 JSF 应用程序中有一个 @ConversationScoped CDI Managed 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>
当我单击数据表中的 link 时,它会调用 ciudadMB.cargar() 并执行其中的代码,但它会忽略 return "ciudades/detalle" 。因此,隐式导航在第一次工作时(当我在 index.xhtml 上并单击按钮时,它会带我到 lista.xhtml)但是当我单击 link 转到 detalle.xhtml,它会忽略它。它只是刷新 lista.xhtml。此外,我尝试使用@SessionScoped 和@RequestScoped(总是使用javax.enterprise.context 注释而不是JSF 注释,并删除Conversation 对象和初始化)。
使用@SessionScoped 它具有相同的行为。分页工作没有问题,但是当我单击数据表中的 commandLink 时,它会调用操作方法但会忽略字符串 return。
使用@RequestScoped,如果我单击commandLink,它会刷新页面但不会调用操作方法。如果我将虚拟 commandLink 放在数据表之外,它会调用操作方法,但它会再次忽略字符串 return.
为什么隐式导航不起作用?是一些 CDI 问题吗?问候。
编辑:我还将注释更改为
导入 javax.faces.bean.ManagedBean;
导入 javax.faces.bean.SessionScoped;
查看是不是CDI注解的问题,也没有用,所以不是CDI的问题。我是否必须在我的配置中激活某些东西才能使其工作?这是 Wildfly 8.2.1 上的 Eclipse 动态 Web 项目 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>
面孔-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>
您正在使用相对导航。试试
return "detalle";
而不是
return "ciudades/detalle";
或者改用绝对导航:
return "/ciudades/detalle";
最后,我尝试了一些东西:我没有在我的 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";
}
我的 JSF 应用程序中有一个 @ConversationScoped CDI Managed 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>
当我单击数据表中的 link 时,它会调用 ciudadMB.cargar() 并执行其中的代码,但它会忽略 return "ciudades/detalle" 。因此,隐式导航在第一次工作时(当我在 index.xhtml 上并单击按钮时,它会带我到 lista.xhtml)但是当我单击 link 转到 detalle.xhtml,它会忽略它。它只是刷新 lista.xhtml。此外,我尝试使用@SessionScoped 和@RequestScoped(总是使用javax.enterprise.context 注释而不是JSF 注释,并删除Conversation 对象和初始化)。
使用@SessionScoped 它具有相同的行为。分页工作没有问题,但是当我单击数据表中的 commandLink 时,它会调用操作方法但会忽略字符串 return。
使用@RequestScoped,如果我单击commandLink,它会刷新页面但不会调用操作方法。如果我将虚拟 commandLink 放在数据表之外,它会调用操作方法,但它会再次忽略字符串 return.
为什么隐式导航不起作用?是一些 CDI 问题吗?问候。
编辑:我还将注释更改为 导入 javax.faces.bean.ManagedBean; 导入 javax.faces.bean.SessionScoped; 查看是不是CDI注解的问题,也没有用,所以不是CDI的问题。我是否必须在我的配置中激活某些东西才能使其工作?这是 Wildfly 8.2.1 上的 Eclipse 动态 Web 项目 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>
面孔-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>
您正在使用相对导航。试试
return "detalle";
而不是
return "ciudades/detalle";
或者改用绝对导航:
return "/ciudades/detalle";
最后,我尝试了一些东西:我没有在我的 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";
}