views:

32

answers:

2

Suppose I want to define an interface, FooProvider, and then have multiple implementations of this interface available at runtime (maybe as individual services). In my controller class, I'd like to be able to have all known implementations of this interface injected at runtime so that I can expose them as "options" to the user for getting different types of "Foo" items. This would allow my server-side code to be a lot more modular and allow multiple people to define different ways of plugging in FooProvider services.

From what I see, Grails only gives me the option of injecting a single instance of a service implementation in my controller/domain classes. Is there a way for Grails to inject multiple instances of a service based on an interface type? I guess I'm paralleling this with OSGi's ability to inject implementations of an interface available in the OSGi container...any ideas?

A: 

Grails uses Spring underneath, so you can inject as many services into your controller as you wish if you know Spring.

But I'd think about a possible good reason to not do so. When you start putting several services into a controller, it's the controller that's taking over the order in which they're called. It sounds like a workflow to me at that point, something that is best left to a service.

Controllers are part of the web tier. You can't expose that process to a client that comes in through another channel besides the web tier if it's buried in the controller.

I'd recommend that you not do this, even if it's possible. A better idea would be to expose what sounds like a complex use case in another service. Encapsulate it and hide the details from clients. That's what objects are for - hiding complexity.

duffymo
Fair enough. So what if I wanted to inject all implementations into a facade service? Say I want the service just to supply me all "Foo"s available through the plugin providers and just let the user choose which "Foo" items they want...where in my grails hierarchy do I define what to inject into a service? Thanks for the tip!
Mike
A: 

Sort of what I think you're aiming at ... I built a plugin that supplies a custom artifact (call it Foo) and supplies a script to let the developer make new instances (MyFoo, YourFoo) and I have the artifact template extend a base class (could implement an interface). Then when Grails starts it finds all the Foo artifacts and in my FooService I have a method getFooList() which just returns "application.getFooClasses()" ... in the FooController I get that list and pass into the UI to populate a selection list. After the user chooses one by name, the FooService instantiates it with

    def clazz = ApplicationHolder.application.getFooClass(name)
    myFoo = clazz?.newInstance()

Obviously this doesn't ensure that every implementation of the interface or base class is found, but it does let my FooService have the user choose from an extensible list of implementations.

Wayne