jsf 2 - Error PrettyFaces con el atributo requerido
jsf-2 navigation (1)
Estoy desarrollando una aplicación web usando JSF 2 y bondades . @ViewScoped
uno de mis beans @ViewScoped
con bonitas anotaciones. Eso es lo que tengo:
@ManagedBean
@ViewScoped
@URLMapping(parentId = "app-list", id = "app-view", pattern = "/detail/#{appId}",
viewId = "/system/manage_app/content/app_detail/app_detail.xhtml")
public class NavegableAppView extends SystemNavegable {
/**
Básicamente eso muestra los detalles de una aplicación que está instalada en mi sistema. Este bean se puede instanciar de dos maneras, pasando #{appId}
param, que indica el id de la aplicación que deseo cargar, o sin ese parámetro, en este caso el bean recuperará este id de un bean @SessionScoped
.
Así es como la página /system/manage_app/content/app_detail/app_detail.xhtml
está administrando el parámetro:
<ui:composition 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:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui"
template="/templates/general_template.xhtml">
<ui:define name="metadata">
<f:metadata>
<f:viewParam id="appId" name="appId"
value="#{navegableAppView._ParamApp}" required="false" />
<f:event type="preRenderView"
listener="#{navegableAppView.initialize}" />
</f:metadata>
</ui:define>
<ui:define name="general_content">
<p:panel>
<!--More stuff-->
El problema aquí es que quiero que se cree el bean NavegableAppView
, con o sin param. Lo he intentado de esta manera <p:button value="prueba" outcome="pretty:app-view" />
que funciona pero me limita a hacer nada más que el resultado y también <p:commandButton value="prueba2" action="pretty:app-view" ajax="false" />
, que es el equivalente a llamar a un método de acción y devolver el caso de navegación ( eso es lo que realmente quiero ).
La primera opción crea el bean correctamente y carga el valor de la sesión. Segundo caso, me está dando este error:
HTTP 500 - PrettyFaces: Exception occurred while building URL
for MappingId < app-view >, Required value < #{appId} > was null
Entonces, mi bean objetivo no está siendo construido. He intentado agregar el parámetro manualmente al caso de navegación: return pretty:app-view?appId=1
y funciona, pero quiero que el bean objetivo lo recupere de la sesión misma. ¿Tengo que llamar a un redireccionamiento o algo así en mi método de acción?
Reúna sus ideas.
Entonces, en realidad te encuentras con uno de los efectos de "borde" de PrettyFaces. El parámetro "appId" que ha definido se trata en realidad como un nombre de parámetro, y también como una ubicación de valor de bean EL para construir enlaces.
@URLMapping(parentId = "app-list", id = "app-view", pattern = "/detail/#{appId}",
viewId = "/system/manage_app/content/app_detail/app_detail.xhtml")
Cuando utiliza la funcionalidad de navegación de devolución de datos de PrettyFaces, requiere un nombre de bean EL. Ahora, sucede que dado que no ha proporcionado uno en su anotación @URLMapping
, PrettyFaces intentará usar el nombre del parámetro de todos modos, y espera que pueda encontrar lo que desea. En este caso, obviamente, no hay ningún valor de frijol llamado #{appId}
.
Realmente está mezclando dos tipos de funcionalidad que intentan resolver el mismo problema. Sus definiciones <f:metadata>
y <f:viewParam>
hacen lo mismo que PrettyFaces con sus parámetros de ruta y métodos de acción. Deberías usar uno u otro mecanismo. Si realmente quieres mezclarlos, entonces como dijiste, deberías invocar la navegación real desde tu <h:commandButton>
, así:
<p:commandButton value="prueba2" action="#{navegableAppView.goToAppId}" ajax="false" />
Luego, deberá asegurarse de devolver una cadena de navegación JSF2 válida CON el parámetro appId
, como por ejemplo:
public String goToAppId() {
return "/system/manage_app/content/app_detail/app_detail.xhtml?faces-redirect=true&appId=" + appId";
}
PrettyFaces comprenderá que está redireccionando a una URL que ha sido asignada, y realizará la reescritura de salida en la URL y, en su lugar, lo enviará a la /detail/#{addId}
. Esto está todo en los documentos.
La última opción sería simplemente eliminar los <f:metadata>
y <f:viewParam>
, y usar la funcionalidad PrettyFaces incorporada para administrar los parámetros de vista en su lugar. Simplemente eliminar los metadatos y actualizar su @URLMapping
a esto, resolvería su problema:
@ManagedBean
@ViewScoped
@URLMapping(parentId = "app-list", id = "app-view", pattern = "/detail/#{appId : navegableAppView._ParamApp}",
viewId = "/system/manage_app/content/app_detail/app_detail.xhtml")
public class NavegableAppView extends SystemNavegable {
@URLAction
public String initialize() {
if ( appId != null ) {
this.item = appsDB.findById(appId);
return null;
}
// Add a message here, "The item {..} could not be found."
return "pretty:app-list";
}
Así es como inicializas las páginas usando PrettyFaces. Cuando se trata de eso, si está usando pretty:mappingId
navigation, solo debería usar las funciones PrettyFaces. Si va a utilizar navegación normal de estilo JSF2 donde especifica la id de la vista y todos los parámetros de la URL, puede mezclar y combinar (siempre que use parámetros de ruta con nombre en sus asignaciones de URL).
Espero que esto ayude.