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(); } }