You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Alex Kotchnev <ak...@gmail.com> on 2013/02/28 23:34:17 UTC

Conditional service override

I would like to be able to conditionally override a service inside of a
tapestry module (e.g. in the case of DevelopmentModule)

My first pass was to declare a new service inside of the development
module, e.g. :

FooService buildDevFooService() {
   ...
}

and then use the override approach described on the wiki:

@Contribute(ServiceOverride.class)
public static void
setupApplicationServiceOverrides(MappedConfiguration<Class, Object>
configuration,
            @Local FooService devFooSvc
            ) {

            configuration.add(FooService.class, devFooSvc);
}

That works great if I always want to override the service in Development.
However, I want to have a symbol that controls which way it goes into
development. So, I tried this:

@Contribute(ServiceOverride.class)
    public static void
setupApplicationServiceOverrides(MappedConfiguration<Class, Object>
configuration,
            @Local FooService devFooSvc,
            @Symbol("enableDevFooSvc") Boolean enableDevFoo
            ) {

            if (enableDevFoo) {
                configuration.add(FooService.class, devFooSvc);
            }
}

So, this works great when I enableDevFoo is enabled - the dev specific
service overrides the original one. However, if enableDevFoo is false, the
FooService is not overriden (and it keeps the original implementation).

That also works great, until I inject FooService by the service interface
class somewhere else. In that case (when enableDevFoo=false) , now there
are two implementations of FooService and I have a problem.

I thought that I could check the same symbol in buildDevFooService, but the
builder method complains when I return null (understandably). I thought
that it would be nice to somehow disable  the devFooService if
enableDevFoo=false, but I didn't find a way to "disable" an existing
service.

Any ideas how I can accomplish this ?

Cheers - Alex K

Re: Conditional service override

Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Fri, 01 Mar 2013 01:30:38 -0300, Alex Kotchnev <ak...@gmail.com>  
wrote:

> Thiago - I can probably try going the decoration route, although it  
> feels a little bit "not right" -conceptually I want to  'override' the  
> original
> implementation.

It may not feel 100% right, but a decorator is still a different  
implementation of something anyway.

> If I try to decorate the service, do I still have to build
> it as a service (e.g. using a service builder method) , or can I
> instantiate it as I had shown above (inside of the decorator method)

You need to declare the service to be decorated in some way (binder.bind()  
or builder method), but the service override/decorator instance itself can  
be constructed in any way you want, even instantiating it directly in the  
decorate method.

-- 
Thiago H. de Paula Figueiredo

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Conditional service override

Posted by Ivan Khalopik <ik...@gmail.com>.
There is a helper method in configuration classes for service autobuilding:

configuration.addInstance(FooService.class, DevFooService.class);

But I think autobuilding inside service override contribution is not a good
idea as it can result in recursion if service has complex dependency tree.
The better way if you will instantiate service directly.

You can also try tapestry execution mode approach.

http://tapestry.apache.org/configuration.html#Configuration-SettingExecutionModes

So you can create some DevelopmentModule, Override all necessary services
with local replacements inside this module. You don't need to check any
symbol as your services will automatically be available only in dev mode.



On Fri, Mar 1, 2013 at 7:30 AM, Alex Kotchnev <ak...@gmail.com> wrote:

> One other thing that I tried was to instantiate the "overriding" class
> inside of the overriding method instead of providing a builder method to
> create an overriding service, e.g. :
>
> @Contribute(ServiceOverride.class)
>     public static void
> setupApplicationServiceOverrides(MappedConfiguration<Class,
> Object> configuration,
>             @Symbol("enableDevFooSvc") Boolean enableDevFoo
>             ) {
>
>             if (enableDevFoo) {
>                 configuration.add(FooService.class, new DevFooService() );
>             }
> }
>
> For whatever reason, inside my code when I use ObjectLocator to find an
> instance of FooService.class, I still get the original instance that I had
> tried to override.
>
> Taha - thanks for the suggestion. Unfortunately, the "overriding"
> implementation comes from a third party and I need to instantiate it w/ a
> specific constructor argument. Now that you mention it, I could probably
> try to subclass it with my own implementation that is more Tap IoC aware
> (e.g. injects @Symbol-s in the constructor).
>
> Thiago - I can probably try going the decoration route, although it feels a
> little bit "not right" -conceptually I want to  'override' the original
> implementation.  If I try to decorate the service, do I still have to build
> it as a service (e.g. using a service builder method) , or can I
> instantiate it as I had shown above (inside of the decorator method)
>
> Cheers - Alex K
>
> On Thu, Feb 28, 2013 at 7:31 PM, Taha Siddiqi <tawus.tapestry@gmail.com
> >wrote:
>
> > Hi Alex
> >
> > How about instantiating the service inside the override contribution
> > method.
> >
> > configuration.add(FooService.class,
> > objectLocator.autobuild(MyOtherImplementation.class));
> >
> > regards
> > Taha
> >
> > On Mar 1, 2013, at 4:04 AM, Alex Kotchnev wrote:
> >
> > > I would like to be able to conditionally override a service inside of a
> > > tapestry module (e.g. in the case of DevelopmentModule)
> > >
> > > My first pass was to declare a new service inside of the development
> > > module, e.g. :
> > >
> > > FooService buildDevFooService() {
> > >   ...
> > > }
> > >
> > > and then use the override approach described on the wiki:
> > >
> > > @Contribute(ServiceOverride.class)
> > > public static void
> > > setupApplicationServiceOverrides(MappedConfiguration<Class, Object>
> > > configuration,
> > >            @Local FooService devFooSvc
> > >            ) {
> > >
> > >            configuration.add(FooService.class, devFooSvc);
> > > }
> > >
> > > That works great if I always want to override the service in
> Development.
> > > However, I want to have a symbol that controls which way it goes into
> > > development. So, I tried this:
> > >
> > > @Contribute(ServiceOverride.class)
> > >    public static void
> > > setupApplicationServiceOverrides(MappedConfiguration<Class, Object>
> > > configuration,
> > >            @Local FooService devFooSvc,
> > >            @Symbol("enableDevFooSvc") Boolean enableDevFoo
> > >            ) {
> > >
> > >            if (enableDevFoo) {
> > >                configuration.add(FooService.class, devFooSvc);
> > >            }
> > > }
> > >
> > > So, this works great when I enableDevFoo is enabled - the dev specific
> > > service overrides the original one. However, if enableDevFoo is false,
> > the
> > > FooService is not overriden (and it keeps the original implementation).
> > >
> > > That also works great, until I inject FooService by the service
> interface
> > > class somewhere else. In that case (when enableDevFoo=false) , now
> there
> > > are two implementations of FooService and I have a problem.
> > >
> > > I thought that I could check the same symbol in buildDevFooService, but
> > the
> > > builder method complains when I return null (understandably). I thought
> > > that it would be nice to somehow disable  the devFooService if
> > > enableDevFoo=false, but I didn't find a way to "disable" an existing
> > > service.
> > >
> > > Any ideas how I can accomplish this ?
> > >
> > > Cheers - Alex K
> >
> >
>



-- 
BR
Ivan

Re: Conditional service override

Posted by Alex Kotchnev <ak...@gmail.com>.
One other thing that I tried was to instantiate the "overriding" class
inside of the overriding method instead of providing a builder method to
create an overriding service, e.g. :

@Contribute(ServiceOverride.class)
    public static void
setupApplicationServiceOverrides(MappedConfiguration<Class,
Object> configuration,
            @Symbol("enableDevFooSvc") Boolean enableDevFoo
            ) {

            if (enableDevFoo) {
                configuration.add(FooService.class, new DevFooService() );
            }
}

For whatever reason, inside my code when I use ObjectLocator to find an
instance of FooService.class, I still get the original instance that I had
tried to override.

Taha - thanks for the suggestion. Unfortunately, the "overriding"
implementation comes from a third party and I need to instantiate it w/ a
specific constructor argument. Now that you mention it, I could probably
try to subclass it with my own implementation that is more Tap IoC aware
(e.g. injects @Symbol-s in the constructor).

Thiago - I can probably try going the decoration route, although it feels a
little bit "not right" -conceptually I want to  'override' the original
implementation.  If I try to decorate the service, do I still have to build
it as a service (e.g. using a service builder method) , or can I
instantiate it as I had shown above (inside of the decorator method)

Cheers - Alex K

On Thu, Feb 28, 2013 at 7:31 PM, Taha Siddiqi <ta...@gmail.com>wrote:

> Hi Alex
>
> How about instantiating the service inside the override contribution
> method.
>
> configuration.add(FooService.class,
> objectLocator.autobuild(MyOtherImplementation.class));
>
> regards
> Taha
>
> On Mar 1, 2013, at 4:04 AM, Alex Kotchnev wrote:
>
> > I would like to be able to conditionally override a service inside of a
> > tapestry module (e.g. in the case of DevelopmentModule)
> >
> > My first pass was to declare a new service inside of the development
> > module, e.g. :
> >
> > FooService buildDevFooService() {
> >   ...
> > }
> >
> > and then use the override approach described on the wiki:
> >
> > @Contribute(ServiceOverride.class)
> > public static void
> > setupApplicationServiceOverrides(MappedConfiguration<Class, Object>
> > configuration,
> >            @Local FooService devFooSvc
> >            ) {
> >
> >            configuration.add(FooService.class, devFooSvc);
> > }
> >
> > That works great if I always want to override the service in Development.
> > However, I want to have a symbol that controls which way it goes into
> > development. So, I tried this:
> >
> > @Contribute(ServiceOverride.class)
> >    public static void
> > setupApplicationServiceOverrides(MappedConfiguration<Class, Object>
> > configuration,
> >            @Local FooService devFooSvc,
> >            @Symbol("enableDevFooSvc") Boolean enableDevFoo
> >            ) {
> >
> >            if (enableDevFoo) {
> >                configuration.add(FooService.class, devFooSvc);
> >            }
> > }
> >
> > So, this works great when I enableDevFoo is enabled - the dev specific
> > service overrides the original one. However, if enableDevFoo is false,
> the
> > FooService is not overriden (and it keeps the original implementation).
> >
> > That also works great, until I inject FooService by the service interface
> > class somewhere else. In that case (when enableDevFoo=false) , now there
> > are two implementations of FooService and I have a problem.
> >
> > I thought that I could check the same symbol in buildDevFooService, but
> the
> > builder method complains when I return null (understandably). I thought
> > that it would be nice to somehow disable  the devFooService if
> > enableDevFoo=false, but I didn't find a way to "disable" an existing
> > service.
> >
> > Any ideas how I can accomplish this ?
> >
> > Cheers - Alex K
>
>

Re: Conditional service override

Posted by Taha Siddiqi <ta...@gmail.com>.
Hi Alex

How about instantiating the service inside the override contribution method.

configuration.add(FooService.class, objectLocator.autobuild(MyOtherImplementation.class));

regards
Taha

On Mar 1, 2013, at 4:04 AM, Alex Kotchnev wrote:

> I would like to be able to conditionally override a service inside of a
> tapestry module (e.g. in the case of DevelopmentModule)
> 
> My first pass was to declare a new service inside of the development
> module, e.g. :
> 
> FooService buildDevFooService() {
>   ...
> }
> 
> and then use the override approach described on the wiki:
> 
> @Contribute(ServiceOverride.class)
> public static void
> setupApplicationServiceOverrides(MappedConfiguration<Class, Object>
> configuration,
>            @Local FooService devFooSvc
>            ) {
> 
>            configuration.add(FooService.class, devFooSvc);
> }
> 
> That works great if I always want to override the service in Development.
> However, I want to have a symbol that controls which way it goes into
> development. So, I tried this:
> 
> @Contribute(ServiceOverride.class)
>    public static void
> setupApplicationServiceOverrides(MappedConfiguration<Class, Object>
> configuration,
>            @Local FooService devFooSvc,
>            @Symbol("enableDevFooSvc") Boolean enableDevFoo
>            ) {
> 
>            if (enableDevFoo) {
>                configuration.add(FooService.class, devFooSvc);
>            }
> }
> 
> So, this works great when I enableDevFoo is enabled - the dev specific
> service overrides the original one. However, if enableDevFoo is false, the
> FooService is not overriden (and it keeps the original implementation).
> 
> That also works great, until I inject FooService by the service interface
> class somewhere else. In that case (when enableDevFoo=false) , now there
> are two implementations of FooService and I have a problem.
> 
> I thought that I could check the same symbol in buildDevFooService, but the
> builder method complains when I return null (understandably). I thought
> that it would be nice to somehow disable  the devFooService if
> enableDevFoo=false, but I didn't find a way to "disable" an existing
> service.
> 
> Any ideas how I can accomplish this ?
> 
> Cheers - Alex K


Re: Conditional service override

Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Thu, 28 Feb 2013 19:34:17 -0300, Alex Kotchnev <ak...@gmail.com>  
wrote:

> I would like to be able to conditionally override a service inside of a
> tapestry module (e.g. in the case of DevelopmentModule)

Sometimes, instead of contributing to ServiceOverrides, using a decorator  
method works better. You don't need to actually decorate the original  
service, you can just return the service object directly.

-- 
Thiago H. de Paula Figueiredo

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org