2010-06-15 16 views
0

Fondamentalement, je veux pouvoir assigner des objets créés dans des filtres aux membres d'un contrôleur de base à partir duquel chaque contrôleur s'étend. Tout moyen de le faire?Comment accéder aux propriétés dynamiques du contrôleur dans le constructeur d'un contrôleur de base dans Grails?

Voici comment j'ai essayé, mais je n'ai pas besoin de le faire fonctionner.

Ce que j'essaye de réaliser est d'avoir tous mes contrôleurs étendent un contrôleur de base. Le constructeur du contrôleur de base serait utilisé pour assigner des valeurs à ses membres, ces valeurs étant extraites de la carte session. Exemple ci-dessous

fichier grails-app/régulateurs/HomeController.groovy:

class HomeController extends BaseController { 
    def index = { 
     render username 
    } 
} 

fichier Grails-app/controllers/BaseController.groovy:

abstract class BaseController { 
    public String username 

    public BaseController() { 
     username = session.username 
    } 
} 

Lors de l'exécution de l'application, la sortie est représentée:

2010-06-15 18:17:16,671 [main] ERROR [localhost].[/webapp] - Exception sending context initialized event to listener instance of class org.codehaus.groovy.grails.web.context.GrailsContextLoaderListener 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pluginManager' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.RuntimeException: Unable to locate constructor with Class parameter for class org.codehaus.groovy.grails.commons.DefaultGrailsControllerClass 
    ... 
Caused by: java.lang.RuntimeException: Unable to locate constructor with Class parameter for class org.codehaus.groovy.grails.commons.DefaultGrailsControllerClass 
    ... 
Caused by: java.lang.reflect.InvocationTargetException 
    ... 
Caused by: org.codehaus.groovy.grails.exceptions.NewInstanceCreationException: Could not create a new instance of class [com.my.package.controller.HomeController]! 
    ... 
Caused by: groovy.lang.MissingPropertyException: No such property: session for class: com.my.package.controller.HomeController 
    at com.my.package.controller.BaseController.<init>(BaseController.groovy:16) 
    at com.my.package.controller.HomeController.<init>(HomeController.groovy) 
    ... 
2010-06-15 18:17:16,687 [main] ERROR core.StandardContext - Error listenerStart 
2010-06-15 18:17:16,687 [main] ERROR core.StandardContext - Context [/webapp] startup failed due to previous errors 

Et l'application ne sera pas exécutée.

Ceci est juste un exemple car dans mon cas, je ne voudrais pas attribuer un nom d'utilisateur à une valeur de chaîne, mais plutôt quelques objets tirés de la carte session. Les objets tirés de la carte session sont définis dans des filtres.

L'alternative que je vois est de pouvoir accéder à l'instance du contrôleur dans l'exécution du filtre. Est-ce possible?

Aidez s'il vous plaît! Merci beaucoup!

Répondre

4

Vous ne pouvez généralement pas faire grand-chose dans le constructeur dans les artefacts Grails. Vous pouvez utiliser un intercepteur pour ce bien:

abstract class BaseController { 
    protected String username 

    def beforeInterceptor = { 
     username = session.username 
    } 
} 

Ceci est décrit dans la section 6.1.5 de http://grails.org/doc/latest/

+0

Merci pour votre réponse! Le problème avec ceci est quand un contrôleur concret (HomeController) définit un beforeInterceptor lui-même, beforeInterceptor du BaseController ne sera pas appelé. Essayer de l'appeler en utilisant 'super.beforeInterceptor()' à travers le compilateur concret compile, mais au moment de l'exécution jette ceci: org.codehaus.groovy.runtime.InvokerInvocationException: java.lang.StackOverflowError \t at java.lang.Thread.run (Thread.java:619) causée par: java.lang.StackOverflowError \t à com.my.package.controller.HomeController $ _closure1.doCall (HomeController.groovy) \t ... Une manière de résoudre ce problème? Merci! – djule5

+2

Puisqu'il s'agit d'une fermeture, super.beforeInterceptor() ne peut pas fonctionner. Mais vous pouvez déléguer l'intercepteur à une méthode réelle qui peut être surchargée: def beforeInterceptor = {prepareCall()} protected void prepareCall() {nom d'utilisateur = session.username} –

0

Vous pouvez utiliser une demande de service scope ...

0

En règle générale, je d mise en garde contre la mise en état directement dans un contrôleur; les contrôleurs en général (quel que soit le cadre) sont généralement destinés à être apatrides. Je collerais avec les constructions standard d'état de webapp comme la demande et la session pour stocker et transférer des données.

Pour votre cas, je ferais une des opérations suivantes:

  • Si les données légères (primitives), je les stocker dans la session et simplement les accès au besoin:
    par exemple render session.username

  • Si des données dynamiques ou basées sur des bases de données, je créer un service et tirer les données selon les besoins: par exemple. homeService.getUser(). nom d'utilisateur

  • En tant que variante de votre discussion avec Burt ci-dessus, vous pouvez utiliser un filtre pour remplir une requête ou une valeur de session.