How to extend/override controller actions of plugins?
Asked Answered
M

3

7

The plugin (Nimble 0.3) I am using in my grails application, includes some controllers and associated actions. I want to change (slightly) some actions behavior, and I was wondering how I can achieve that.

Can I create a child controller that inherits from my plugin controller and override some of the action implementation?

Or, can I create another Controller with the same name as the plugin controller but located in a different package?

Well actually what I really need to understand is : how Grails determines which controller action to call when there are name conflicts ?

Mascara answered 31/1, 2010 at 23:10 Comment(0)
F
8

Assuming you have a plugin controller named PluginController and an action 'foo' that you want to override, you can subclass the controller:

class MyController extends PluginController {

   def foo = {
      ...
   }
}

but you'll need to do some work in UrlMappings:

class UrlMappings {

   static mappings = {
      "/$controller/$action?/$id?" {
         constraints {}
      }

      "/myController/foo/$id?"(controller: "myController", action: "foo")
      "/myController/$action?/$id?"(controller: "pluginController")
      "/pluginController/$action?/$id?"(controller: "errors", action: "urlMapping")

      "/"(view:"/index")
      "500"(view:'/error')
      "404"(controller: "errors", action: "notFound")
   }
}

and this depends on an ErrorsController:

class ErrorsController {

   def notFound = {
      log.debug "could not find $request.forwardURI"
   }

   def urlMapping = {
      log.warn "unexpected call to URL-Mapped $request.forwardURI"
      render view: 'notFound'
   }
}

which renders a 404 page if you call the old "unmapped" controller actions. You'll need to create grails-app/views/errors/notFound.gsp to show an appropriate 404 page.

The first url mapping ensures that your overridden action is called. The 2nd routes everything else to the original controller. And the 3rd sends 404s for direct access.

Fleming answered 6/2, 2010 at 22:46 Comment(1)
Burt, what if the plugin defines "404"(view:'/error'), can I override that with my own "404" mapping, but to an action in a custom controller instead?Khedive
P
2

With Grails 1.3.7 and Nimble plugin 0.4 I found that Burt's UrlMapping solution did not work for me. However, simply creating a controller that both subclasses the plugin controller and has the same name worked, per Burt's other answer

class AuthController extends grails.plugins.nimble.core.AuthController{

    private static String TARGET = 'grails.plugins.nimble.controller.AuthController.TARGET'

    def login = {
        // custom logic here    
    }
}
Paviour answered 21/3, 2011 at 23:31 Comment(0)
N
0

I would subclass the original class and override the behavior you need. I am doing a lot of that with another plugin, and it works great.

An alternate way is of course to use the plugin inline and just modify the original source, but that's worse, since you'll have an issue with upgrades.

I am also a user of Nimble, and if you think your extension could be used by others, then you could contribute - nimble certainly tried to make sure it's very extensible.

Negligee answered 3/2, 2010 at 18:55 Comment(1)
Jean, I am actually subclassing the original controller AND overriding some actions BUT Grails still route my requests to the older actions (and not to the subclass controller action). In order to make it work, I needed to change the action name inside the inline plugin. Do you know how to force Grails to use one controller action instead of another?Mascara

© 2022 - 2024 — McMap. All rights reserved.