2015-08-21 33 views
0

我在我的JSF應用程序中使用了在Wildfly 8.2.1上運行的Primefaces 5.2的@ConversationScoped CDI託管Bean。隱式導航只在我的應用程序中工作過一次。首先,我有我的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; 
    } 

} 

最後,XHTML其中i打電話給我的方法cargar()。我想調用該方法,然後加載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),但是當我點擊一個鏈接去detalle.xhtml,它忽略它。它只是刷新lista.xhtml。另外,我已經使用@SessionScoped和@RequestScoped(總是使用javax.enterprise.context註釋來代替JSF註釋,並刪除對話對象和初始化)。

使用@SessionScoped它具有相同的行爲。分頁工作沒有問題,但是當我點擊數據表中的commandLink時,它會調用操作方法,但忽略字符串返回。

使用@RequestScoped如果我單擊commandLink,它會刷新頁面但不會調用操作方法。如果我在數據表外部放置了一個虛擬commandLink,它會調用操作方法,但又會忽略字符串返回。

爲什麼隱式導航不起作用?是否有一些CDI問題?問候。

編輯:我也改變了註釋到 import javax.faces.bean.ManagedBean; import 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> 

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> 
+0

你暗示,它正常工作與JSF託管bean。但你沒有明確證實你的問題。請澄清。另外,您的bean實際上是會話作用域而不是對話作用域。這很混亂。 – BalusC

+0

對不起,你是對的。我更改爲@ SessionScoped來檢查它是否是@ ConversationScopes特有的問題,但它也不起作用。我會糾正我的問題。 –

+0

好的,總結一下,無論bean管理框架如何,也不管bean的作用域如何,操作方法在任何情況下都可以正確調用,但導航結果的返回字符串會被完全忽略,因爲它會返回到同一頁面? – BalusC

回答

2

您正在使用相對導航。與

return "detalle";

,而不是

return "ciudades/detalle";

一次或使用絕對導航來代替:

return "/ciudades/detalle";

+0

但是這意味着我無法將我的xhtml歸類到文件夾中,例如,如果我有/ ciudades/detalle和/ paises/detalle會發生什麼情況? –

+0

@BalusC你可以請這個問題進行調解嗎? 奧斯卡卡爾德隆,我給你解決你的問題。你根據一個附加條件拒絕它,無論如何我在最後一行覆蓋了這個必要條件「或者使用絕對導航。」 – lametaweb

+0

對不起@lametaweb,當你談到關於添加斜槓的「絕對導航」時,我沒有那麼明白。 –

0

最後,我想的東西:我還沒有設置JSF參數「我的web.xml文件」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"; 
    }