2012-11-08 11 views
7

io sono in grado di ottenere con successo questo a lavorare con il modello in mio app:Ottenere Facelets templates/file da un file system esterno o un database

<ui:decorate template="/WEB-INF/templates/mytemplate.xhtml"> 

Sono anche in grado di muoversi modello per /META-INF/templates/mytemplate.xhtml di un JAR e farlo funzionare:

<ui:decorate template="/templates/mytemplate.xhtml"> 

Mi piacerebbe davvero mettere questo file sul filesystem (o database per quella materia). Come posso raggiungere questo obiettivo? Ho trovato un sacco di cose relative a com.sun.facelets.impl.DefaultResourceResolver, ma non penso che sia in realtà correlato a sostituire la pubblicazione del modello. Non sta cercando di risolvere un URL, sta semplicemente cercando di ottenere il file in qualche modo sul classpath.

risposta

12

Se si è già in JSF 2.2, è possibile farlo fornendo un numero personalizzato ResourceHandler in cui si restituisce la risorsa di visualizzazione desiderata in createViewResource().

public class FaceletsResourceHandler extends ResourceHandlerWrapper { 

    private ResourceHandler wrapped; 

    public FaceletsResourceHandler(ResourceHandler wrapped) { 
     this.wrapped = wrapped; 
    } 

    @Override 
    public ViewResource createViewResource(FacesContext context, final String name) { 
     ViewResource resource = super.createViewResource(context, name); 

     if (resource == null) { 
      resource = new ViewResource() { 
       @Override 
       public URL getURL() { 
        try { 
         return new File("/some/base/path", name).toURI().toURL(); 
        } catch (MalformedURLException e) { 
         throw new FacesException(e); 
        } 
       } 
      }; 
     } 

     return resource; 
    } 

    @Override 
    public ResourceHandler getWrapped() { 
     return wrapped; 
    } 

} 

che è registrata in faces-config.xml come di seguito:

<application> 
    <resource-handler>com.example.FaceletsResourceHandler</resource-handler> 
</application> 

Oppure, se non sei in JSF 2.2 ancora, quindi utilizzare ResourceResolver invece.

public class FaceletsResourceResolver extends ResourceResolver { 

    private ResourceResolver parent; 

    public FaceletsResourceResolver(ResourceResolver parent) { 
     this.parent = parent; 
    } 

    @Override 
    public URL resolveUrl(String path) { 
     URL url = parent.resolveUrl(path); // Resolves from WAR. 

     if (url == null) { 
      try { 
       url = new File("/some/base/path", path).toURI().toURL(); 
      } catch (MalformedURLException e) { 
       throw new FacesException(e); 
      } 

     } 

     return url; 
    } 

} 

che è registrata in web.xml come di seguito:

<context-param> 
    <param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name> 
    <param-value>com.example.FaceletsResourceResolver</param-value> 
</context-param> 

Indipendentemente dal modo in cui, al fine di fornire la risorsa dal database, sia che ci si salva/li cache (temp) sistema di file su disco in modo da poter fornire il URL solo tramite File o inventare un protocollo personalizzato come db:// e fornire un'implementazione personalizzata URLStreamHandlerFactory e URLStreamHandler per eseguire il lavoro effettivo del flusso dal DB. Puoi trovare un esempio di kickoff qui Registering and using a custom java.net.URL protocol.

+0

Ciao BalusC..Questo è stato aiutato a farmi iniziare. Mi sembra che funzioni bene con l'ottenimento di pagine .xhtml. Ma non sembra funzionare con l'uso del modello. Modifica la domanda per mostrare l'errore corrente che sto ottenendo. – JeffJak

+0

Il file apparentemente non esiste. Estendi l'esempio di kickoff per usare il test 'File # exists()' e restituisci 'null' quando non lo fa. – BalusC

+0

Ho capito il problema ... La tua soluzione funziona. Ma dipende da come definisco il modello. Ad esempio se uso template = "myfile.xhtml" fallirà. Ma se faccio template = "/ myfile.xhtml" entrerà nel ResourceResolver. – JeffJak

Problemi correlati