2010-11-04 11 views
5

Tengo filtros como los que se definen a continuación. Ejecutan el mismo bloque de código en varios lugares, así que para mantenerlo SECO refactoré ese código en un método llamado doResponse().Llamar a render() desde un método de filtro de ayuda en 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 
    } 
} 

Sin embargo, esto tiene un desagradable efecto secundario. Parece que el método render() solo está disponible desde el cierre de filtros. ¿Hay alguna forma (limpia) para llamar a render() desde doResponse()?

Editar: El error que consigo es:

groovy.lang.MissingMethodException: No hay ninguna firma de método: MyFilters.render() es aplicable para los tipos de argumentos: los valores (java.util.LinkedHashMap): [[Estado : 500, contentType: text/xml, codificación: ISO-8859-1, texto: ...]]

Respuesta

8

pasar el objeto que define el método render(..) con el método doRespond(..), e invocar el método render(..) en ese objeto.

Los cierres tienen algunos implicit variables, incluidos sus owner que se refieren al cierre de los padres; por lo que podemos pasar a lo siguiente:

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

doRespond(..) método:

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

hola He intentado hacerlo, pero obtengo: java.lang.NullPointerException: no se puede establecer la propiedad 'viewName' en el objeto nulo \t en java.lang.Thread.run (Thread.java:680) –

0

¿Podría pasar una referencia a la función render a la función doResponse?

es decir:

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

y

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

Desafortunadamente, eso parece ser equivalente a llamar a render() directamente desde doResponse(). Me sale el mismo error. – Einar

+0

Darn. Por interés, ¿podría agregar el error al texto de la pregunta? –

+0

Por supuesto. Parece que SO recorta las últimas partes del texto de excepción, pero debería ser suficiente. – Einar

0

Usted podría intentar esta solución.

Cambio doResponse a un cierre:

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

Calling doResponse (de cierre del filtro):

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

La clonación se realiza por razones de concurrencia.

He estado utilizando este método con éxito en otras DSL de Grails como cierres de Criteria.

+0

Gracias.Esto funciona, pero la solución de robbberts requiere un código ligeramente menor. – Einar

Cuestiones relacionadas