2016-08-04 51 views
0

Ich habe eine Stateless-Anmeldeseite, wie BalusC in this answer vorschlägt. Wenn ich f:viewParam oder f:viewAction einschließe, wird meine Aktionsmethode nicht aufgerufen.Aktionsmethode, die nicht in der transienten Ansicht aufgerufen wird, einschließlich viewParam oder viewAction

Ich habe bereits this answer gelesen, um meinen Code zu debuggen, aber ich konnte das Problem nicht identifizieren.

Hier ist ein Beispielcode, der das Problem reproduziert. Wenn Sie auf die Schaltfläche klicken, wird "Angemeldet" auf der Konsole gedruckt. Aber wenn ich entweder f:viewParam oder f:viewAction in login.xhtml auskommentiere, wird die Methode nicht mehr aufgerufen.

login.xhtml

<ui:composition template="./WEB-INF/templates/template.xhtml" 
       xmlns="http://www.w3.org/1999/xhtml" 
       xmlns:ui="http://java.sun.com/jsf/facelets" 
       xmlns:h="http://java.sun.com/jsf/html" 
       xmlns:f="http://xmlns.jcp.org/jsf/core"> 

    <ui:define name="metadata" > 
     <f:metadata> 
      <!-- uncomment one of these to reproduce the issue 
      <f:viewParam name="test" required="false"/> 
      <f:viewAction action="#{AuthenticationBean.sayHello()}"/> 
      --> 
     </f:metadata> 
    </ui:define> 

    <ui:define name="main_content"> 
     <f:view transient="true"> 
      <h:form> 
       <h:commandButton value="Login" 
           action="#{AuthenticationBean.login()}" /> 
      </h:form> 
     </f:view> 
    </ui:define> 

</ui:composition> 

template.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:h="http://java.sun.com/jsf/html" 
     xmlns:f="http://java.sun.com/jsf/core"> 

    <f:view locale="en" contentType="text/html" > 

     <ui:insert name="metadata"/> 

     <h:head> 
     </h:head> 

     <h:body id="body"> 
      <h:messages/> 
      <ui:insert name="main_content" /> 
     </h:body> 

    </f:view> 
</html> 

AuthenticationBean.java

import javax.enterprise.context.RequestScoped; 
import javax.inject.Named; 

@Named("AuthenticationBean") 
@RequestScoped 
public class AuthenticationBean { 

    public String login() { 
     System.out.println("Logged in"); 
     return ""; 
    } 

    public void sayHello() { 
     System.out.println("Hello"); 
    } 

} 

web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<web-app version="3.1" 
     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-app_3_1.xsd"> 
    <context-param> 
     <param-name>javax.faces.PROJECT_STAGE</param-name> 
     <param-value>Development</param-value> 
    </context-param> 
    <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>/test/*</url-pattern> 
    </servlet-mapping> 
    <welcome-file-list> 
     <welcome-file>test/login.xhtml</welcome-file> 
    </welcome-file-list> 
    <listener> 
     <listener-class> 
      org.jboss.weld.environment.servlet.Listener 
     </listener-class> 
    </listener> 
</web-app> 

Könnte mir jemand erklären, was schief läuft? Und wie man es repariert?

Ich verwende Mojarra 2.2.13 auf Tomcat läuft 8.

Antwort

1

Die f:viewParam ist eine Stateful-Komponente, sie speichert die Werte im Ansichtszustand. Im Quellcode der UIViewParameter können wir dies sehen.

@Override 
public Object getSubmittedValue() { 
    return getStateHelper().get(PropertyKeys.submittedValue); 
} 

@Override 
public void setSubmittedValue(Object submittedValue) { 
    getStateHelper().put(PropertyKeys.submittedValue, submittedValue); 
} 

Siehe den Artikel Stateless vs Stateful JSF view parameters für weitere Details.

Für die f:viewAction bin ich nicht sicher, ob es wirklich Stateful ist, aber im Quellcode von UIViewAction können wir sehen, dass viele Eigenschaften in der State-Helfer gespeichert sind.

Als Workaround für die f:viewAction in einer statusfreien Ansicht können wir das preRenderView-Ereignis verwenden.

login.xhtml

<f:metadata> 
    <f:event type="preRenderView" listener="#{AuthenticationBean.sayHello()}"/> 
</f:metadata> 

Wir auch Anforderungsparameter innerhalb der sayHello Methode greifen können.

AuthenticationBean.java

public void sayHello() { 
    System.out.println("Hello"); 
    FacesContext facesContext = FacesContext.getCurrentInstance(); 
    ExternalContext externalContext = facesContext.getExternalContext(); 
    Map<String, String> requestParameterMap = 
           externalContext.getRequestParameterMap(); 
    if (requestParameterMap.containsKey("test")) { 
     String test = requestParameterMap.get("test"); 
     System.out.println("Test parameter: " + test); 
    } 
} 

Und auch die Navigation durchzuführen.

AuthenticationBean.java

public void sayHello() { 
    System.out.println("Hello"); 
    FacesContext facesContext = FacesContext.getCurrentInstance(); 
    facesContext.getApplication().getNavigationHandler() 
         .handleNavigation(facesContext, null, "mypage"); 
}