PDA

View Full Version : Loop


.ben
10-10-2005, 12:42 PM
Hi, I'll just paste the code and give some comments since it's kinda hard to explain.

Somewhere in a method I'm using spring to get an object for my uploader

_uploader = CType(BL.ObjectManager.GetObject("UploaderService"), IUploaderService)


My 'own' objectmanager looks like this:
Public Class ObjectManager

Private Shared _ctx As IApplicationContext
Private Shared _mut As New Mutex

Private Sub New()

End Sub

Public Shared Function GetObject(ByVal name As String) As Object
_mut.WaitOne()
Try
If _ctx Is Nothing Then
_ctx = ContextRegistry.GetContext()
End If
Return _ctx.GetObject(name)
Catch ex As Exception
Throw
Finally
_mut.ReleaseMutex()
End Try
End Function
End Class

In the constructor for the uploader I instantiate some other objects

Public Sub New()
_factory = New SomeFactory

In the constructor of this factory I use spring again to get a reference to a dao:


Public Sub New()
_someDao = CType(BL.ObjectManager.GetObject("someDao"), ISomeDAO)
End Sub

Now somehow, whenever I get to this point it goes back to the constructor of the uploader, who goes back all the way down the last code snippet which then goes back to the uploader etc. a nice loop.

The configuration:

<object name="someDao"
type="DAO.Implementations.Xml.someDao, DAO" factory-method="GetInstance" />

<object name="UploaderService"
type="Services.Implementations.UploaderServiceImp,Servic es"/>

The factory and the dao work fine seperate and combined, even combined via spring.

If I hardcode the instantiaton of the dao in the factory the uploader works fine too. But that's not really what I want to do :D

I hope I made myself clear, what on earth am I doing wrong.

Thanks in advance.

.ben
10-10-2005, 01:45 PM
A simpler version :p

Imports NUnit.Framework
Public Class Class1

Private _obj As Class2

Public Sub New()
_obj = CType(BL.ObjectManager.GetObject("Class2"), Class2)
End Sub
End Class

Public Class Class2
Private _obj As Class3

Public Sub New()
_obj = CType(BL.ObjectManager.GetObject("Class3"), Class3)
End Sub
End Class

Public Class Class3
Public Sub New()

End Sub
End Class

<TestFixture()> _
Public Class TestClass
<Test()> _
Public Sub test()
Dim objClass As New Class1
End Sub

End Class

<object name="Class2"
type="Tests.Class2, Tests"/>
<object name="Class3"
type="Tests.Class3, Tests"/>

It only runs if I make the call in class2 hardcoded.

Rick Evans
10-10-2005, 02:10 PM
Hi

I don't think you are doing anything wrong per se. Lazy intialization is something to be avoided though, because it introduces race conditions of the kind you are seeing. This same ground was (I believe) covered in a previous forum post (http://forum.springframework.net/viewtopic.php?p=796).

For starters... remove the mutex code and the associated try catch block in the GetObject method of your ObjectManager class. I don't think you gain anything by doing it the way you are doing... if services within your application are going to fail, you want them to fail as soon as is possible (i.e. at startup) rather than at some undetermined point in time when ObjectManager.GetObject is first called. If you have another cogent business reason why you need to do the lazy initialisation of the context, then please do share.

So, move the code that instantiates the ApplicationContext into the ctor of the ObjectManager class. If you have some heavyweight objects in your application (that are managed using Spring), then make judicious use of the 'lazy-init' attribute on the object definition of your heavyweight service(s).

Mmm... I've just realised that I havent actually said what the issue is :) The call to the ObjectManager.GetObject gets called in the scope of another (the first) call to the ObjectManager.GetObject call. The mutex won't help, since it will be the same thread calling into the GetObject method. The _ctx variable will still be null at the point that the second call enters the method, so the loop starts again, and again, and again, etc.

I'll ask, feel free to share... why can't your object that performs the lookup in its constructor simply have the dependency injected into it using constructor injection?

Ciao
Rick

.ben
04-04-2006, 02:33 PM
Took me a while to reply :p, but here I am.

Well offcourse you were right, most of the time you can 'simply' inject them in the constructor or with a set property or whatever. A place where I still use lazy intialization is i.e:

public class BLOrder
{
private System.Collections.IList m_orderLines;

public System.Collections.IList OrderLines
{
get{
if (m_orderLines != null)
{
BLOrderLineManager manager = ObjectManager.GetObject("OrderLineManager") as BLOrderLineManager;
m_orderLines = manager.GetOrderLines(this);
}
return m_orderLines;
}

}

// some other code
}

I need the manager to get the orderlines, but I don't really want to supply an orderline manager every time I create an order. Is this a valid location to use lazy initialization or does spring offer me another solution to this "problem"? I'm still discovering new stuff every day, today I started with the AOP functionality you provide.

Thanks in advance

Bruno Baia
04-05-2006, 08:33 PM
Took me a while to reply :p, but here I am.


héhé :)
I see you switched from VB.NET to C#, good choice :D

About ur "problem", if your object "OrderLineManager" is configured as a singleton, the orderlineManager will only be loaded once.


-Bruno

.ben
04-06-2006, 11:54 AM
haha, VB.Net is company policy. I don't really care in which language I write.