diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs index 60ed720f..f16a716a 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs @@ -142,13 +142,18 @@ namespace Spring.Objects.Factory.Support /// specified object. /// /// Name of the object. - /// The merged object definition to determine the type for. + /// The merged object definition to determine the type for. May be null /// /// The type of the object, or null if not predictable /// protected override Type PredictObjectType(string objectName, RootObjectDefinition mod) { Type objectType; + if (mod == null) + { + return null; + } + if (StringUtils.HasText(mod.FactoryMethodName)) { objectType = GetTypeForFactoryMethod(objectName, mod); diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs index 0eeda5de..b7912c4b 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs @@ -740,11 +740,11 @@ namespace Spring.Objects.Factory.Support /// To be overridden in subclasses, applying more sophisticated type detection. /// /// Name of the object. - /// The merged object definition to determine the type for. + /// The merged object definition to determine the type for. May be null /// The type of the object, or null if not predictable protected virtual Type PredictObjectType(string objectName, RootObjectDefinition mod) { - if (StringUtils.HasText(mod.FactoryObjectName)) + if (mod == null || StringUtils.HasText(mod.FactoryObjectName)) { return null; } diff --git a/src/Spring/Spring.Services/Remoting/SaoExporter.cs b/src/Spring/Spring.Services/Remoting/SaoExporter.cs index 18a74089..4ec33d7f 100644 --- a/src/Spring/Spring.Services/Remoting/SaoExporter.cs +++ b/src/Spring/Spring.Services/Remoting/SaoExporter.cs @@ -249,10 +249,26 @@ namespace Spring.Remoting } IProxyTypeBuilder builder = new SaoRemoteObjectProxyTypeBuilder( this ); - builder.TargetType = this.objectFactory.GetType( targetName ); - if (interfaces != null && interfaces.Length > 0) + Type targetType = this.objectFactory.GetType( targetName ); + if (targetType == null) { - builder.Interfaces = TypeResolutionUtils.ResolveInterfaceArray( interfaces ); + // perform full object retrieval if type cannot be predicted - this will + // also cause any object creation exceptions to be thrown + targetType = this.objectFactory.GetObject(targetName).GetType(); + } + + if (targetType.IsInterface) + { + builder.Interfaces = new Type[] { targetType }; + builder.TargetType = typeof(object); + } + else + { + if (interfaces != null && interfaces.Length > 0) + { + builder.Interfaces = TypeResolutionUtils.ResolveInterfaceArray(interfaces); + } + builder.TargetType = targetType; } Type proxyType = builder.BuildProxyType(); diff --git a/test/Spring/Spring.Services.Tests/Remoting/SaoExporterTests.cs b/test/Spring/Spring.Services.Tests/Remoting/SaoExporterTests.cs index 2cac107c..a7fb4d96 100644 --- a/test/Spring/Spring.Services.Tests/Remoting/SaoExporterTests.cs +++ b/test/Spring/Spring.Services.Tests/Remoting/SaoExporterTests.cs @@ -22,33 +22,52 @@ using System; using NUnit.Framework; +using Rhino.Mocks; +using Spring.Aop.Framework; +using Spring.Core.IO; using Spring.Objects; +using Spring.Objects.Factory; using Spring.Objects.Factory.Support; +using Spring.Objects.Factory.Xml; #endregion namespace Spring.Remoting { - /// - /// Unit tests for the SaoExporter class. - /// - /// Bruno Baia - /// Mark Pollack - [TestFixture] - public class SaoExporterTests : BaseRemotingTestFixture - { + /// + /// Unit tests for the SaoExporter class. + /// + /// Bruno Baia + /// Mark Pollack + [TestFixture] + public class SaoExporterTests : BaseRemotingTestFixture + { [Test] - [ExpectedException(typeof(ArgumentException))] - public void BailsWhenNotConfigured () - { - SaoExporter exp = new SaoExporter(); - exp.AfterPropertiesSet(); - } + [ExpectedException(typeof(ArgumentException))] + public void BailsWhenNotConfigured() + { + SaoExporter exp = new SaoExporter(); + exp.AfterPropertiesSet(); + } + + [Test] + [ExpectedException(typeof(NoSuchObjectDefinitionException))] + public void BailsIfTargetNotFound() + { + using (DefaultListableObjectFactory of = new DefaultListableObjectFactory()) + { + SaoExporter saoExporter = new SaoExporter(); + saoExporter.ObjectFactory = of; + saoExporter.TargetName = "DOESNOTEXIST"; + saoExporter.ServiceName = "RemotedSaoSingletonCounter"; + saoExporter.AfterPropertiesSet(); + } + } [Test] public void ExportSingleton() { - using(DefaultListableObjectFactory of = new DefaultListableObjectFactory()) + using (DefaultListableObjectFactory of = new DefaultListableObjectFactory()) { of.RegisterSingleton("simpleCounter", new SimpleCounter()); SaoExporter saoExporter = new SaoExporter(); @@ -58,7 +77,7 @@ namespace Spring.Remoting saoExporter.AfterPropertiesSet(); of.RegisterSingleton("simpleCounterExporter", saoExporter); // also tests SaoExporter.Dispose()! - ISimpleCounter client = (ISimpleCounter) Activator.GetObject(typeof(ISimpleCounter), "tcp://localhost:8005/RemotedSaoSingletonCounter" ); + ISimpleCounter client = (ISimpleCounter)Activator.GetObject(typeof(ISimpleCounter), "tcp://localhost:8005/RemotedSaoSingletonCounter"); client.Count(); client.Count(); @@ -69,7 +88,7 @@ namespace Spring.Remoting [Test] public void ExportSingleCall() { - using(DefaultListableObjectFactory of = new DefaultListableObjectFactory()) + using (DefaultListableObjectFactory of = new DefaultListableObjectFactory()) { of.RegisterObjectDefinition("simpleCounter", new RootObjectDefinition(typeof(SimpleCounter), false)); SaoExporter saoExporter = new SaoExporter(); @@ -79,11 +98,62 @@ namespace Spring.Remoting saoExporter.AfterPropertiesSet(); of.RegisterSingleton("simpleCounterExporter", saoExporter); // also tests SaoExporter.Dispose()! - ISimpleCounter client = (ISimpleCounter) Activator.GetObject(typeof(ISimpleCounter), "tcp://localhost:8005/RemotedSaoSingleCallCounter" ); + ISimpleCounter client = (ISimpleCounter)Activator.GetObject(typeof(ISimpleCounter), "tcp://localhost:8005/RemotedSaoSingleCallCounter"); client.Count(); client.Count(); Assert.AreEqual(0, client.Counter); } } - } + + /// + /// Checks that exp an IFactoryObject.ObjectType returns an interface type, + /// + [Test(Description = "http://jira.springframework.org/browse/SPRNET-1251")] + public void CanExportFromInterfaceTargetType() + { + using (DefaultListableObjectFactory of = new DefaultListableObjectFactory()) + { + MockRepository mocks = new MockRepository(); + IFactoryObject simpleCounterFactory = (IFactoryObject) mocks.DynamicMock(typeof (IFactoryObject)); + Expect.Call(simpleCounterFactory.ObjectType).Return(typeof (ISimpleCounter)); + Expect.Call(simpleCounterFactory.IsSingleton).Return(true); + Expect.Call(simpleCounterFactory.GetObject()).Return(new SimpleCounter()); + + mocks.ReplayAll(); + + of.RegisterSingleton("simpleCounter", simpleCounterFactory); + SaoExporter saoExporter = new SaoExporter(); + saoExporter.ObjectFactory = of; + saoExporter.TargetName = "simpleCounter"; + saoExporter.ServiceName = "RemotedSaoCallCounter"; + saoExporter.AfterPropertiesSet(); + +// XmlObjectDefinitionReader reader = new XmlObjectDefinitionReader(of); +// reader.LoadObjectDefinitions(new StringResource( +// @" +// +// +// +// +// +// +// +// +// +// +// +//")); +// SaoExporter saoExporter = (SaoExporter) of.GetObject("ISimpleCounterExporter"); +// Assert.IsNotNull(saoExporter); + + ISimpleCounter client = (ISimpleCounter)Activator.GetObject(typeof(ISimpleCounter), "tcp://localhost:8005/RemotedSaoCallCounter"); + client.Count(); + client.Count(); + + Assert.AreEqual(2, client.Counter); + + mocks.VerifyAll(); + } + } + } }