¿Cómo navegar en JSF? Cómo hacer que la URL refleje la página actual (y no la anterior)

Actualmente estoy aprendiendo JSF y me sorprendió y desconcerté cuando me di cuenta de que cada vez que usamos , el comportamiento estándar de JSF es mostrarme siempre la URL de la página anterior en el navegador, en lugar de la URL de la página actual .

Entiendo que esto tiene que ver con la forma en que JSF siempre publica un formulario en la misma página y luego simplemente muestra la página que el controlador le devuelve al navegador que no sabe que la ubicación de la página ha cambiado.

Parece que JSF ha existido lo suficiente como para que haya una forma limpia y sólida de lidiar con esto. Si es así, ¿te importaría compartir?

He encontrado varias soluciones, pero lamentablemente nada que parezca una solución sólida real.

  • Simplemente acepte que la URL es engañosa.
  • Agregar "?faces-redirect=true" al valor de retorno de cada acción de bean y luego
    • Descubre cómo reemplazar @RequestScoped con algo más (Ámbitos Flash, conversación CDI, @SessionScoped, …).
    • acepte tener dos viajes de ida y vuelta HTTP para cada acción del usuario.
  • Utilice algún método (por ejemplo, biblioteca de terceros o código personalizado) para ocultar el nombre de la página en la URL, siempre usando la misma URL genérica para cada página.

Si "?faces-redirect=true" es lo mejor posible, ¿hay alguna forma de configurar una aplicación completa para tratar todas las solicitudes de esta manera?

De hecho, JSF, al ser una aplicación basada en formularios dirigida al marco MVC, envía el formulario POST a la misma URL donde se solicitó el formulario con la página . Puede confirmarlo mirando la URL

del resultado HTML generado. Esto es en términos de desarrollo web caracterizados como devolución de datos . Una navegación en una devolución de datos no causa de manera predeterminada una nueva solicitud a la nueva URL, sino que carga la página de destino como contenido de la respuesta. Esto de hecho es confuso cuando simplemente desea la navegación de página a página.

En general, el enfoque correcto en cuanto a la navegación / redirección depende de los requisitos del negocio y la idempotencia (léase: “bookmarkability”) de la solicitud.

  • Si la solicitud es idempotente, solo use un formulario / enlace GET en lugar del formulario POST (es decir, use

    , o lugar de y ).
    Por ejemplo, navegación de página a página, formulario de búsqueda similar a Google, etc.

  • Si la solicitud no es idempotente, simplemente muestre los resultados de forma condicional en la misma vista (es decir, devuelva null o void y utilice, por ejemplo, y / o rendered ).
    Por ejemplo, entrada / edición de datos, asistente de pasos múltiples, diálogo modal, formulario de confirmación, etc.

  • Si la solicitud no es idempotente, pero la página de destino es idempotente, simplemente envíe una redirección después de POST (es decir, devuelva el resultado con ?faces-redirect=true o ).
    Por ejemplo, mostrando la lista de todos los datos después de una edición exitosa, redirigir después de iniciar sesión, etc.

Tenga en cuenta que la navegación pura página a página suele ser idempotente y aquí es donde muchos iniciadores JSF fallan al abusar de los enlaces de comando / botones para eso y luego se quejan de que las URL no cambian. También tenga en cuenta que los casos de navegación son muy raramente utilizados en aplicaciones del mundo real que se desarrollan con respecto a SEO / UX y aquí es donde muchos tutoriales JSF fallan al permitir que los lectores crean lo contrario.

También tenga en cuenta que el uso de POST no es “más seguro” que GET porque los parámetros de solicitud no son visibles inmediatamente en la URL. Todavía son visibles en el cuerpo de solicitud HTTP y aún manipulables. Así que no hay absolutamente ninguna razón para preferir POST para solicitudes idempotentes por el bien de la “seguridad”. La seguridad real consiste en usar HTTPS en lugar de HTTP y verificar los métodos de servicio comercial si el usuario actualmente conectado puede consultar la entidad X o manipular la entidad X, etc. Un marco de seguridad decente ofrece anotaciones para esto.

Ver también:

  • ¿Cuál es la diferencia entre redirigir y navegación / reenviar y cuándo usar qué?
  • JSF navegación implícita vs. explícita
  • Bookmarkability a través de la característica View Parameters
  • ¿Para qué pueden usarse , y ?
  • ¿Cuándo debería usar h: outputLink en lugar de h: commandLink?
  • Creación de páginas de detalles maestros para las entidades, cómo vincularlas y qué ámbito de bean elegir
  • Retención de parámetros de cadena de consulta de solicitud GET en el envío de formulario JSF
  • Pase un objeto entre @ViewScoped beans sin usar los parámetros GET