Controller Mixins? 2
One of the things I’m wanting to solve (in a simple and elegant manner) is the problem of caching. Essentially I want to introduce an interface that you can place on things that would be put in a request or session attribute so that I can determine the cacheability of the page dynamically. It would be easy enough to introduce a base class that takes care of this for me. The problem is that not every controller needs to have caching, and some controllers need to force no caching within the same application. Not to mention, if we want to add a set of actions to an existing controller like the Ruby on Rails scaffolding mixin we would be required to either have a multiplicity of base classes or we would need a mixin functionality like Ruby.
Now, the cool thing with ActionPack is that we are already calling methods introspectively on a class, so what could be difficult about calling methods on another controller that is “mixed in” to your controller? That allows you to manage functionality chunks effectively. The mixin controllers don’t have to be (and really shouldn’t be) in the same package as the rest of your controllers. The only issue comes up where a controller has the same action of a mixed-in controller. The action has to be simple and predictable every time. My current thinking is to provide the same action as inheritance. I.e. the new action would override the old action. The only issue comes with calling super.actionName() within the action. How do we capture that? The only way I can think of is that we provide one method to handle the delegation if it is called. For example yield() would tell the controller to look in it’s mixins for the corresponding action and call it.
The idea is pretty cool, and the ability to snap in aspects of functionality into your web application is truly useful. It’s a truer version of separation of concerns without the intrusiveness and lack of clarity as the more traditional aspect oriented programming (AOP) efforts. However, it does introduce a certain intellectual complexity. We have to make it really obvious to developers that mixins are being used, and we have to use a design principle that Java developers are used to. That’s why I intend to imitate the functionality of inheritance as best I can. Mixing in multiple controllers also requires predictability. The order that a developer mixes in controllers must be respected. If two controllers don’t play nice together, the developer needs to have the ability to override the order that the actions are called.
I’m balancing the payoff for the complexity involved. I’m also thinking about how to implement the thing, to keep things as transparent as possible to users of the ActionPack framework, yet apparent as possible to developers of the ActionPack framework. The one thing I haven’t touched is what to do with views associated with the mixins. That’s going to be a big issue to work out later. First I want to do logic only mixins. Yet another question is when are mixins allowed to be added/created? It might be terribly useful to add mixins based on user parameters. For example, if the application supports users from several companies, and they want navigation cues specific to their company then adding in the mixin specific to that company would be something done in a filter. If we provide no limitations, and only require that the mixin is applied before it is used, that might also be an option.
I’m thinking that the mixin approach is definitely going to be used, the question is really how to make it easy to understand .

You might check out Guice. It supports scopes. For example, if you use it with Struts 2, you can can just apply @SessionScoped to an action class and it will be stored in that scope. Is this what you’re looking for?
No, I’m looking to add a group of functionality to an existing controller. For example, automatically evaluating the cache HTTP headers to use, or something akin to the Ruby on Rails scaffolding. It’s more of an intelligent way to break down your controller classes to support certain aspects of the system.