1. Destinazione irraggiungibile, identificativo 'bean' risolto in null
Questo si riduce al fatto che l'istanza del bean gestito non è stata trovata esattamente da quell'identificatore (nome del bean gestito) in EL in questo modo #{bean}
.
L'identificazione della causa può essere suddivisa in tre fasi:
un. Chi gestisce il fagiolo?
b. Qual è il nome (predefinito) del bean gestito?
c. Dov'è la classe del bean di supporto?
1 bis. Chi gestisce il fagiolo?
Il primo passo sarebbe verificare quale framework di gestione dei bean è responsabile della gestione dell'istanza del bean. È JSF via @ManagedBean
? O è CDI via @Named
? O è primavera via @Component
? Puoi assicurarti di non mescolare più annotazioni specifiche del framework di gestione dei bean sulla stessa classe di bean di supporto? Ad esempio @Named @Component
, o @Named @ManagedBean
, o @ManagedBean @Component
. Questo è sbagliato. Il bean deve essere gestito al massimo da un framework di gestione bean e tale framework deve essere configurato correttamente. Se non hai già idea di quale scegliere, vai su Backing bean (@ManagedBean) o CDI Beans (@Named)? e integrazione JSF Spring: come iniettare un componente / servizio Spring nel bean gestito JSF?
Nel caso in cui sia JSF a gestire il bean tramite @ManagedBean
, è necessario accertarsi di quanto segue:
La faces-config.xml
dichiarazione di root è compatibile con JSF 2.0. Quindi il file XSD e il version
must devono almeno specificare JSF 2.0 o versioni successive e quindi non 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">
Per JSF 2.1, basta sostituire 2_0
e 2.0
con 2_1
e2.1
, rispettivamente.
Se utilizzi JSF 2.2 o versioni successive, assicurati di utilizzare gli xmlns.jcp.org
spazi dei nomi anziché java.sun.com
in tutti i luoghi.
<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">
Per JSF 2.3, basta sostituire 2_2
e 2.2
da 2_3
e 2.3
, rispettivamente.
Non hai importato accidentalmente javax.annotation.ManagedBean
invece dijavax.faces.bean.ManagedBean
. Fai attenzione con il completamento automatico IDE, Eclipse è noto per eseguire automaticamente il test di quello errato come primo elemento dell'elenco.
- Non è stato eseguito l'override
@ManagedBean
di una <managed-bean>
voce di stile JSF 1.x nella faces-config.xml
stessa classe di bean di backup insieme a un diverso nome di bean gestito. Questo avrà la precedenza @ManagedBean
. La registrazione di un bean gestito faces-config.xml
non è necessaria poiché JSF 2.0, è sufficiente rimuoverlo.
- Il percorso di classe di runtime è pulito e privo di duplicati nei JAR relativi all'API JSF. Assicurati di non mescolare più implementazioni JSF (Mojarra e MyFaces). Assicurati di non fornire un altro file JAR API JEF o Java EE lungo webapp quando il contenitore di destinazione raggruppa già l'API JSF fuori dalla scatola. Vedi anche la sezione "Installazione di JSF" della nostra pagina wiki JSF JSF per le istruzioni di installazione di JSF. Nel caso in cui si intenda aggiornare JSF in bundle dal contenitore da WAR invece che nel contenitore stesso, assicurarsi di aver incaricato il contenitore di destinazione di utilizzare l'API / impl JSF in bundle di WAR.
- Se si impacchettano i bean gestiti JSF in un JAR, assicurarsi che il JAR abbia almeno un JSF 2.0 compatibile
/META-INF/faces-config.xml
. Vedi anche Come fare riferimento ai bean gestiti JSF forniti in un file JAR?
Se stai effettivamente utilizzando il Jurassic JSF 1.x e non riesci ad aggiornare, allora devi registrare il bean tramite <managed-bean>
in faces-config.xml
invece di @ManagedBean
. Non dimenticare di correggere il percorso di compilazione del tuo progetto in modo tale da non avere più librerie JSF 2.x (in modo che l' @ManagedBean
annotazione non venga compilata in modo confuso con successo).
Nel caso in cui sia il CDI a gestire il bean tramite @Named
, è necessario accertarsi di quanto segue:
CDI 1.0 (Java EE 6) richiede un /WEB-INF/beans.xml
file per abilitare CDI in WAR. Può essere vuoto o può avere solo il seguente contenuto:
<?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) senza alcun beans.xml
, o un beans.xml
file vuoto , o con la precedente CDI 1.0 compatibile beans.xml
si comporterà come CDI 1.0. Quando esiste un CDI 1.1 compatibile beans.xml
con un esplicito version="1.1"
, per impostazione predefinita registrerà solo i @Named
bean con una CDI esplicito scopo di annotazione, come @RequestScoped
, @ViewScoped
, @SessionScoped
, @ApplicationScoped
, ecc Nel caso in cui si ha intenzione di registrare tutti i fagioli come CDI gestito fagioli, anche quelli senza un esplicito Ambito CDI, utilizzare il CDI 1.1 di seguito compatibile /WEB-INF/beans.xml
con bean-discovery-mode="all"
set (l'impostazione predefinita è 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>
Quando si utilizza CDI 1.1+ con bean-discovery-mode="annotated"
(impostazione predefinita), assicurarsi di non aver importato accidentalmente un ambito JSF come al javax.faces.bean.RequestScoped
posto di un ambito CDI javax.enterprise.context.RequestScoped
. Fai attenzione con il completamento automatico IDE.
- Quando si utilizza Mojarra 2.3.0-2.3.2 e CDI 1.1+ con
bean-discovery-mode="annotated"
(impostazione predefinita), è necessario aggiornare Mojarra alla versione 2.3.3 o successiva a causa di un bug . Nel caso in cui non è possibile aggiornare, quindi è necessario sia per set bean-discovery-mode="all"
in beans.xml
, o di mettere la specifica JSF 2.3 @FacesConfig
annotazione su una classe arbitraria nella guerra (in genere una sorta di un'applicazione con scope classe di avvio).
- I contenitori EE non Java come Tomcat e Jetty non vengono spediti con CDI in bundle. È necessario installarlo manualmente. È un po 'più di lavoro che aggiungere semplicemente i JAR della libreria. Per Tomcat, assicurati di seguire le istruzioni in questa risposta: Come installare e utilizzare CDI su Tomcat?
- Il tuo percorso di classe di runtime è pulito e privo di duplicati nei JAR relativi all'API CDI. Assicurati di non mescolare più implementazioni CDI (Weld, OpenWebBeans, ecc.). Assicurati di non fornire un altro file JAR dell'API API EE Java o CDE insieme a webapp quando il contenitore di destinazione raggruppa già l'API CDI immediatamente.
Se si confezionano bean gestiti CDI per le viste JSF in un JAR, assicurarsi che il JAR abbia almeno un valido /META-INF/beans.xml
(che può essere tenuto vuoto).
Nel caso in cui Spring gestisca il bean tramite @Component
, è necessario accertarsi di quanto segue:
La molla viene installata e integrata come da sua documentazione . È importante sottolineare che è necessario almeno avere questo in web.xml
:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
E questo in faces-config.xml
:
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
(sopra tutto quello che so per quanto riguarda Spring - Non lo faccio Spring - sentiti libero di modificare / commentare con altre probabili cause legate a Spring; ad esempio alcuni problemi relativi alla configurazione XML)
Nel caso in cui sia un componente ripetitore che gestisce il bean (nidificato) tramite il suo var
attributo (ad es<h:dataTable var="item">
, <ui:repeat var="item">
, <p:tabView var="item">
, ecc) e in realtà ottenuto un "target irraggiungibile, identificatore 'voce' deliberato di nulla", allora avete bisogno di assicurarsi di quanto segue :
A #{item}
non viene fatto riferimento binding
nell'attributo di alcun componente figlio. Ciò non è corretto poiché l' binding
attributo viene eseguito durante il tempo di creazione della vista, non durante il tempo di rendering della vista. Inoltre, c'è fisicamente un solo componente nell'albero dei componenti che viene semplicemente riutilizzato durante ogni ciclo di iterazione. In altre parole, dovresti effettivamente utilizzare binding="#{bean.component}"
invece di binding="#{item.component}"
. Ma molto meglio è sbarazzarsi del collegamento dei componenti al bean e investigare / chiedere l'approccio corretto per il problema che si pensava di risolvere in questo modo. Vedi anche Come funziona l'attributo 'binding' in JSF? Quando e come dovrebbe essere usato?
1b. Qual è il nome (predefinito) del bean gestito?
Il secondo passo sarebbe verificare il nome del bean gestito registrato. Le convenzioni di utilizzo JSF e Spring sono conformi alle specifiche JavaBeans mentre CDI ha eccezioni a seconda della versione / impl CDI.
Una FooBean
classe di bean di supporto come di seguito,
@Named
public class FooBean {}
avrà in tutti i framework di gestione dei bean un nome di bean gestito predefinito #{fooBean}
, come da specifica JavaBeans.
Una FOOBean
classe di bean di supporto come di seguito,
@Named
public class FOOBean {}
il cui nome di classe non qualificato inizia con almeno due maiuscole in JSF e Spring avrà un nome di bean gestito predefinito esattamente il nome di classe non qualificato #{FOOBean}
, anche conforme alla specificazione JavaBeans. Nel CDI, questo vale anche nelle versioni Weld rilasciate prima di giugno 2015, ma non nelle versioni Weld rilasciate dopo giugno 2015 (2.2.14 / 2.3.0.B1 / 3.0.0.A9) né in OpenWebBeans a causa di una svista in CDI spec . In quelle versioni di saldatura e in tutte le versioni di OWB è solo con il primo carattere in minuscolo #{fOOBean}
.
Se è stato specificato esplicitamente un nome di bean gestito foo
come di seguito,
@Named("foo")
public class FooBean {}
o equivalentemente con @ManagedBean(name="foo")
o @Component("foo")
, quindi sarà disponibile solo da #{foo}
e quindi non da #{fooBean}
.
1 quater. Dov'è la classe del bean di supporto?
Il terzo passo sarebbe il doppio controllo se la classe del bean di backup si trova nel posto giusto nel file WAR compilato e distribuito. Assicurati di aver eseguito correttamente una pulizia completa, ricostruzione, ridistribuzione e riavvio del progetto e del server nel caso in cui tu fossi effettivamente impegnato a scrivere codice e premere con impazienza F5 nel browser. Se ancora invano, lascia che il sistema di generazione produca un file WAR, che poi estrai e controlli con uno strumento ZIP. Il .class
file compilato della classe bean di backup deve risiedere nella struttura del pacchetto in /WEB-INF/classes
. Oppure, quando è impacchettato come parte di un modulo JAR, il JAR che contiene il .class
file compilato deve risiedere /WEB-INF/lib
e quindi non ad es. EAR /lib
o altrove.
Se stai usando Eclipse, assicurati che la classe del bean di supporto sia presente src
e quindi no WebContent
, e assicurati che Progetto> Crea automaticamente sia abilitato. Se stai usando Maven, assicurati che la classe del bean di supporto sia in src/main/java
e quindi non in src/main/resources
o src/main/webapp
.
Se impacchetti l'applicazione Web come parte di una EAR con EJB + WAR (s), devi assicurarti che le classi di bean di supporto siano nel modulo WAR e quindi non nel modulo EAR né nel modulo EJB. Il livello aziendale (EJB) deve essere privo di qualsiasi artefatto relativo al livello Web (WAR), in modo che il livello aziendale sia riutilizzabile su più livelli Web diversi (JSF, JAX-RS, JSP / Servlet, ecc.).
2. Target irraggiungibile, "entità" restituita nulla
Questo si riduce a quello della proprietà nidificataentity
come #{bean.entity.property}
restituita null
. Questo di solito si rivela solo quando JSF deve impostare il valore per property
tramite un componente di input come di seguito, mentre quello #{bean.entity}
effettivamente restituito null
.
<h:inputText value="#{bean.entity.property}" />
È necessario assicurarsi di aver preparato in anticipo l'entità modello in un metodo @PostConstruct
o <f:viewAction>
, o forse un add()
metodo di azione nel caso in cui si stiano lavorando con elenchi CRUD e / o finestre di dialogo nella stessa 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();
}
// ...
}
Quanto all'importanza di @PostConstruct
; farlo in un normale costruttore fallirebbe nel caso in cui si utilizzi un framework di gestione bean che utilizza proxy , come CDI. Utilizzare sempre @PostConstruct
per agganciare l'inizializzazione dell'istanza del bean gestito (e utilizzare @PreDestroy
per agganciare la distruzione dell'istanza del bean gestito). Inoltre, in un costruttore non avresti ancora accesso alle dipendenze iniettate, vedi anche NullPointerException mentre provi ad accedere al bean @Inject nel costruttore .
Nel caso in cui entityId
venga fornito tramite <f:viewParam>
, è necessario utilizzare <f:viewAction>
invece di @PostConstruct
. Guarda anche Quando usare f: viewAction / preRenderView contro PostConstruct?
Devi anche assicurarti di preservare il non null
modello durante i postback nel caso in cui lo stai creando solo con un add()
metodo di azione. Il più semplice sarebbe inserire il bean nell'ambito della vista. Vedi anche Come scegliere l'ambito bean giusto?
3. Target non raggiungibile, "null" restituito null
Questo ha effettivamente la stessa causa del n. 2, solo l'implementazione EL (precedente) utilizzata è in qualche modo difettosa nel preservare il nome della proprietà da visualizzare nel messaggio di eccezione, che alla fine è stato erroneamente esposto come 'null'. Questo rende il debug e la correzione un po 'più difficili solo se hai proprietà nidificate come queste#{bean.entity.subentity.subsubentity.property}
.
La soluzione è sempre la stessa: assicurarsi che l'entità nidificata in questione non lo sia null
, a tutti i livelli.
4. Target irraggiungibile, '' 0 '' ha restituito null
Ciò ha anche la stessa causa del n. 2, solo l'implementazione EL (precedente) utilizzata è errata nella formulazione del messaggio di eccezione. Questo espone solo quando si utilizza la notazione di parentesi graffa []
in EL come in #{bean.collection[index]}
cui la #{bean.collection}
stessa non è nulla, ma l'elemento nell'indice specificato non esiste. Tale messaggio deve quindi essere interpretato come:
Target irraggiungibile, 'collection [0]' ha restituito null
La soluzione è la stessa di # 2: assicurati che l'elemento di raccolta sia disponibile.
5. Target irraggiungibile, "BracketSuffix" restituito null
Questo ha in realtà la stessa causa del n. 4, solo l'implementazione EL (precedente) utilizzata è in qualche modo difettosa nel preservare l'indice di iterazione da visualizzare nel messaggio di eccezione, che alla fine ha erroneamente esposto come 'BracketSuffix' che è davvero il personaggio ]
. Questo rende il debug e la correzione solo un po 'più difficile quando hai più elementi nella raccolta.
Altre possibili cause di javax.el.PropertyNotFoundException
: