2015-09-04 12 views
5

Mojarra 2.2.12intesa FacesContext dettagli di istanza

Ecco il pezzo di codice presa in consegna l'istanza del FacesContext:

FacesContext context = facesContextFactory.getFacesContext 
       (servletConfig.getServletContext(), request, response, lifecycle); 

L'espressione è perfettamente chiaro. Una volta ricevuta una richiesta, acquisiamo un'informazione globale da essa e creiamo l'istanza FacesContext che la utilizza. Quindi, l'istanza viene creata per ogni richiesta. Ma ottenere l'intance di facesContextFactory mi è sembrato molto più difficile.

// Acquire our FacesContextFactory instance 
try { 
    facesContextFactory = (FacesContextFactory) 
     FactoryFinder.getFactory 
     (FactoryFinder.FACES_CONTEXT_FACTORY); 
} catch (FacesException e) { 
    //others 
} 

Dove

String javax.faces.FactoryFinder.FACES_CONTEXT_FACTORY = "javax.faces.context.FacesContextFactory" 

JavaDocs per la FactoryFinder descrive i cosiddetti

algoritmo scoperta standard per tutti gli oggetti di fabbrica specificati nella JavaServer Faces API.

Questo è quello che mi ha confuso.

Ora, prendiamo in considerazione il metodo effettivo che crea l'istanza di fabbrica: javax.faces.FactoryFinderInstance#getFactory(String factoryName)

try { 
     factoryOrList = factories.get(factoryName); 
     if (!(factoryOrList instanceof List)) { 
      return factoryOrList; 
     } 
} finally { 
     lock.readLock().unlock(); 
} 

Il campo factories viene inizializzato come segue copyInjectionProviderFromFacesContext():

private void copyInjectionProviderFromFacesContext() { 
    InjectionProvider injectionProvider = null; 
    FacesContext context = FacesContext.getCurrentInstance(); //USE FACES CONTEXT!!!!! 
    if (null != context) { 
     injectionProvider = (InjectionProvider) context.getAttributes().get("com.sun.faces.config.ConfigManager_INJECTION_PROVIDER_TASK"); 
    } 
    if (null != injectionProvider) { 
     factories.put(INJECTION_PROVIDER_KEY, injectionProvider); 
    } else { 
     if (LOGGER.isLoggable(Level.SEVERE)) { 
      LOGGER.log(Level.SEVERE, "Unable to obtain InjectionProvider from init time FacesContext. Does this container implement the Mojarra Injection SPI?"); 
     } 
    } 
} 

Così, creando utilizzato FacesContext esempio, ma la fabbrica stessa viene utilizzata per creare lo FacesContext. Non potresti spiegare quel ciclo?

risposta

6

C'è uno speciale "init FacesContext" che è disponibile durante l'inizializzazione del contenitore servlet, assicurando che ci sia almeno "a" FacesContext in giro durante l'inizializzazione JSF. Questo speciale "init FacesContext" ha molte proprietà empty/null/default, in particolare quelle che dipendono dalla richiesta/risposta del servlet HTTP, ma le proprietà relative a applicazioni e configurazioni come quelle disponibili tramite FacesContext#getApplication() sono già disponibili sulla base di a.o. faces-config.xml.

In caso di Mojarra, questo "init FacesContext" è created in a.o. la com.sun.faces.config.FacesInitializer, un'implementazione ServletContainerInitializer che viene eseguita durante l'avvio webapp. In quel momento, vengono create fabbriche.

+0

Quindi, questo è il caso della creazione di InitFacesContext: 'FacesContextFactory privateFacesContextFactory = (FacesContextFactory) FactoryFinder.getFactory (" com.sun.faces.ServletContextFacesContextFactory ");'? Non appare nel [Mojarra 2.2.4] (http://grepcode.com/file/repo1.maven.org/maven2/com.sun.faces/jsf-api/2.2.4/javax/faces/ context/FacesContext.java # FacesContext.getCurrentInstance% 28% 29) sebbene ... –

+0

No, è stato creato in 'FacesInitializer'. Fai clic sul link "creato" nella mia risposta. – BalusC

+0

Come mai ho riscontrato un errore relativo a JSF durante il tentativo di eseguire un'app di Spring su GF 4.1.1 senza alcun riferimento a Mojarra: Info: WebModule [null] ServletContext.log(): Nessun tipo di Spring WebApplicationInitializer rilevato su classpath Info : Inizializzazione di Mojarra 2.2.12 per il contesto '/sm-shop-2.0.3-SNAPSHOT' Severe: impossibile ottenere InjectionProvider da init FacesContext. Questo contenitore implementa il Mojarra Injection SPI? Grave: impossibile chiamare i metodi annotati @PreDestroy perché non è possibile trovare InjectionProvider. Questo contenitore implementa il Mojarra Injection SPI? – developer10