Oscar Calderon
Oscar Calderon

Reputation: 989

Implicit Navigation doesn't work

I have a @ConversationScoped CDI Managed Bean in my JSF application, using Primefaces 5.2 running on Wildfly 8.2.1 . Implicit navigation is just working once in my application. First, i have my index.xhtml which has a button that calls my managed 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>

Next, here is CiudadesManagedBean. As you can see, i start a conversation on @PostConstruct method and it loads a list when i call cargarCiudades from index.xhtml, and finally it loads 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;
    }

}

Finally, the xhtml where i call my method cargar(). I want to invoke that method and then load ciudades/detalle.xhtml because here's my form.

<!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>

When i click on a link inside my datatable, it invokes ciudadMB.cargar() and executes the code inside it, but it ignores the return "ciudades/detalle" . So, implicit navigation works at first time (when i'm on index.xhtml and i click the buttons, it takes me to lista.xhtml) but when i click on a link to go to detalle.xhtml, it ignores it. It just refresh lista.xhtml. Also, I've tried with @SessionScoped and @RequestScoped (always using javax.enterprise.context annotations instead JSF annotations, and removing Conversation object and initialization).

With @SessionScoped it has the same behavior. Pagination works without problems but when i click on the commandLink inside datatable it invokes the action method but ignores the String return.

With @RequestScoped if i click the commandLink it refreshes the page but doesn't invoke the action method. If i put a dummy commandLink outside the datatable it invokes the action method but again, it ignores the String return.

Why Implicit Navigation is not working? Is some CDI issue? Regards.

EDIT: I also changed the annotations to import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; to check if it was about CDI annotations, but it didn't work either, so it isn't a problem of CDI. Do i have to activate something in my configuration to make it work? This is a Eclipse Dynamic Web Project 3.1, JPA 2.1 and JSF 2.2 running on Wildfly 8.2.1 . Here is my web.xml configuration file:

<?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>

And CDI beans.xml file:

<?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>

Upvotes: 0

Views: 1045

Answers (2)

Javier Haro
Javier Haro

Reputation: 1255

You are using relative navigation. Try with

return "detalle";

instead of

return "ciudades/detalle";

Or use absolute navigation instead:

return "/ciudades/detalle";

Upvotes: 2

Oscar Calderon
Oscar Calderon

Reputation: 989

Finally, i tried something: I haven't set JSF parameter "PROJECT_STAGE" in my web.xml file, so i set it in development mode:

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

After that, i've tried again and i got this error:

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.

The problem is that i was using a relative path. The first time, moving from index.xhtml to ciudades/lista.xhtml, it worked without problem because i was in the root path (http:localhost:8094/SistemaFutJsf), but after that, when i was trying to go to ciudades/detalle.xhtml, the application context was this (http:localhost:8094/SistemaFutJsf/ciudades) and because of that it couldn't find /ciudades/ciudades/detalle.xhtml.

So, the solution was to add a slash (/) to make the paths absolute, like this:

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";
    }

Upvotes: 0

Related Questions