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 via email to