What about nestable manual scopes?

On Thu, Sep 24, 2009 at 1:29 PM, Paul Field <paul.fi...@db.com> wrote:

> There was a recent thread that discussed implementing the equivalent of
> Spring's "prototype" beans in Tapestry IOC. I was of the opinion that it
> wasn't possible to implement sensibly: you either run the risk of the
> service living too long or else Tapestry's proxies would mean that you
> created a new instance for every method call.
>
> I've been thinking about this some more, and I've realised that the
> problem is about controlling the scope. Prototype beans in Spring are a
> bit problematic anyway and the reason is that the scope is started by a
> request to the container for the bean and then ended by the last reference
> being removed (GC).  Sometimes the "call to the container" is hidden - so
> it's not very clear exactly what the scope is and that would be
> particularly true in Tapestry where the proxies and @Inject mechanisms
> hide the container well away from the client code.
>
> So I think that the key to doing a similar thing in Tapestry IOC is to
> make control of the scope explicit. This would be known as "manual" scope
> and the pattern would be something like this:
>
>
> -----------------
> // This is provided by a hypothetical library and is actually 'perthread'
> scoped - so your manual scope is nested within a thread
> public interface ManualScope {
>  // Opens the scope - error if already open
>  void open();
>
>  // Closes the scope - error if not open
>  void close();
>
>  // Runs 'r' inside the scope - error if scope is already open
>  void run(Runnable r);
> }
>
> -----------------
> // This is your module creating your manually-scoped service (somewhat
> equivalent to a spring prototype bean)
> public class MyModule {
>    public static void bind(ServiceBinder binder) {
>        binder.bind(MyService.class, MyServiceImpl.class).scope("manual");
>    }
> }
>
> -----------------
> // This is your client code using the service
>
> @Inject ManualScope manualScope;
> @Inject MyService myManualScopedService;
>
>
> public void doSomethingOldSchool() {
>    manualScope.open()
>    try {
>        myManualScopedService.doSomething();
>        myManualScopedService.doSomeMore();
>    } finally {
>        manualScope.close();
>    }
> }
>
>
> public void doSomethingNewSchool() {
>    manualScope.run(new Runnable() {
>        public void run() {
>            myManualScopedService.doSomething();
>            myManualScopedService.doSomeMore();
>        }
>    });
> }
>
>
> So the idea is that you can only use myManualScoped bean within the
> open()/close() pair, or within the run(). If you use it outside, you get a
> helpful exception.
>
>
> There other options for 'prototype' beans I can think of involve not
> having a service. Either:
> 1) Create a factory service; the client code injects the factory and calls
> a create() method.
> 2) Inject ObjectLocator and call autobuild()  (gives you the benefit of
> dependency injection for a non-service object)
>
> Both of these are much simpler for the client. The manual scope is a bit
> clunky to use. The main benefit is that the service is a proper IOC
> service you can decorate it/advise it/override it and all kinds of other
> good IOC stuff. In addition, you have complete control over the lifetime
> of your service and potentially there could be a
> ManualScopeCleanupListener (similar to ThreadCleanupListener) to clean-up
> services when the scope closes.
>
> I'm pretty sure my work project would find it useful as, in Spring, I have
> one-shot "commands" that are prototype beans and we use Spring's AOP to
> add-on transactions, logging and auditing. This Manual scope idea would
> work quite well for that as we could use the IOC's decorating/advising
> capabilities.
>
>
> However, I'm not convinced that the clunkyness of the client code won't
> put people off using it and I'm not convinced that there are enough times
> that you want to use IOC magic (such as advice) on a "prototype bean". So,
> I'd appreciate some feedback on the idea.
>
> Can you think of any simplification I could make that makes it less
> clunky? Would you use it? Is it useful enough for me to write the
> implementation as open source? Useful enough to pester the committers to
> put it in the core IOC? Or just a bad idea that I've had late one evening
> :-)
>
> Thanks,
>
> - Paul
>
>
>
> ---
>
> This e-mail may contain confidential and/or privileged information. If you
> are not the intended recipient (or have received this e-mail in error)
> please notify the sender immediately and delete this e-mail. Any
> unauthorized copying, disclosure or distribution of the material in this
> e-mail is strictly forbidden.
>
> Please refer to http://www.db.com/en/content/eu_disclosures.htm for
> additional EU corporate and regulatory disclosures.




-- 
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to learn
how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

Reply via email to