2010-11-04 5 views
5

Ho filtri come quelli definiti di seguito. Eseguono lo stesso blocco di codice in vari punti, quindi per mantenerlo ASCIUTTO ho rifattorizzato quel codice in un metodo chiamato doResponse().Chiamata di rendering() da un metodo di filtro helper in Grails

class MyFilters { 

    def filters = { 
     web(uri: '/web/**') { 
      before = { 

       // Do Stuff 
       if (condition) { 
        doResponse(request, response, params) 
       } 
       return true 
      } 
      after = { 
       if (condition) { 
        doResponse(request, response, params) 
       } 
       else { 
        // Do Stuff 
        doResponse(request, response, params) 
       } 

      } 
      afterView = { 
      } 
     } 
    } 

    boolean doResponse(request, response, params) { 
    // Do Stuff 
     render(status: statusCode, contentType: "text/xml", encoding: "ISO-8859-1", text: text) 
    // Do post-render stuff 
     return false 
    } 
} 

Tuttavia questo ha un effetto collaterale sgradevole. Sembra che il metodo render() sia disponibile solo all'interno della chiusura dei filtri. C'è un modo (pulito) per me di chiamare render() da doResponse()?

Edit: L'errore che ottengo è:

groovy.lang.MissingMethodException: No firma del metodo: MyFilters.render() è applicabile per tipi di argomenti: i valori (java.util.LinkedHashMap): [[Stato : 500, contentType: text/xml, codifica: ISO-8859-1, testo: ...]]

risposta

8

passare l'oggetto che definisce il metodo render(..) al metodo doRespond(..), e richiamare il metodo render(..) su quell'oggetto.

Le chiusure hanno un numero di implicit variables, incluso il loro owner che si riferisce alla chiusura del genitore; in modo che possiamo passare che:

if (condition) { 
    doResponse(owner, request, response, params) 
} 

doRespond(..) metodo:

boolean doResponse(webFilter, request, response, params) { 
    // Do Stuff 
    webFilter.render(status: statusCode, contentType: 
     "text/xml", encoding: "ISO-8859-1", text: text) 
    // Do post-render stuff 
    return false 
} 
+0

ciao ho provato a farlo, ma ottenendo: java.lang.NullPointerException: Impossibile impostare la proprietà 'viewName' su oggetto nullo \t a java.lang.Thread.run (Thread.java:680) –

0

È possibile passare un riferimento alla funzione render alla funzione doResponse?

cioè:

if(condition) { 
    doResponse(request, response, params, this.&render) 
} 

e

boolean doResponse(request, response, params, renderFn) { 
// Do Stuff 
    renderFn(status: statusCode, contentType: "text/xml", encoding: "ISO-8859-1", text: text) 
// Do post-render stuff 
    return false 
} 
+0

Sfortunatamente questo sembra essere equivalente a chiamare render() direttamente da doResponse(). Ho fatto lo stesso errore. – Einar

+0

Darn. Interessato, potresti aggiungere l'errore nel testo della domanda? –

+0

Naturalmente. Sembra che SO ritiri le ultime parti del testo di eccezione, ma dovrebbe essere sufficiente. – Einar

0

Si potrebbe provare questa soluzione.

Change doResponse ad una chiusura:

def doResponse = { 
     render(status: statusCode, contentType: "text/xml", encoding: "ISO-8859-1", text: text) 
     return false 
} 

Calling doResponse (dalla chiusura del filtro):

def doResponseClosure = doResponse.clone() 
doResponseClosure.delegate = delegate 
// if it doesn't work, try adding: doResponseClosure.owner = owner 
return doResponseClosure() 

La clonazione avviene a causa di motivi di concorrenza.

Sto usando questo metodo con successo in altri DSL Grails come le chiusure dei criteri.

+0

Grazie.Funziona, ma la soluzione di robbberts richiede un po 'meno codice. – Einar