1. Destino inalcanzable, identificador 'bean' resuelto a nulo
Esto se reduce a que la instancia de bean administrado en sí no se pudo encontrar exactamente por ese identificador (nombre de bean administrado) en EL así #{bean}
.
La identificación de la causa se puede dividir en tres pasos:
a. ¿Quién está manejando el frijol?
si. ¿Cuál es el nombre de bean administrado (predeterminado)?
C. ¿Dónde está la clase de bean de respaldo?
1a. ¿Quién está manejando el frijol?
El primer paso sería verificar qué marco de administración de beans es responsable de administrar la instancia de bean. ¿Es JSF vía @ManagedBean
? ¿O es a través de CDI@Named
? ¿O es Spring via @Component
? ¿Puede asegurarse de que no está mezclando anotaciones específicas del marco de administración de múltiples beans en la misma clase de bean de respaldo? Por ejemplo @Named @Component
, o @Named @ManagedBean
, o @ManagedBean @Component
. Esto está mal. El bean debe ser administrado como máximo por un marco de administración de bean y ese marco debe estar configurado correctamente. Si ya no tiene idea de cuál elegir, diríjase a Backing beans (@ManagedBean) o CDI Beans (@Named)? e integración Spring JSF: ¿cómo inyectar un componente / servicio Spring en JSF bean gestionado?
En caso de que sea JSF quien administre el bean vía @ManagedBean
, entonces debe asegurarse de lo siguiente:
La faces-config.xml
declaración raíz es compatible con JSF 2.0. Por lo tanto, el archivo XSD y el version
deben al menos especificar JSF 2.0 o superior y, por lo tanto, no 1.x.
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
Para JSF 2.1, simplemente reemplace 2_0
y 2.0
por 2_1
y2.1
respectivamente.
Si utiliza JSF 2.2 o superior, asegúrese de utilizar xmlns.jcp.org
espacios de nombres en lugar de java.sun.com
todos los lugares.
<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">
Para JSF 2.3, simplemente reemplace 2_2
y 2.2
por 2_3
y 2.3
respectivamente.
No importaste accidentalmente en javax.annotation.ManagedBean
lugar dejavax.faces.bean.ManagedBean
. Tenga cuidado con el autocompletado IDE, se sabe que Eclipse sugiere automáticamente el incorrecto como primer elemento de la lista.
- No reemplazó la entrada de
@ManagedBean
estilo JSF 1.x en la misma clase de bean de respaldo junto con un nombre de bean administrado diferente. Este tendrá prioridad sobre . No es necesario registrar un bean administrado desde JSF 2.0, simplemente elimínelo.<managed-bean>
faces-config.xml
@ManagedBean
faces-config.xml
- Su classpath en tiempo de ejecución está limpio y libre de duplicados en JAR relacionados con API JSF. Asegúrese de no mezclar múltiples implementaciones JSF (Mojarra y MyFaces). Asegúrese de no proporcionar otro archivo JAR JSF API o Java EE API junto con la aplicación web cuando el contenedor de destino ya incluye la API JSF de fábrica. Consulte también la sección "Instalación de JSF" de nuestra página wiki de JSF de JSF para obtener instrucciones de instalación de JSF. En caso de que tenga la intención de actualizar JSF empaquetado en contenedor desde WAR en lugar de en el contenedor en sí, asegúrese de haber indicado al contenedor de destino que use API / impl JSF empaquetado en WAR.
- Si empaqueta beans gestionados JSF en un JAR, asegúrese de que el JAR tenga al menos un JSF 2.0 compatible
/META-INF/faces-config.xml
. Consulte también ¿Cómo hacer referencia a los beans gestionados JSF que se proporcionan en un archivo JAR?
Si en realidad está utilizando el JSF jurásico 1.x, y no puede actualizar, entonces necesita registrar el bean vía <managed-bean>
en faces-config.xml
lugar de @ManagedBean
. No olvide corregir la ruta de compilación de su proyecto de modo que ya no tenga bibliotecas JSF 2.x (para que la @ManagedBean
anotación no se compile con éxito de forma confusa).
En caso de que sea CDI quien administre el bean vía @Named
, entonces debe asegurarse de lo siguiente:
CDI 1.0 (Java EE 6) requiere un /WEB-INF/beans.xml
archivo para habilitar CDI en WAR. Puede estar vacío o puede tener solo el siguiente contenido:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
CDI 1.1 (Java EE 7) sin ninguno beans.xml
, o un beans.xml
archivo vacío , o con el CDI 1.0 anterior compatible beans.xml
se comportará igual que CDI 1.0. Cuando hay un CDI 1.1 compatible beans.xml
con una explícita version="1.1"
, entonces será por defecto registro de sólo @Named
granos con un CDI anotación explícita alcance tales como @RequestScoped
, @ViewScoped
, @SessionScoped
,@ApplicationScoped
, etc. En caso de que la intención de registrar a todos los granos como CDI habas logró, incluso aquellos sin una explícita Alcance CDI, use el CDI 1.1 a continuación compatible /WEB-INF/beans.xml
con el bean-discovery-mode="all"
conjunto (el valor predeterminado es bean-discovery-mode="annotated"
).
<?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="all">
</beans>
Cuando use CDI 1.1+ con bean-discovery-mode="annotated"
(predeterminado), asegúrese de no importar accidentalmente un ámbito JSF como, por ejemplo, en javax.faces.bean.RequestScoped
lugar de un ámbito CDI javax.enterprise.context.RequestScoped
. Cuidado con el autocompletado IDE.
- Cuando se usa Mojarra 2.3.0-2.3.2 y CDI 1.1+ con
bean-discovery-mode="annotated"
(predeterminado), entonces necesita actualizar Mojarra a 2.3.3 o posterior debido a un error . En caso de que no se puede actualizar, entonces usted necesita ya sea a conjunto bean-discovery-mode="all"
en beans.xml
, o para poner el concreto JSF 2.3 @FacesConfig
anotación en una clase arbitraria en el GUERRA (generalmente algún tipo de aplicación en el ámbito clase de arranque).
- Los contenedores que no son Java EE como Tomcat y Jetty no se entregan con CDI incluido. Necesita instalarlo manualmente. Es un poco más de trabajo que simplemente agregar la biblioteca JAR (s). Para Tomcat, asegúrese de seguir las instrucciones de esta respuesta: ¿Cómo instalar y usar CDI en Tomcat?
- Su classpath en tiempo de ejecución está limpio y libre de duplicados en los JAR relacionados con la API CDI. Asegúrese de no mezclar múltiples implementaciones de CDI (Weld, OpenWebBeans, etc.). Asegúrese de no proporcionar otro CDI o incluso un archivo JAR API Java EE a lo largo de la aplicación web cuando el contenedor de destino ya incluye la API CDI de fábrica.
Si está empaquetando beans gestionados CDI para vistas JSF en un JAR, asegúrese de que el JAR tenga al menos un valor válido /META-INF/beans.xml
(que puede mantenerse vacío).
En caso de que sea Spring quien gestione el bean a través de@Component
, entonces debe asegurarse de lo siguiente:
Spring se está instalando e integrando según su documentación . Es importante destacar que al menos debe tener esto en web.xml
:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Y esto en faces-config.xml
:
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
(lo anterior es todo lo que sé con respecto a Spring, no hago Spring, siéntase libre de editar / comentar con otras causas probables relacionadas con Spring; por ejemplo, algunos problemas relacionados con la configuración de XML)
En caso de que sea un componente repetidor quién administra el grano (anidado) a través de su var
atributo (por ejemplo <h:dataTable var="item">
, <ui:repeat var="item">
,<p:tabView var="item">
, etc.) y que en realidad tiene un "objetivo inalcanzable, identificador 'tema' resuelto nulo", entonces usted necesita para asegurarse de lo siguiente :
No #{item}
se hace referencia a la binding
atribución de ningún componente secundario. Esto es incorrecto ya que el binding
atributo se ejecuta durante el tiempo de construcción de la vista, no durante el tiempo de representación de la vista. Además, físicamente solo hay un componente en el árbol de componentes que simplemente se reutiliza durante cada ronda de iteración. En otras palabras, en realidad deberías estar usando en binding="#{bean.component}"
lugar de binding="#{item.component}"
. Pero mucho mejor es deshacerse por completo de la unión de componentes a bean e investigar / preguntar el enfoque adecuado para el problema que pensó resolver de esta manera. Consulte también ¿Cómo funciona el atributo 'vinculante' en JSF? ¿Cuándo y cómo debe usarse?
1b. ¿Cuál es el nombre de bean administrado (predeterminado)?
El segundo paso sería verificar el nombre de bean administrado registrado. Las convenciones de uso de JSF y Spring cumplen con la especificación JavaBeans, mientras que CDI tiene excepciones dependiendo de la versión / impl CDI.
Una FooBean
clase de bean de respaldo como a continuación,
@Named
public class FooBean {}
en todos los marcos de administración de beans tendrá un nombre de bean administrado predeterminado de #{fooBean}
, según la especificación JavaBeans.
Una FOOBean
clase de bean de respaldo como a continuación,
@Named
public class FOOBean {}
cuyo nombre de clase no calificado comience con al menos dos mayúsculas tendrá en JSF y Spring un nombre de bean administrado predeterminado exactamente del nombre de clase no calificado #{FOOBean}
, también se ajusta a la especificación JavaBeans. En CDI, este también es el caso en las versiones de Weld lanzadas antes de junio de 2015, pero no en las versiones de Weld lanzadas después de junio de 2015 (2.2.14 / 2.3.0.B1 / 3.0.0.A9) ni en OpenWebBeans debido a una supervisión en CDI spec . En esas versiones de Weld y en todas las versiones de OWB, solo es con el primer carácter en minúscula #{fOOBean}
.
Si ha especificado explícitamente un nombre de bean administrado foo
como el siguiente,
@Named("foo")
public class FooBean {}
o equivalentemente con @ManagedBean(name="foo")
o @Component("foo")
, entonces solo estará disponible por #{foo}
y por lo tanto no por #{fooBean}
.
1c. ¿Dónde está la clase de bean de respaldo?
El tercer paso sería una doble verificación si la clase de bean de respaldo está en el lugar correcto en el archivo WAR construido e implementado. Asegúrese de haber realizado correctamente una limpieza completa, reconstruir, volver a implementar y reiniciar el proyecto y el servidor en caso de que estuviera realmente ocupado escribiendo código y presionando impacientemente F5 en el navegador. Si todavía es en vano, deje que el sistema de compilación produzca un archivo WAR, que luego extrae e inspecciona con una herramienta ZIP. El .class
archivo compilado de la clase de bean de respaldo debe residir en su estructura de paquete en /WEB-INF/classes
. O bien, cuando está empaquetado como parte de un módulo JAR, el JAR que contiene el .class
archivo compilado debe residir /WEB-INF/lib
y, por lo tanto, no, por ejemplo, EAR/lib
ni en ningún otro lugar.
Si está utilizando Eclipse, asegúrese de que la clase de bean de respaldo esté dentro src
y, por lo tanto WebContent
, no , y asegúrese de que Project> Build Automatically esté habilitado. Si está utilizando Maven, asegúrese de que la clase de bean de respaldo esté en src/main/java
y por lo tanto no en src/main/resources
o src/main/webapp
.
Si está empaquetando la aplicación web como parte de un EAR con EJB + WAR (s), entonces debe asegurarse de que las clases de beans de respaldo estén en el módulo WAR y, por lo tanto, no en el módulo EAR ni en el módulo EJB. El nivel empresarial (EJB) debe estar libre de artefactos relacionados con el nivel web (WAR), de modo que el nivel empresarial sea reutilizable en varios niveles web diferentes (JSF, JAX-RS, JSP / Servlet, etc.).
2. Destino inalcanzable, 'entidad' devuelta nulo
Esto se reduce a que la propiedad anidadaentity
como en #{bean.entity.property}
devuelto null
. Esto generalmente solo se expone cuando JSF necesita establecer el valor a property
través de un componente de entrada como el siguiente, mientras que en #{bean.entity}
realidad se devuelve null
.
<h:inputText value="#{bean.entity.property}" />
Debe asegurarse de haber preparado la entidad modelo de antemano en un método @PostConstruct
o <f:viewAction>
método, o tal vez un add()
método de acción en caso de que esté trabajando con listas y / o cuadros de diálogo CRUD en la misma vista.
@Named
@ViewScoped
public class Bean {
private Entity entity; // +getter (setter is not necessary).
@Inject
private EntityService entityService;
@PostConstruct
public void init() {
// In case you're updating an existing entity.
entity = entityService.getById(entityId);
// Or in case you want to create a new entity.
entity = new Entity();
}
// ...
}
En cuanto a la importancia de @PostConstruct
; hacer esto en un constructor normal fallaría en caso de que esté utilizando un marco de administración de beans que usa proxies , como CDI. Siempre use @PostConstruct
para conectar la inicialización de la instancia de bean administrado (y use @PreDestroy
para conectar la destrucción de la instancia de bean administrado). Además, en un constructor aún no tendría acceso a ninguna dependencia inyectada, consulte también NullPointerException al intentar acceder a @Inject bean en el constructor .
En caso de que entityId
se suministre a través de <f:viewParam>
, deberá usar en <f:viewAction>
lugar de @PostConstruct
. Consulte también ¿ Cuándo usar f: viewAction / preRenderView versus PostConstruct?
También debe asegurarse de preservar el no null
modelo durante las devoluciones en caso de que lo esté creando solo con un add()
método de acción. Lo más fácil sería poner el bean en el alcance de la vista. Consulte también ¿Cómo elegir el alcance de frijol correcto?
3. Objetivo inalcanzable, 'nulo' devuelto nulo
En realidad, esto tiene la misma causa que el n. ° 2, solo la implementación EL (más antigua) que se está utilizando es algo defectuosa para preservar el nombre de la propiedad que se mostrará en el mensaje de excepción, que finalmente se expone incorrectamente como 'nulo'. Esto solo hace que la depuración y la corrección sean un poco más difíciles cuando tienes algunas propiedades anidadas como esta#{bean.entity.subentity.subsubentity.property}
.
La solución sigue siendo la misma: asegúrese de que la entidad anidada en cuestión no lo sea null
, en todos los niveles.
4. Destino inalcanzable, '' 0 '' devuelto nulo
Esto también tiene la misma causa que el n. ° 2, solo la implementación de EL (más antigua) que se usa tiene errores al formular el mensaje de excepción. Esto se expone solo cuando usa la notación de llaves []
en EL como en #{bean.collection[index]}
donde el #{bean.collection}
sí mismo no es nulo, pero el elemento en el índice especificado no existe. Dicho mensaje debe interpretarse como:
Destino inalcanzable, 'colección [0]' devuelto nulo
La solución también es la misma que la n.º 2: asegúrese de que el elemento de la colección esté disponible.
5. Objetivo inalcanzable, 'BracketSuffix' devuelto nulo
En realidad, esto tiene la misma causa que el n. ° 4, solo la implementación de EL (más antigua) que se está utilizando es un poco defectuosa para preservar el índice de iteración para mostrar en el mensaje de excepción, que finalmente se expone incorrectamente como 'BracketSuffix', que es realmente el personaje ]
. Esto solo hace que la depuración y la reparación sean un poco más difíciles cuando tienes varios elementos en la colección.
Otras posibles causas de javax.el.PropertyNotFoundException
: