2012-04-27 35 views
11

tengo unas pocas páginas que necesita un nombre de usuario para trabajar, por lo tanto el siguiente código:Manejo de los parámetros de vista en JSF después del post

userpage.xhtml

<!-- xmlns etc. omitted --> 
<html> 
<f:metadata> 
    <f:viewParam name="userId" value="#{userPageController.userId}"/> 
</f:metadata> 
<f:view contentType="text/html"> 
<h:head> 
</h:head> 
<h:body> 
    <h:form> 
     <h:commandButton action="#{userPageController.doAction}" value="post"/> 
    </h:form> 
</h:body> 
</f:view> 

userPageController.java

@Named 
@ViewScoped 
public class userPageControllerimplements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Inject protected SessionController sessionController; 
    @Inject private SecurityContext securityContext; 
    @Inject protected UserDAO userDAO; 

    protected User user; 
    protected Long userId; 

    public UserPage() { 
    } 

    public User getUser() { 
     return user; 
    } 

    public void setUser(User user) { 
     this.user = user; 
    } 

    public Long getUserId() { 
     return userId; 
    } 

    public void setUserId(Long userId) { 
     if(!FacesContext.getCurrentInstance().isPostback()){ 
      User u = userDAO.find(userId); 
      this.userId = userId; 
      this.user = u; 
     } 
    } 

    public void doAction(){ 

    } 

} 

Sin embargo, después de llamar a doAction, el parámetro de vista en la url desaparece. El bean todavía funciona debido a su naturaleza viewcoped, pero arruina mis intentos de navegación futura. Cuando busco, me da la impresión de que el parámetro de vista debe permanecer después de una publicación y leer userpage.jsf? UserId = 123, pero este no es el caso. ¿Cuál es realmente el comportamiento previsto?

En relación con esto, traté de implementar la adición automática de parámetros de vista al navegar a otra página donde deseo mantener el ID de usuario. Parece que funciona para otros, pero para mí, el ID de usuario en ViewRoot siempre es nulo. Código de abajo utiliza para recuperar el viewparameter (Sé que podría utilizar mi ID de usuario se almacena temporalmente en el grano para la navegación, pero esta solución sería mucho más elaborado):

String name = "userId"; 
    FacesContext ctx = FacesContext.getCurrentInstance(); 
    ViewDeclarationLanguage vdl = ctx.getApplication().getViewHandler().getViewDeclarationLanguage(ctx, viewId); 
    ViewMetadata viewMetadata = vdl.getViewMetadata(ctx, viewId); 
    UIViewRoot viewRoot = viewMetadata.createMetadataView(ctx); 
    UIComponent metadataFacet = viewRoot.getFacet(UIViewRoot.METADATA_FACET_NAME); 

    // Looking for a view parameter with the specified name 
    UIViewParameter viewParam = null; 
    for (UIComponent child : metadataFacet.getChildren()) { 
     if (child instanceof UIViewParameter) { 
      UIViewParameter tempViewParam = (UIViewParameter) child; 
      if (name.equals(tempViewParam.getName())) { 
       viewParam = tempViewParam; 
       break; 
      } 
     } 
    } 

    if (viewParam == null) { 
     throw new FacesException("Unknown parameter: '" + name + "' for view: " + viewId); 
    } 

    // Getting the value 
    String value = viewParam.getStringValue(ctx); // This seems to ALWAYS be null. 

Una última reflexión es que los métodos setter todavía parecen trabajo, setUserId se llama con el valor correcto en la publicación.

¿He entendido por completo cómo funcionan los parámetros de vista, o hay algún tipo de error aquí? Creo que mi caso de uso debería ser extremadamente común y tener soporte básico en el marco.

Respuesta

25

cuando busco la vuelta, me da la impresión de que el parámetro de vista debe permanecer después de leer un post de este modo userpage.jsf? Userid = 123, pero este no es el caso. ¿Cuál es realmente el comportamiento previsto?

Este comportamiento es correcto. El <h:form> genera un elemento HTML <form> con una acción URL sin ningún parámetro de vista. La solicitud POST solo envía exactamente a esa URL. Si tiene la intención de mantener los parámetros de la vista en la URL, entonces hay básicamente 3 formas:

  1. traer un poco de la magia de AJAX.

    <h:commandButton action="#{userPageController.doAction}" value="post"> 
        <f:ajax execute="@form" render="@form" /> 
    </h:commandButton> 
    

    De esta manera la página solicitada inicialmente y por lo tanto también la petición de URL en la barra de direcciones del navegador sigue siendo el mismo todo el tiempo.

  2. Si corresponde (por ejemplo, para la navegación de página a página), hágala una solicitud GET y use includeViewParams=true. Puede utilizar <h:link> y <h:button> para esto:

    <h:button outcome="nextview?includeViewParams=true" value="post" /> 
    

    Sin embargo, esto tiene una seguridad EL explotar en las versiones mayores de Mojarra 2.1.6. Asegúrese de estar utilizando Mojarra 2.1.6 o posterior. Vea también issue 2247.

  3. Controle la generación de acción URL de <h:form> usted mismo.Proporcione un ViewHandler personalizado (solo extienda ViewHandlerWrapper) en donde hace el trabajo en getActionURL().

    public String getActionURL(FacesContext context, String viewId) { 
        String originalActionURL = super.getActionURL(context, viewId); 
        String newActionURL = includeViewParamsIfNecessary(context, originalActionURL); 
        return newActionURL; 
    } 
    

    Para conseguir que se ejecute, registrarla en faces-config.xml de la siguiente manera:

    <application> 
        <view-handler>com.example.YourCustomViewHandler</view-handler> 
    </application> 
    

    Esto es también lo OmniFaces<o:form> está haciendo. Es compatible con una includeViewParams atributo adicional que incluye todos los parámetros de vista de URL de acción de la forma:

    <o:form includeViewParams="true"> 
    

actualización: la obtención de la vista parámetros de la vista actual mediante programación (que es básicamente su segunda pregunta) se debe hacer de la siguiente manera:

Collection<UIViewParameter> viewParams = ViewMetadata.getViewParameters(FacesContext.getCurrentInstance().getViewRoot()); 

for (UIViewParameter viewParam : viewParams) { 
    String name = viewParam.getName(); 
    Object value = viewParam.getValue(); 
    // ... 
} 
+0

Creo tercera es opciones conocidas. – kosa

+0

Probablemente usaré 1. para manejar el problema de la barra url. Aproximadamente 2: sería una solución limpia para ver el manejo de los parámetros, pero solo funciona cuando se usa el mismo bean administrado para 2 páginas (algo que creo que normalmente es una mala opción), por lo que es inútil. Lo más probable es que termine definiendo los parámetros manualmente en cada enlace. ¿Tiene alguna idea de que el código en la parte inferior no funciona? Obtener el parámetro de vista programáticamente que es. –

+0

Es porque estás creando una vista completamente nueva y en lugar de usar la vista actual. Ver respuesta actualizada. – BalusC

0

Estoy en lo cierto que para la solución 1 a <f:ajax execute="@form" render="@form" /> w ork uno también tiene que incluir algo como

<f:param name="userId" value="#{userPageController.userId}"/> 

dentro del <h:commandButton>?

Como se describe en https://stackoverflow.com/a/14026995/811046

Cuestiones relacionadas