PDA

View Full Version : singleton="false" causes ObjectCreationException


Chris Coleman
05-10-2007, 04:24 PM
Hi,

I'm new to spring and am currently using it with the NHibernate libraries prototyping a new version of a largeish WCF app I am designing. (It was great to see a release schedule for 1.1 :) )

Since I'm new to the Spring.NET framework then apologies if I've missed something painfully obvious.

I have some objects declared:


<object id="BugDAO" type="Brats.Data.DAO.NHibernate.NHibernateBugDAO, Brats.Data.DAO.NHibernate">
<property name="SessionFactory" ref="SessionFactory"/>
</object>

<object id="FindByIdCommand" type="Brats.Commands.FindByIdCommand, Brats.Commands" singleton="false">
<property name="BugDAO" ref="BugDAO" />
</object>


In essence its virtually identical to the Spring.Northwind demo in the examples folder.

The only difference being that I thought I'd try making my Business layer out of command objects, eg


public interface ICommand
{
object Execute();

void ValidateParameters();
}

public interface IFindByIdCommand
: ICommand
{
long BugId
{
get;
set;
}
}

public class FindByIdCommand
: IFindByIdCommand
{
private static ILog _logger = LogManager.GetLogger(typeof(FindByIdCommand));

#region Private members

private IBugDAO _BugDAO;

private long _bugId;

#endregion

#region Public properties

public IBugDAO BugDAO
{
get { return _BugDAO; }
set { _BugDAO = value; }
}

#endregion

#region Command Parameter properties

public long BugId
{
get { return _bugId; }
set { _bugId = value; }
}

#endregion

#region ICommand Members

[Transaction()]
public object Execute()
{
_logger.Debug(String.Format("Entering: {0}", MethodInfo.GetCurrentMethod().Name));

ValidateParameters();

Bug b = BugDAO.FindById(BugId);

return b;
}

public void ValidateParameters()
{
}

#endregion
}


Since the command objects store internal state then they will need to be prototype/non-singleton instances of the class. I figured that this would just be a case of changing the <object id="FindByIdCommand" tag to include singleton="false" as an attribute.

However setting this causes a NullReferenceException to be called on L141 of the file ControlFlowFactory.cs (method.DeclaringType throws an System.ArgumentNullException), and then an ObjectCreationException on L752 of AbstractAutoeireObjectFactory.cs.

I'm totally out of ideas now any and any help would be much appreciated.

Thanks
Chris

Chris Coleman
05-10-2007, 04:32 PM
Sorry - I should add:

.NET 2/3.0
Spring.NET-20070507-0933

And - I don't reckon its relevant but:

Spring.Data.NHibernate12-20070504-0430.zip
Spring.Data.NHibernate-20070405-1659.zip

Bruno Baia
05-10-2007, 05:20 PM
Hi,

You have the same error with singleton="true" ?

We need more information to help you, like the stacktrace and the code that throws the exception.

- Bruno

Chris Coleman
05-11-2007, 09:21 AM
Hi, thanks for the response,

I have no problem obtaining the objects with singleton="true"

This is Call stack:

Spring.Core.dll!Spring.Objects.Factory.Support.Abs tractAutowireCapableObjectFactory.CreateObject(str ing name = "FindByIdCommand", Spring.Objects.Factory.Support.RootObjectDefinitio n definition = {RootObjectDefinition : Abstract = False; Singleton = False; LazyInit = False; Autowire = No; DependencyCheck = None; InitMethodName = ; DestroyMethodName = ; FactoryMethodName = ; FactoryObjectName = ; defined in = file [C:\source\EuroBrats5\EuroBrats.EuroBratsService.Ho sts.Self\bin\Release\Commands.xml]}, object[] arguments = {Dimensions:[0]}, bool allowEagerCaching = true) Line 752 + 0x60 bytes C#
Spring.Core.dll!Spring.Objects.Factory.Support.Abs tractAutowireCapableObjectFactory.CreateObject(str ing name = "FindByIdCommand", Spring.Objects.Factory.Support.RootObjectDefinitio n definition = {RootObjectDefinition : Abstract = False; Singleton = False; LazyInit = False; Autowire = No; DependencyCheck = None; InitMethodName = ; DestroyMethodName = ; FactoryMethodName = ; FactoryObjectName = ; defined in = file [C:\source\EuroBrats5\EuroBrats.EuroBratsService.Ho sts.Self\bin\Release\Commands.xml]}, object[] arguments = {Dimensions:[0]}) Line 634 + 0x14 bytes C#
Spring.Core.dll!Spring.Objects.Factory.Support.Abs tractObjectFactory.GetObject(string name = "FindByIdCommand", System.Type requiredType = {Name = "Object" FullName = "System.Object"}, object[] arguments = {Dimensions:[0]}) Line 257 + 0x11 bytes C#
Spring.Core.dll!Spring.Objects.Factory.Support.Abs tractObjectFactory.GetObject(string name = "FindByIdCommand", object[] arguments = {Dimensions:[0]}) Line 1267 + 0x1f bytes C#
Spring.Core.dll!Spring.Objects.Factory.Support.Abs tractObjectFactory.GetObject(string name = "FindByIdCommand") Line 1227 + 0xf bytes C#
> Spring.Core.dll!Spring.Context.Support.AbstractApp licationContext.this[string].get(string name = "FindByIdCommand") Line 1016 + 0x14 bytes C#


And this is the stack trace in the exception, at the point where the ObjectCreationException is thrown.


ObjectCreationException:
at Spring.Objects.Factory.Support.AbstractAutowireCap ableObjectFactory.CreateObject(String name, RootObjectDefinition definition, Object[] arguments, Boolean allowEagerCaching) in c:\projects\daily\Spring.Net\src\Spring\Spring.Cor e\Objects\Factory\Support\AbstractAutowireCapableO bjectFactory.cs:line 752

Inner System.ArgumentNullException:
at Spring.Core.ControlFlowFactory.DefaultControlFlow. MethodsDeclaredTypeCriteria.IsSatisfied(Object datum) in c:\projects\daily\Spring.Net\src\Spring\Spring.Cor e\Core\ControlFlowFactory.cs:line 141
at Spring.Objects.Support.ComposedCriteria.IsSatisfie d(Object datum) in c:\projects\daily\Spring.Net\src\Spring\Spring.Cor e\Objects\Support\ComposedCriteria.cs:line 76
at Spring.Core.ControlFlowFactory.DefaultControlFlow. IsMatch(ICriteria criteria) in c:\projects\daily\Spring.Net\src\Spring\Spring.Cor e\Core\ControlFlowFactory.cs:line 121
at Spring.Core.ControlFlowFactory.DefaultControlFlow. Spring.Core.IControlFlow.Under(Type type, String methodName) in c:\projects\daily\Spring.Net\src\Spring\Spring.Cor e\Core\ControlFlowFactory.cs:line 97
at Spring.Aop.Framework.AutoProxy.AbstractAdvisorAuto ProxyCreator.ShouldSkip(Object obj, String name) in c:\projects\daily\Spring.Net\src\Spring\Spring.Aop \Aop\Framework\AutoProxy\AbstractAdvisorAutoProxyC reator.cs:line 164
at Spring.Aop.Framework.AutoProxy.AbstractAutoProxyCr eator.PostProcessAfterInitialization(Object obj, String name) in c:\projects\daily\Spring.Net\src\Spring\Spring.Aop \Aop\Framework\AutoProxy\AbstractAutoProxyCreator. cs:line 170
at Spring.Objects.Factory.Support.AbstractAutowireCap ableObjectFactory.ApplyObjectPostProcessorsAfterIn itialization(Object instance, String name) in c:\projects\daily\Spring.Net\src\Spring\Spring.Cor e\Objects\Factory\Support\AbstractAutowireCapableO bjectFactory.cs:line 2016
at Spring.Objects.Factory.Support.AbstractAutowireCap ableObjectFactory.ConfigureObject(String name, RootObjectDefinition definition, IObjectWrapper wrapper) in c:\projects\daily\Spring.Net\src\Spring\Spring.Cor e\Objects\Factory\Support\AbstractAutowireCapableO bjectFactory.cs:line 1862
at Spring.Objects.Factory.Support.AbstractAutowireCap ableObjectFactory.CreateObject(String name, RootObjectDefinition definition, Object[] arguments, Boolean allowEagerCaching) in c:\projects\daily\Spring.Net\src\Spring\Spring.Cor e\Objects\Factory\Support\AbstractAutowireCapableO bjectFactory.cs:line 736

The code causing this is:

Spring.Context.IApplicationContext ctx = Spring.Context.Support.ContextRegistry.GetContext( );

Commands.IFindByIdCommand cmd1 = ctx["FindByIdCommand"] as Commands.IFindByIdCommand;


A couple of other points I have noticed:

If I create these objects as protypes in my main method then all is well, however when acessing them from another dll/assembly then I am getting the above errors.

Also, if I don't place a call to

ContextRegistry.GetContext() in the main method then I get a similar exception, although at the PreInsantiateSingeltons time of the DAO singelton time during the first call to ContextRegistry.GetContext().

If there is any more information I can provide please let me know.

Thanks
Chris

Bruno Baia
05-11-2007, 02:11 PM
Hi,

It seems MethodBase.DeclaringType can be null.

In Spring.Core.ControlFlowFactory (line 140), try to replace

if(method != null)
{
return method.DeclaringType.Equals(_typeToMatch);
}

by

if(method != null && method.DeclaringType != null)
{
return method.DeclaringType.Equals(_typeToMatch);
}


I'll commit it later tonight.


What I don't understand is why it works with singleton="true"...
I never heard about problems related to AutoProxy with non singleton objects.


- Bruno

Chris Coleman
05-11-2007, 02:51 PM
Hi,

Thats great - it all works fine with that check in place. Thanks for the quick fix.

It has also removed the need to have the "Spring.Context.Support.ContextRegistry.GetContext( );" line in the main to avoid the crash on first use of the context.

Many thanks again :)
Chris