Standalone IOC and service overrides

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Standalone IOC and service overrides

Adriaan Joubert-3
Hi,

we love the IOC and are using it in our standalone Java applications as
well as our web applications. I do however have a problem with overriding
services. When using the suggestions from the cookbook (
http://tapestry.apache.org/ioc-cookbook-overriding-ioc-services.html) to
override a service, I find that the the service is not overridden using the
getService method on the registry. I've been through the IOC code and I
could see that the ServiceOverride service is called from the
MasterObjectProvider but not from elsewhere. Based on that I tried to use
the getObject() method on the registry, and that does indeed give me the
overridden service. I found this behaviour rather unexpected, so I assume
I'm missing something.

We use getService in a lot of places, and it would be quite a change to
have to use getObject everywhere instead. As we have markers on our
services, the getService interface is also easier to use.

So my question is: why the difference between getService and getObject? And
which one should we be using?

Please see below a junit test that demonstrates this behaviour. I'd really
appreciate any enlightenment!

Cheers,

Adriaan


import static org.junit.Assert.assertEquals;

import org.apache.tapestry5.ioc.MappedConfiguration;
import org.apache.tapestry5.ioc.Registry;
import org.apache.tapestry5.ioc.RegistryBuilder;
import org.apache.tapestry5.ioc.ServiceBinder;
import org.apache.tapestry5.ioc.annotations.Contribute;
import org.apache.tapestry5.ioc.annotations.SubModule;
import org.apache.tapestry5.ioc.internal.NullAnnotationProvider;
import org.apache.tapestry5.ioc.services.ServiceOverride;
import org.junit.Test;

public class IocTest {

    public interface Simple {
        String getString();
    }

    public static class SimpleImpl implements Simple {
        @Override
        public String getString() {
            return "foo";
        }
    }

    public static class SimpleOverrideImpl implements Simple {
        @Override
        public String getString() {
            return "bar";
        }
    }

    public static class DefaultAppModule {
        public static void bind(ServiceBinder binder) {
            binder.bind(Simple.class, SimpleImpl.class);
        }
    }

    @SubModule(DefaultAppModule.class)
    public static class OverrideAppModule {
        @Contribute(ServiceOverride.class)
        public static void testOverrides(
                MappedConfiguration<Class<?>, Object> configuration) {
            configuration.addInstance(Simple.class,
SimpleOverrideImpl.class);
        }
    }

    @Test
    public void testWithoutOverride() {
        RegistryBuilder builder = new RegistryBuilder();
        builder.add(DefaultAppModule.class);
        Registry registry = builder.build();
        registry.performRegistryStartup();
        Simple simple = registry.getService(Simple.class);
        assertEquals("foo", simple.getString());
        registry.cleanupThread();
        registry.shutdown();
    }

    @Test
    public void testWithOverride() {
        RegistryBuilder builder = new RegistryBuilder();
        builder.add(OverrideAppModule.class);
        Registry registry = builder.build();
        registry.performRegistryStartup();
        Simple simple = registry.getService(Simple.class);
        // !FAILS!
        assertEquals("bar", simple.getString());
        registry.cleanupThread();
        registry.shutdown();
    }

    @Test
    public void testWithOverrideAndObjectProvider() {
        RegistryBuilder builder = new RegistryBuilder();
        builder.add(OverrideAppModule.class);
        Registry registry = builder.build();
        registry.performRegistryStartup();
        Simple simple = registry.getObject(Simple.class,
                new NullAnnotationProvider());
        // SUCCEEDS
        assertEquals("bar", simple.getString());
        registry.cleanupThread();
        registry.shutdown();
    }

}
Reply | Threaded
Open this post in threaded view
|

Re: Standalone IOC and service overrides

RuralHunter
I encountered the same problem with Tapestry IOC 5.4beta.
registry.getService() doesn't respect service overrides. Is this a designed
feature or a bug?

2013-12-13 2:20 GMT+08:00 Adriaan Joubert <[hidden email]>:

> Hi,
>
> we love the IOC and are using it in our standalone Java applications as
> well as our web applications. I do however have a problem with overriding
> services. When using the suggestions from the cookbook (
> http://tapestry.apache.org/ioc-cookbook-overriding-ioc-services.html) to
> override a service, I find that the the service is not overridden using the
> getService method on the registry. I've been through the IOC code and I
> could see that the ServiceOverride service is called from the
> MasterObjectProvider but not from elsewhere. Based on that I tried to use
> the getObject() method on the registry, and that does indeed give me the
> overridden service. I found this behaviour rather unexpected, so I assume
> I'm missing something.
>
> We use getService in a lot of places, and it would be quite a change to
> have to use getObject everywhere instead. As we have markers on our
> services, the getService interface is also easier to use.
>
> So my question is: why the difference between getService and getObject? And
> which one should we be using?
>
> Please see below a junit test that demonstrates this behaviour. I'd really
> appreciate any enlightenment!
>
> Cheers,
>
> Adriaan
>
>
> import static org.junit.Assert.assertEquals;
>
> import org.apache.tapestry5.ioc.MappedConfiguration;
> import org.apache.tapestry5.ioc.Registry;
> import org.apache.tapestry5.ioc.RegistryBuilder;
> import org.apache.tapestry5.ioc.ServiceBinder;
> import org.apache.tapestry5.ioc.annotations.Contribute;
> import org.apache.tapestry5.ioc.annotations.SubModule;
> import org.apache.tapestry5.ioc.internal.NullAnnotationProvider;
> import org.apache.tapestry5.ioc.services.ServiceOverride;
> import org.junit.Test;
>
> public class IocTest {
>
>     public interface Simple {
>         String getString();
>     }
>
>     public static class SimpleImpl implements Simple {
>         @Override
>         public String getString() {
>             return "foo";
>         }
>     }
>
>     public static class SimpleOverrideImpl implements Simple {
>         @Override
>         public String getString() {
>             return "bar";
>         }
>     }
>
>     public static class DefaultAppModule {
>         public static void bind(ServiceBinder binder) {
>             binder.bind(Simple.class, SimpleImpl.class);
>         }
>     }
>
>     @SubModule(DefaultAppModule.class)
>     public static class OverrideAppModule {
>         @Contribute(ServiceOverride.class)
>         public static void testOverrides(
>                 MappedConfiguration<Class<?>, Object> configuration) {
>             configuration.addInstance(Simple.class,
> SimpleOverrideImpl.class);
>         }
>     }
>
>     @Test
>     public void testWithoutOverride() {
>         RegistryBuilder builder = new RegistryBuilder();
>         builder.add(DefaultAppModule.class);
>         Registry registry = builder.build();
>         registry.performRegistryStartup();
>         Simple simple = registry.getService(Simple.class);
>         assertEquals("foo", simple.getString());
>         registry.cleanupThread();
>         registry.shutdown();
>     }
>
>     @Test
>     public void testWithOverride() {
>         RegistryBuilder builder = new RegistryBuilder();
>         builder.add(OverrideAppModule.class);
>         Registry registry = builder.build();
>         registry.performRegistryStartup();
>         Simple simple = registry.getService(Simple.class);
>         // !FAILS!
>         assertEquals("bar", simple.getString());
>         registry.cleanupThread();
>         registry.shutdown();
>     }
>
>     @Test
>     public void testWithOverrideAndObjectProvider() {
>         RegistryBuilder builder = new RegistryBuilder();
>         builder.add(OverrideAppModule.class);
>         Registry registry = builder.build();
>         registry.performRegistryStartup();
>         Simple simple = registry.getObject(Simple.class,
>                 new NullAnnotationProvider());
>         // SUCCEEDS
>         assertEquals("bar", simple.getString());
>         registry.cleanupThread();
>         registry.shutdown();
>     }
>
> }
>