[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.dotnet.framework.remoting

Can you determine CAO from SAO with TransparentProxy?

Sam Santiago

7/27/2004 6:42:00 PM

I have a scenario similar to the one described in the link below. I have a SAO factory object that creates other remote objects for the client. The information in the link below indicates that the returned objects from the SAO are CAOs. I wanted to verify this.
What if I wanted to return SAOs? There's a corresponding article regarding Server-Activated Objects, but it doesn't show how a single object exposed to the client can returns SAOs.

Implementing Broker with .NET Remoting Using Client-Activated Objects
http://msdn.microsoft.com/architecture/patterns/default.aspx?pull=/library/en-us/dnpatterns/html/ImpBroker...

Any help greatly appreciated.

Thanks,

Sam

--
_______________________________
Sam Santiago
ssantiago@n0spam-SoftiTechture.com
http://www.SoftiTe...
_______________________________
17 Answers

Sam Santiago

7/27/2004 8:04:00 PM

0

I found this article below on Ingo Rammer's site that was quite useful in determining how to determine if a transparentproxy is a CAO or SAO. Returned MarshalByRefObjects from the SAO are definitely CAOs. Is it possible for an SAO to return a reference to another SAO?

HOWTO: Get a MarshalByRefObject's remote URL
http://www.thinktecture.com/Resources/RemotingFAQ/GETMARSHALBYREFOBJEC...

I translated his code for VB.NET:

' Pass in your transparentproxy object (your remote object reference)
Private Function GetTypeAndURLForObject(ByRef obj As MarshalByRefObject) As String

' trying for CAOs
Dim o As ObjRef, data As Object

o = RemotingServices.GetObjRefForProxy(obj)
If Not (o Is Nothing) Then
' Object is a CAO
For Each data In o.ChannelInfo.ChannelData

'Verify this object is a ChannelData since a CrossAppDomainData
'object is also in the collection
If TypeOf data Is ChannelDataStore Then
Dim ds As ChannelDataStore
ds = CType(data, ChannelDataStore)
If Not (ds Is Nothing) Then
Return "Type = CAO | " + ds.ChannelUris(0) + o.URI
End If
End If
Next
Else
' either SAO or not remote!
Dim URL As String = RemotingServices.GetObjectUri(obj)
Return "Type = SAO | " + URL
End If

Return String.Empty
End Function

--
_______________________________
Sam Santiago
ssantiago@n0spam-SoftiTechture.com
http://www.SoftiTe...
_______________________________
"Sam Santiago" <ssantiago@n0spam-SoftiTechture.com> wrote in message news:OZs2xlAdEHA.2352@TK2MSFTNGP09.phx.gbl...
I have a scenario similar to the one described in the link below. I have a SAO factory object that creates other remote objects for the client. The information in the link below indicates that the returned objects from the SAO are CAOs. I wanted to verify this.
What if I wanted to return SAOs? There's a corresponding article regarding Server-Activated Objects, but it doesn't show how a single object exposed to the client can returns SAOs.

Implementing Broker with .NET Remoting Using Client-Activated Objects
http://msdn.microsoft.com/architecture/patterns/default.aspx?pull=/library/en-us/dnpatterns/html/ImpBroker...

Any help greatly appreciated.

Thanks,

Sam

--
_______________________________
Sam Santiago
ssantiago@n0spam-SoftiTechture.com
http://www.SoftiTe...
_______________________________

Sunny

7/27/2004 9:55:00 PM

0

Hi Sam,

SAO and CAO are NOT types of objects. These names have meaning only in
terms of using config file configuration or programmatically with
RegisterWellKnown..., I.e. when the remoting infrastructure takes care
about the creation of the object. CAOs are created on a client request,
I.e. the client decides when this object to be created.

SAO are 2 kinds:
1. Singlecall - they are created by the remoting infrastructure,
whenever a method call is received, and they live only for that method
call. On the next call a new object is created.

2. Singletons - when a method call is received, if there is no live
object, a new one is created. And every next method call (from any
client) will either hit the same object, or if its lifetime expires, a
new one will be created.

This all happens when you use RegisterWellKnown... or config file
registration.

Now, when you manually create and expose the objects, they are neither
SAOs, nor CAOs. I'll try to explain, making comparison with the SAO/CAO
naming, starting with SAO Singleton, as a base one for factory patterns
only serverside):

1.

FactoryObject myfactory = new MyFactory();
RemotingServices.Marshal(myfactory, "MyFactory.rem");

with this, now all clients hitting the url ".../MyFactory.rem" will hit
the same myfactory objects. I.e. it behaves like a SAO Singleton.

2.

class MyInternalSinglecall
{
public string DoSomething(string s)
{
return "Received: " + s;
}
}

class MySinglecallEntryPoint : MBR
{
public string DoSomething(string s)
{
MyInternalSingleton obj = new MyInternalSingleton();
return obj.DoSomething(s);
}
}

When a client hits the exposed MySinglecallEntryPoint object, it creates
always a new internal object to serve the request.
As you see, this example does not make any practical sense, but thats
exactly how Singlecalls are working, except that here your code is the
one which creates the working instance, and when using WellKnown... this
is done by the system itself.

3.
Standard factory pattern. Your factory method creates a new object,
which is returned to the calling client. This is like CAO done by
remothing. Just here your method is the one who creates the returned
object.

Now, look at this factory object:

class MyFactory : MBR
{
static ClientObject cao;

public ClientObject GetNewObject()
{
if (cao == null)
cao = new ClientObject();
return cao;
}
}

As you can see, even this is a factory, and it returns an object, it
returns always a reference to the same object to all clients. Is it SAO
or CAO?

Or if you move "static ClientObject cao;" somewhere else, in another
class, and other method expose it on an url with Marshal(cao)? Now every
client which hits that url will work with exactly the same object, which
is returned to every client hitting the factory method. Is it SAO or
CAO?

Conclusion: SAO and CAO are only a names for how the server objects are
created and how they are exposed to different clients. You can accept
this naming convention, and still you can provide your own
implementation for creating and exposing the objects to the clients.

All we use CAO as name for an object, which is exposed only to one
client, and is created because this client requested it. If this object
is created by the remoting system itself, or by our code (factory), it
doesn't matter. Important think is only the behaviour.

Same can be said for SAOs, they are accessible on a given url, and are
accessible for all clients.

I do not know how clear was all that :), so please if something is
confusing, ask.

Sunny

Sam Santiago

7/27/2004 11:23:00 PM

0

Thanks for replying. I see your points. Using a static CAO maybe a good solution in my situation. CAOs do maintain state as well, so if you do have a static reference you have to ensure you do not store stateful information within the object or re-initialize it with every invocation to ensure you start with a clean state. CAO and SAO do seem to have some more differences other than how you use an object.

Check out this link on Remoting Performance:
http://msdn.microsoft.com/library/en-us/dnpag/html/scalenetchapt11.asp?frame=true#scalenetchap...

Here's an excerpt:

a.. Consider the limited scalability offered by CAOs. CAOs are not generally recommended, due to scalability limitations. Objects activated at the client cause the client proxy reference to be bound to a specific server where the server object was activated. This server affinity reduces the ability of your application to scale, and it negatively impacts performance because load on the individual server increases. When the server load increases, there is no way to offload the calls from the client to another server in the farm that has less load. If you have a single server solution, this is not an issue. However, if you need to scale out and use a server cluster, CAOs significantly limit scalability. CAOs do provide the benefit of allowing the server object to maintain state across method calls. Generally, it is better to design stateless objects for performance and scalability.

Thanks,

Sam

--
_______________________________
Sam Santiago
ssantiago@n0spam-SoftiTechture.com
http://www.SoftiTe...
_______________________________
"Sunny" <sunny@newsgroups.nospam> wrote in message news:OZ6odRCdEHA.3016@tk2msftngp13.phx.gbl...
> Hi Sam,
>
> SAO and CAO are NOT types of objects. These names have meaning only in
> terms of using config file configuration or programmatically with
> RegisterWellKnown..., I.e. when the remoting infrastructure takes care
> about the creation of the object. CAOs are created on a client request,
> I.e. the client decides when this object to be created.
>
> SAO are 2 kinds:
> 1. Singlecall - they are created by the remoting infrastructure,
> whenever a method call is received, and they live only for that method
> call. On the next call a new object is created.
>
> 2. Singletons - when a method call is received, if there is no live
> object, a new one is created. And every next method call (from any
> client) will either hit the same object, or if its lifetime expires, a
> new one will be created.
>
> This all happens when you use RegisterWellKnown... or config file
> registration.
>
> Now, when you manually create and expose the objects, they are neither
> SAOs, nor CAOs. I'll try to explain, making comparison with the SAO/CAO
> naming, starting with SAO Singleton, as a base one for factory patterns
> only serverside):
>
> 1.
>
> FactoryObject myfactory = new MyFactory();
> RemotingServices.Marshal(myfactory, "MyFactory.rem");
>
> with this, now all clients hitting the url ".../MyFactory.rem" will hit
> the same myfactory objects. I.e. it behaves like a SAO Singleton.
>
> 2.
>
> class MyInternalSinglecall
> {
> public string DoSomething(string s)
> {
> return "Received: " + s;
> }
> }
>
> class MySinglecallEntryPoint : MBR
> {
> public string DoSomething(string s)
> {
> MyInternalSingleton obj = new MyInternalSingleton();
> return obj.DoSomething(s);
> }
> }
>
> When a client hits the exposed MySinglecallEntryPoint object, it creates
> always a new internal object to serve the request.
> As you see, this example does not make any practical sense, but thats
> exactly how Singlecalls are working, except that here your code is the
> one which creates the working instance, and when using WellKnown... this
> is done by the system itself.
>
> 3.
> Standard factory pattern. Your factory method creates a new object,
> which is returned to the calling client. This is like CAO done by
> remothing. Just here your method is the one who creates the returned
> object.
>
> Now, look at this factory object:
>
> class MyFactory : MBR
> {
> static ClientObject cao;
>
> public ClientObject GetNewObject()
> {
> if (cao == null)
> cao = new ClientObject();
> return cao;
> }
> }
>
> As you can see, even this is a factory, and it returns an object, it
> returns always a reference to the same object to all clients. Is it SAO
> or CAO?
>
> Or if you move "static ClientObject cao;" somewhere else, in another
> class, and other method expose it on an url with Marshal(cao)? Now every
> client which hits that url will work with exactly the same object, which
> is returned to every client hitting the factory method. Is it SAO or
> CAO?
>
> Conclusion: SAO and CAO are only a names for how the server objects are
> created and how they are exposed to different clients. You can accept
> this naming convention, and still you can provide your own
> implementation for creating and exposing the objects to the clients.
>
> All we use CAO as name for an object, which is exposed only to one
> client, and is created because this client requested it. If this object
> is created by the remoting system itself, or by our code (factory), it
> doesn't matter. Important think is only the behaviour.
>
> Same can be said for SAOs, they are accessible on a given url, and are
> accessible for all clients.
>
> I do not know how clear was all that :), so please if something is
> confusing, ask.
>
> Sunny
>

Sam Santiago

7/31/2004 4:52:00 AM

0

FYI:
All MBR objects created by using New in an SAO and returned to the client are treated as CAOs by the client. I experimented with returning an SAO reference from another SAO and came up with the following method. If you want to return a SAO to the client then you have to create your object using Activator.GetObject and marshal it yourself.

Here's an example:

On the Server side:

' This is a method inside of a Singleton SAO to return a reference to
another Singleton SAO to the client.
Public Function Return_SAO_to_Client() As ObjRef
Dim BO As MyMBR
BO = CType(Activator.GetObject(GetType(MyMBR), "http://localhost:8085/MyMBR"), MyMBR)
Return RemotingServices.Marshal(BO)
End Function

On the ClientSide:

Dim tempbo As MyMBR
tempbo = CType(RemotingServices.Unmarshal(myRootSAO.Return_SAO_to_Client), MyMBR)

Thanks,

Sam


--
_______________________________
Sam Santiago
ssantiago@n0spam-SoftiTechture.com
http://www.SoftiTe...
_______________________________
"Sam Santiago" <ssantiago@n0spam-SoftiTechture.com> wrote in message news:OZs2xlAdEHA.2352@TK2MSFTNGP09.phx.gbl...
I have a scenario similar to the one described in the link below. I have a SAO factory object that creates other remote objects for the client. The information in the link below indicates that the returned objects from the SAO are CAOs. I wanted to verify this.
What if I wanted to return SAOs? There's a corresponding article regarding Server-Activated Objects, but it doesn't show how a single object exposed to the client can returns SAOs.

Implementing Broker with .NET Remoting Using Client-Activated Objects
http://msdn.microsoft.com/architecture/patterns/default.aspx?pull=/library/en-us/dnpatterns/html/ImpBroker...

Any help greatly appreciated.

Thanks,

Sam

--
_______________________________
Sam Santiago
ssantiago@n0spam-SoftiTechture.com
http://www.SoftiTe...
_______________________________

Sunny

7/31/2004 8:13:00 PM

0

Hi,

you can have the same, if you do this:

<shared.dll>

public interface IClientObject
{
string GetStringData();
int GetIntData();
}

public interface ISAOGetter
{
IClientObject GetObject();
}


<server>

public class MySharedObject : MBR, IClientObject
{
public string GetStringData()
{
return "Hello";
}
public int GetIntData()
{
return 2;
}
}

public class ObjectPublisher : MBR, ISAOGetter
{
private MySharedObject sharedObject = new MySharedObject();

public IClientObject GetObject()
{
return (IClientObject)sharedObject;
}
}

Now, you can expose ObjectPublisher as SAO Singleton, and all clients
calling GetObject will receive one and the same sharedObject. Even this
object is created with "new", it is NOT treated as CAO. It is SAO
Singleton in all meanings.

So, if you read again my previous post, there I state that SAO and CAO
are only naming conventions, which describe how the remoted object
behave. If one object is accessible by all clients, it is SAO, if every
client own its own object, this is CAO.

It doesn't meter how you expose these objects - using Marshal,
RegisterWellKnown, or "return". As you see above, even using return the
returned object acts as SAO.

Just 2c :)

Sunny

In article <OvZRmordEHA.3392@tk2msftngp13.phx.gbl>, ssantiago@n0spam-
SoftiTechture.com says...
> FYI:
> All MBR objects created by using New in an SAO and returned to the client are treated as CAOs by the client. I experimented with returning an SAO reference from another SAO and came up with the following method. If you want to return a SAO to the client then you have to create your object using Activator.GetObject and marshal it yourself.
>
> Here's an example:
>
> On the Server side:
>
> ' This is a method inside of a Singleton SAO to return a reference to
> another Singleton SAO to the client.
> Public Function Return_SAO_to_Client() As ObjRef
> Dim BO As MyMBR
> BO = CType(Activator.GetObject(GetType(MyMBR), "http://localhost:8085/MyMBR"), MyMBR)
> Return RemotingServices.Marshal(BO)
> End Function
>
> On the ClientSide:
>
> Dim tempbo As MyMBR
> tempbo = CType(RemotingServices.Unmarshal(myRootSAO.Return_SAO_to_Client), MyMBR)
>
> Thanks,
>
> Sam
>
>
>

Sam Santiago

8/1/2004 5:25:00 PM

0

Sunny,

Thanks for your reply. Your postings always get me thinking. Since there was nothing on TV last night I figured I would try your approach ;-). I created an example that uses both approaches: 1) A Singleton SAO factory that returns an MBR object and 2) A Singleton SAO factory that returns a ObjRef to another Singleton SAO. You can download the source here: http://www.softitechture.com/di....

Below is a summary and links to other articles but the conclusion is that in order to implement a true Singleton object you must return a Singleton SAO to the client, method #2. The only way to do so is to create an SAO on the server using the Activator class and to return an ObjRef to the client by Marshaling the SAO reference yourself.

I think your assumption that there is no difference between an SAO and CAO is not correct. There are fundamental differences between these two types of remote objects and the context of how you use an object alone does not determine whether it is an SAO or CAO. How you activate an object seem to determine this classification and most importantly any MBR object returned to a client that is created by another remote object (factory pattern) that is created with the New statement will be classified as a CAO.

The key fundamental difference between an SAO and CAO is their lifetime management with leases. SAO lifetimes are controlled by the server, whereas CAO lifetimes are controlled by the client. If you attempt to use a CAO as a singleton that services all clients it's lifetime will be controlled by the first client that creates it. Even if you give this CAO a lifetime lease, it is not the same as a lifetime lease on an SAO. As soon as the reference from the first client goes out of scope or is set to nothing your CAO singleton will be recycled on the server once it's lease expires. Below are some references to an MSDN article and the ..NET documentation that discusses this in more depth.

I have attached a ZIP file to this message that is a Visual Studio solution based on the code you provided below that demonstrates this behavior. Below is also the output from an execution of this program.


Client Activation
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconclientacti...

Here's an excerpt:

The client might even request an indefinite default lifetime, effectively preventing the remote object from ever being recycled until the server application domain is torn down. The difference between this and a server-activated indefinite lifetime is that an indefinite server-activated object will serve all client requests for that type, whereas the client-activated instances serve only the client and the reference that was responsible for their creation.

Managing the Lifetime of Remote .NET Objects with Leasing and Sponsorship by Juval Lowy
http://msdn.microsoft.com/msdnmag/issues/03/12/LeaseManager/de...

Here's an excerpt:

The case of the client-activated object is the one affected most by the leasing mechanism. When using a client-activated model, every client that creates a new object gets a dedicated server object. That object's lifetime is governed by a lease, and the object will be disconnected from the clients once its lease has expired. The only safe way to manage client-activated objects is to use sponsors. All other options, such as global lease properties or configuring individual objects' leases, are speculative at best. Ultimately, only the client knows when it no longer needs the object.

Console output from running attached test:

**************************************************************************************************************
Remote Client #1

Note the URL & GUID of the CAO and the returned value from GetIntData from both the CAO
and SAO MySharedObjects.
**************************************************************************************************************
Configuring Remoting
8/1/2004 8:33:22 AM
- ISAOGetter type URL: Type = SAO | http://localhost:8085/ObjectPublisher
8/1/2004 8:33:23 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
- Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
- GetIntData = 1 <-------------------
8/1/2004 8:33:23 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
- Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
- GetIntData = 2 <-------------------
8/1/2004 8:33:23 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 1 <-------------------
8/1/2004 8:33:23 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 2 <-------------------
CAO reference set to Nothing.

**************************************************************************************************************
Remote Client #2 (launched 7 seconds after #1)

Note the URL & GUID of the CAO are the same as for #1 and the returned value from GetIntData
has continued where #1 left off for both the CAO and SAO.
**************************************************************************************************************
Configuring Remoting
8/1/2004 8:33:30 AM
- ISAOGetter type URL: Type = SAO | http://localhost:8085/ObjectPublisher
8/1/2004 8:33:30 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
- Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
- GetIntData = 3 <-------------------
8/1/2004 8:33:30 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
- Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
- GetIntData = 4 <-------------------
8/1/2004 8:33:30 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 3 <-------------------
8/1/2004 8:33:30 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 4 <-------------------
CAO reference set to Nothing.

**************************************************************************************************************
Remote Client #3 (launched 7 MINUTES after #2)

Note the URL & GUID of the CAO are NOT the same as for #1 and #2. This is a
totally DIFFERENT object. This CANNOT be a Singleton by definition.
Note that the returned value from GetIntData has NOT been continued where #2 left off
for the CAO, but has restarted at 1.
Note that the returned value from the GetIntData for the SAO MySharedObject CONTINUES
to increment where #2 left off. This is THE SAME object answering client requests
and is a Singleton by definition.
**************************************************************************************************************

Configuring Remoting
8/1/2004 8:40:00 AM
- ISAOGetter type URL: Type = SAO | http://localhost:8085/ObjectPublisher
8/1/2004 8:40:00 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/tShr4Faa2r2UEPsUfu8eEuAo_2.rem
- Guid: 40f316da-9c95-4daf-b14a-1776f7e0b476
- GetIntData = 1 <-------------------
8/1/2004 8:40:00 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/tShr4Faa2r2UEPsUfu8eEuAo_2.rem
- Guid: 40f316da-9c95-4daf-b14a-1776f7e0b476
- GetIntData = 2 <-------------------
8/1/2004 8:40:00 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 5 <-------------------
8/1/2004 8:40:00 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 6 <-------------------
CAO reference set to Nothing.


Thanks,

Sam
--
_______________________________
Sam Santiago
ssantiago@n0spam-SoftiTechture.com
http://www.SoftiTe...
_______________________________

Sunny

8/1/2004 7:35:00 PM

0

Hi Sam,

thanks for all that efforts. For sure I'll take a deeper look these
days, when I find some free time, and I'll post back.

Thanks again
Sunny

In article <#ms6$x#dEHA.720@TK2MSFTNGP11.phx.gbl>, ssantiago@n0spam-
SoftiTechture.com says...
> Sunny,
>
> Thanks for your reply. Your postings always get me thinking. Since there was nothing on TV last night I figured I would try your approach ;-). I created an example that uses both approaches: 1) A Singleton SAO factory that returns an MBR object and 2) A Singleton SAO factory that returns a ObjRef to another Singleton SAO. You can download the source here: http://www.softitechture.com/di....
>
> Below is a summary and links to other articles but the conclusion is that in order to implement a true Singleton object you must return a Singleton SAO to the client, method #2. The only way to do so is to create an SAO on the server using the Activator class and to return an ObjRef to the client by Marshaling the SAO reference yourself.
>
> I think your assumption that there is no difference between an SAO and CAO is not correct. There are fundamental differences between these two types of remote objects and the context of how you use an object alone does not determine whether it is an SAO or CAO. How you activate an object seem to determine this classification and most importantly any MBR object returned to a client that is created by another remote object (factory pattern) that is created with the New
statement will be classified as a CAO.
>
> The key fundamental difference between an SAO and CAO is their lifetime management with leases. SAO lifetimes are controlled by the server, whereas CAO lifetimes are controlled by the client. If you attempt to use a CAO as a singleton that services all clients it's lifetime will be controlled by the first client that creates it. Even if you give this CAO a lifetime lease, it is not the same as a lifetime lease on an SAO. As soon as the reference from the first
client goes out of scope or is set to nothing your CAO singleton will be recycled on the server once it's lease expires. Below are some references to an MSDN article and the .NET documentation that discusses this in more depth.
>
> I have attached a ZIP file to this message that is a Visual Studio solution based on the code you provided below that demonstrates this behavior. Below is also the output from an execution of this program.
>
>
> Client Activation
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconclientacti...
>
> Here's an excerpt:
>
> The client might even request an indefinite default lifetime, effectively preventing the remote object from ever being recycled until the server application domain is torn down. The difference between this and a server-activated indefinite lifetime is that an indefinite server-activated object will serve all client requests for that type, whereas the client-activated instances serve only the client and the reference that was responsible for their creation.
>
> Managing the Lifetime of Remote .NET Objects with Leasing and Sponsorship by Juval Lowy
> http://msdn.microsoft.com/msdnmag/issues/03/12/LeaseManager/de...
>
> Here's an excerpt:
>
> The case of the client-activated object is the one affected most by the leasing mechanism. When using a client-activated model, every client that creates a new object gets a dedicated server object. That object's lifetime is governed by a lease, and the object will be disconnected from the clients once its lease has expired. The only safe way to manage client-activated objects is to use sponsors. All other options, such as global lease properties or configuring
individual objects' leases, are speculative at best. Ultimately, only the client knows when it no longer needs the object.
>
> Console output from running attached test:
>
> **************************************************************************************************************
> Remote Client #1
>
> Note the URL & GUID of the CAO and the returned value from GetIntData from both the CAO
> and SAO MySharedObjects.
> **************************************************************************************************************
> Configuring Remoting
> 8/1/2004 8:33:22 AM
> - ISAOGetter type URL: Type = SAO | http://localhost:8085/ObjectPublisher
> 8/1/2004 8:33:23 AM
> - myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
> _9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
> - Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
> - GetIntData = 1 <-------------------
> 8/1/2004 8:33:23 AM
> - myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
> _9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
> - Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
> - GetIntData = 2 <-------------------
> 8/1/2004 8:33:23 AM
> - myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
> - Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
> - GetIntData = 1 <-------------------
> 8/1/2004 8:33:23 AM
> - myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
> - Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
> - GetIntData = 2 <-------------------
> CAO reference set to Nothing.
>
> **************************************************************************************************************
> Remote Client #2 (launched 7 seconds after #1)
>
> Note the URL & GUID of the CAO are the same as for #1 and the returned value from GetIntData
> has continued where #1 left off for both the CAO and SAO.
> **************************************************************************************************************
> Configuring Remoting
> 8/1/2004 8:33:30 AM
> - ISAOGetter type URL: Type = SAO | http://localhost:8085/ObjectPublisher
> 8/1/2004 8:33:30 AM
> - myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
> _9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
> - Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
> - GetIntData = 3 <-------------------
> 8/1/2004 8:33:30 AM
> - myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
> _9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
> - Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
> - GetIntData = 4 <-------------------
> 8/1/2004 8:33:30 AM
> - myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
> - Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
> - GetIntData = 3 <-------------------
> 8/1/2004 8:33:30 AM
> - myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
> - Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
> - GetIntData = 4 <-------------------
> CAO reference set to Nothing.
>
> **************************************************************************************************************
> Remote Client #3 (launched 7 MINUTES after #2)
>
> Note the URL & GUID of the CAO are NOT the same as for #1 and #2. This is a
> totally DIFFERENT object. This CANNOT be a Singleton by definition.
> Note that the returned value from GetIntData has NOT been continued where #2 left off
> for the CAO, but has restarted at 1.
> Note that the returned value from the GetIntData for the SAO MySharedObject CONTINUES
> to increment where #2 left off. This is THE SAME object answering client requests
> and is a Singleton by definition.
> **************************************************************************************************************
>
> Configuring Remoting
> 8/1/2004 8:40:00 AM
> - ISAOGetter type URL: Type = SAO | http://localhost:8085/ObjectPublisher
> 8/1/2004 8:40:00 AM
> - myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
> _9d65_2e74985d3d3d/tShr4Faa2r2UEPsUfu8eEuAo_2.rem
> - Guid: 40f316da-9c95-4daf-b14a-1776f7e0b476
> - GetIntData = 1 <-------------------
> 8/1/2004 8:40:00 AM
> - myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
> _9d65_2e74985d3d3d/tShr4Faa2r2UEPsUfu8eEuAo_2.rem
> - Guid: 40f316da-9c95-4daf-b14a-1776f7e0b476
> - GetIntData = 2 <-------------------
> 8/1/2004 8:40:00 AM
> - myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
> - Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
> - GetIntData = 5 <-------------------
> 8/1/2004 8:40:00 AM
> - myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
> - Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
> - GetIntData = 6 <-------------------
> CAO reference set to Nothing.
>
>
> Thanks,
>
> Sam
>

Ken Kolda

8/2/2004 5:24:00 PM

0

Sam --

You can create a singleton SAO without going through the process you show in your code example #2. In that example, you're having the server register a well-known singleton type, but instead of having the client retrieve that object directly, you make a TCP connection from the server to itself to get the singleton (which is instantiated by the remoting framework) and then return that object to the client. That's not the best way to do this.

Generally, if you need a singleton, there are two main ways of accomplishing this, depending on your needs:

1) Register the well-known type and allow the remoting framework to instantiate and hold the reference to it. Do this if you do not need to use the object within the server-side code. Also, this method has the benefit in that the remoting framework will re-instantiate the singleton if its lease expires (but, in that case, it's really not a singleton in the way most people think about it).

2) Write the code in your server to create an object instance, store it in a static class variable somewhere and then call RemotingService.Marshal(). You now have effectively a singleton which you can return to multiple clients without a problem and access within the server code itself.

I can't think of any case where you would need to have the server use the Activator to get a singleton from itself only to return it to the client.

I think your example code has confused the issue a bit because your ObjectPublisher object, which you have made a singleton, doesn't override InitializeLifetimeServices(). Thus, it expired before your third test, which is why you get a different CAO for your third test run than you did for the first two. It has nothing to do with objects being SAO or CAO -- it's simply that your singleton was disconnected because it timed out.

Ken



"Sam Santiago" <ssantiago@n0spam-SoftiTechture.com> wrote in message news:%23ms6$x%23dEHA.720@TK2MSFTNGP11.phx.gbl...
Sunny,

Thanks for your reply. Your postings always get me thinking. Since there was nothing on TV last night I figured I would try your approach ;-). I created an example that uses both approaches: 1) A Singleton SAO factory that returns an MBR object and 2) A Singleton SAO factory that returns a ObjRef to another Singleton SAO. You can download the source here: http://www.softitechture.com/di....

Below is a summary and links to other articles but the conclusion is that in order to implement a true Singleton object you must return a Singleton SAO to the client, method #2. The only way to do so is to create an SAO on the server using the Activator class and to return an ObjRef to the client by Marshaling the SAO reference yourself.

I think your assumption that there is no difference between an SAO and CAO is not correct. There are fundamental differences between these two types of remote objects and the context of how you use an object alone does not determine whether it is an SAO or CAO. How you activate an object seem to determine this classification and most importantly any MBR object returned to a client that is created by another remote object (factory pattern) that is created with the New statement will be classified as a CAO.

The key fundamental difference between an SAO and CAO is their lifetime management with leases. SAO lifetimes are controlled by the server, whereas CAO lifetimes are controlled by the client. If you attempt to use a CAO as a singleton that services all clients it's lifetime will be controlled by the first client that creates it. Even if you give this CAO a lifetime lease, it is not the same as a lifetime lease on an SAO. As soon as the reference from the first client goes out of scope or is set to nothing your CAO singleton will be recycled on the server once it's lease expires. Below are some references to an MSDN article and the .NET documentation that discusses this in more depth.

I have attached a ZIP file to this message that is a Visual Studio solution based on the code you provided below that demonstrates this behavior. Below is also the output from an execution of this program.


Client Activation
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconclientacti...

Here's an excerpt:

The client might even request an indefinite default lifetime, effectively preventing the remote object from ever being recycled until the server application domain is torn down. The difference between this and a server-activated indefinite lifetime is that an indefinite server-activated object will serve all client requests for that type, whereas the client-activated instances serve only the client and the reference that was responsible for their creation.

Managing the Lifetime of Remote .NET Objects with Leasing and Sponsorship by Juval Lowy
http://msdn.microsoft.com/msdnmag/issues/03/12/LeaseManager/de...

Here's an excerpt:

The case of the client-activated object is the one affected most by the leasing mechanism. When using a client-activated model, every client that creates a new object gets a dedicated server object. That object's lifetime is governed by a lease, and the object will be disconnected from the clients once its lease has expired. The only safe way to manage client-activated objects is to use sponsors. All other options, such as global lease properties or configuring individual objects' leases, are speculative at best. Ultimately, only the client knows when it no longer needs the object.

Console output from running attached test:

**************************************************************************************************************
Remote Client #1

Note the URL & GUID of the CAO and the returned value from GetIntData from both the CAO
and SAO MySharedObjects.
**************************************************************************************************************
Configuring Remoting
8/1/2004 8:33:22 AM
- ISAOGetter type URL: Type = SAO | http://localhost:8085/ObjectPublisher
8/1/2004 8:33:23 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
- Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
- GetIntData = 1 <-------------------
8/1/2004 8:33:23 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
- Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
- GetIntData = 2 <-------------------
8/1/2004 8:33:23 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 1 <-------------------
8/1/2004 8:33:23 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 2 <-------------------
CAO reference set to Nothing.

**************************************************************************************************************
Remote Client #2 (launched 7 seconds after #1)

Note the URL & GUID of the CAO are the same as for #1 and the returned value from GetIntData
has continued where #1 left off for both the CAO and SAO.
**************************************************************************************************************
Configuring Remoting
8/1/2004 8:33:30 AM
- ISAOGetter type URL: Type = SAO | http://localhost:8085/ObjectPublisher
8/1/2004 8:33:30 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
- Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
- GetIntData = 3 <-------------------
8/1/2004 8:33:30 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
- Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
- GetIntData = 4 <-------------------
8/1/2004 8:33:30 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 3 <-------------------
8/1/2004 8:33:30 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 4 <-------------------
CAO reference set to Nothing.

**************************************************************************************************************
Remote Client #3 (launched 7 MINUTES after #2)

Note the URL & GUID of the CAO are NOT the same as for #1 and #2. This is a
totally DIFFERENT object. This CANNOT be a Singleton by definition.
Note that the returned value from GetIntData has NOT been continued where #2 left off
for the CAO, but has restarted at 1.
Note that the returned value from the GetIntData for the SAO MySharedObject CONTINUES
to increment where #2 left off. This is THE SAME object answering client requests
and is a Singleton by definition.
**************************************************************************************************************

Configuring Remoting
8/1/2004 8:40:00 AM
- ISAOGetter type URL: Type = SAO | http://localhost:8085/ObjectPublisher
8/1/2004 8:40:00 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/tShr4Faa2r2UEPsUfu8eEuAo_2.rem
- Guid: 40f316da-9c95-4daf-b14a-1776f7e0b476
- GetIntData = 1 <-------------------
8/1/2004 8:40:00 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/tShr4Faa2r2UEPsUfu8eEuAo_2.rem
- Guid: 40f316da-9c95-4daf-b14a-1776f7e0b476
- GetIntData = 2 <-------------------
8/1/2004 8:40:00 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 5 <-------------------
8/1/2004 8:40:00 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 6 <-------------------
CAO reference set to Nothing.


Thanks,

Sam
--
_______________________________
Sam Santiago
ssantiago@n0spam-SoftiTechture.com
http://www.SoftiTe...
_______________________________

Sam Santiago

8/2/2004 8:54:00 PM

0

Here are some more observations after playing with this some more. In my
first test run below in my first message, my Singleton SAO factory object,
ObjectPublisher, did not have a lifetime lease. Therefore, it was this
object that was being reclaimed after 5 minutes, NOT the contained MBR,
MySharedObject. With a lifetime lease on ObjectPublisher, the same
MySharedObject instance was returned to all the clients and "behaved" like a
Singleton, maintaining it's state in between calls. However, the returned
MySharedObject to the client is a CAO. Lifetime management is definitely
different between a CAO and a SAO and I would think odds are high that there
are more low level differences. Another side effect of the CAO approach is
that your CAO object's lifetime will be dependent on the lifetime of the
factory. If your factory has a lifetime lease, then in theory this should
not be a problem, but generally you would not want the life of an object
created by a factory object dependent on that factory for its existence.

Therefore, it seems that both options - 1) A Singleton SAO factory that
returns an MBR object that will be a CAO and 2) A Singleton SAO factory that
returns a ObjRef to another Singleton SAO - are viable. Although the CAO
approach does behave like a Singleton my personal preference would be to
lean towards the safe side and returning a true Singleton SAO to the client.

I have updated the sample application at
http://www.softitechture.com/di... if you would like to see the
source.


Console output from test run #2 (lifetime lease on SAO Factory):

****************************************************************************
**********************************
Remote Client #1

Note the URL & GUID of the CAO and the returned value from GetIntData from
both the CAO
and SAO MySharedObjects.
****************************************************************************
**********************************
Configuring Remoting
8/2/2004 11:27:39 AM
- ISAOGetter type URL: Type = SAO |
http://localhost:8085/ObjectPublisher
8/2/2004 11:27:40 AM
- myTempBO type URL: Type = CAO |
http://127.0.0.1:8085/87861b38...
_8844_06e78e937d6a/VsLMsusbiRukKWYE6GjQXrQf_1.rem
- Guid: 8a33880d-4f6a-4436-84d6-b3dc96441271
- GetIntData = 1 <-------------------------------------------------
8/2/2004 11:27:40 AM
- myTempBO type URL: Type = CAO |
http://127.0.0.1:8085/87861b38...
_8844_06e78e937d6a/VsLMsusbiRukKWYE6GjQXrQf_1.rem
- Guid: 8a33880d-4f6a-4436-84d6-b3dc96441271
- GetIntData = 2 <-------------------------------------------------
8/2/2004 11:27:40 AM
- myTempBO2 type URL: Type = SAO |
http://localhost:8085/MySharedObject
- Guid: f74fc69e-fa0c-4adb-9a5d-6bec1718e4a0
- GetIntData = 1 <-------------------------------------------------
8/2/2004 11:27:40 AM
- myTempBO2 type URL: Type = SAO |
http://localhost:8085/MySharedObject
- Guid: f74fc69e-fa0c-4adb-9a5d-6bec1718e4a0
- GetIntData = 2 <-------------------------------------------------
CAO reference set to Nothing.


****************************************************************************
**********************************
Remote Client #2 (launched 15 seconds after #1)

Note the URL & GUID of the CAO are the same as for #1 and the returned value
from GetIntData
has continued where #1 left off for both the CAO and SAO.
****************************************************************************
**********************************
Configuring Remoting
8/2/2004 11:27:55 AM
- ISAOGetter type URL: Type = SAO |
http://localhost:8085/ObjectPublisher
8/2/2004 11:27:55 AM
- myTempBO type URL: Type = CAO |
http://127.0.0.1:8085/87861b38...
_8844_06e78e937d6a/VsLMsusbiRukKWYE6GjQXrQf_1.rem
- Guid: 8a33880d-4f6a-4436-84d6-b3dc96441271
- GetIntData = 3 <-------------------------------------------------
8/2/2004 11:27:55 AM
- myTempBO type URL: Type = CAO |
http://127.0.0.1:8085/87861b38...
_8844_06e78e937d6a/VsLMsusbiRukKWYE6GjQXrQf_1.rem
- Guid: 8a33880d-4f6a-4436-84d6-b3dc96441271
- GetIntData = 4 <-------------------------------------------------
8/2/2004 11:27:55 AM
- myTempBO2 type URL: Type = SAO |
http://localhost:8085/MySharedObject
- Guid: f74fc69e-fa0c-4adb-9a5d-6bec1718e4a0
- GetIntData = 3 <-------------------------------------------------
8/2/2004 11:27:55 AM
- myTempBO2 type URL: Type = SAO |
http://localhost:8085/MySharedObject
- Guid: f74fc69e-fa0c-4adb-9a5d-6bec1718e4a0
- GetIntData = 4 <-------------------------------------------------
CAO reference set to Nothing.


****************************************************************************
**********************************
Remote Client #3 (launched 9 MINUTES after #2)

Note the URL & GUID of the CAO ARE the same as for #1 and #2. This is the
SAME
object.
Note that the returned value from GetIntData has remembered state for both
the CAO
and SAO approach.

These are THE SAME objects answering client requests and are Singletons by
definition.
****************************************************************************
**********************************
Configuring Remoting
8/2/2004 11:36:46 AM
- ISAOGetter type URL: Type = SAO |
http://localhost:8085/ObjectPublisher
8/2/2004 11:36:47 AM
- myTempBO type URL: Type = CAO |
http://127.0.0.1:8085/87861b38...
_8844_06e78e937d6a/VsLMsusbiRukKWYE6GjQXrQf_1.rem
- Guid: 8a33880d-4f6a-4436-84d6-b3dc96441271
- GetIntData = 5 <-------------------------------------------------
8/2/2004 11:36:47 AM
- myTempBO type URL: Type = CAO |
http://127.0.0.1:8085/87861b38...
_8844_06e78e937d6a/VsLMsusbiRukKWYE6GjQXrQf_1.rem
- Guid: 8a33880d-4f6a-4436-84d6-b3dc96441271
- GetIntData = 6 <-------------------------------------------------
8/2/2004 11:36:47 AM
- myTempBO2 type URL: Type = SAO |
http://localhost:8085/MySharedObject
- Guid: f74fc69e-fa0c-4adb-9a5d-6bec1718e4a0
- GetIntData = 5 <-------------------------------------------------
8/2/2004 11:36:47 AM
- myTempBO2 type URL: Type = SAO |
http://localhost:8085/MySharedObject
- Guid: f74fc69e-fa0c-4adb-9a5d-6bec1718e4a0
- GetIntData = 6 <-------------------------------------------------
CAO reference set to Nothing.



Thanks,

Sam

--
_______________________________
Sam Santiago
ssantiago@n0spam-SoftiTechture.com
http://www.SoftiTe...
_______________________________
"Sunny" <sunny@newsgroups.nospam> wrote in message
news:ukjRw6$dEHA.1764@TK2MSFTNGP10.phx.gbl...
> Hi Sam,
>
> thanks for all that efforts. For sure I'll take a deeper look these
> days, when I find some free time, and I'll post back.
>
> Thanks again
> Sunny
>
> In article <#ms6$x#dEHA.720@TK2MSFTNGP11.phx.gbl>, ssantiago@n0spam-
> SoftiTechture.com says...
> > Sunny,
> >
> > Thanks for your reply. Your postings always get me thinking. Since
there was nothing on TV last night I figured I would try your approach ;-).
I created an example that uses both approaches: 1) A Singleton SAO factory
that returns an MBR object and 2) A Singleton SAO factory that returns a
ObjRef to another Singleton SAO. You can download the source here:
http://www.softitechture.com/di....
> >
> > Below is a summary and links to other articles but the conclusion is
that in order to implement a true Singleton object you must return a
Singleton SAO to the client, method #2. The only way to do so is to create
an SAO on the server using the Activator class and to return an ObjRef to
the client by Marshaling the SAO reference yourself.
> >
> > I think your assumption that there is no difference between an SAO and
CAO is not correct. There are fundamental differences between these two
types of remote objects and the context of how you use an object alone does
not determine whether it is an SAO or CAO. How you activate an object seem
to determine this classification and most importantly any MBR object
returned to a client that is created by another remote object (factory
pattern) that is created with the New
> statement will be classified as a CAO.
> >
> > The key fundamental difference between an SAO and CAO is their lifetime
management with leases. SAO lifetimes are controlled by the server, whereas
CAO lifetimes are controlled by the client. If you attempt to use a CAO as
a singleton that services all clients it's lifetime will be controlled by
the first client that creates it. Even if you give this CAO a lifetime
lease, it is not the same as a lifetime lease on an SAO. As soon as the
reference from the first
> client goes out of scope or is set to nothing your CAO singleton will be
recycled on the server once it's lease expires. Below are some references to
an MSDN article and the .NET documentation that discusses this in more
depth.
> >
> > I have attached a ZIP file to this message that is a Visual Studio
solution based on the code you provided below that demonstrates this
behavior. Below is also the output from an execution of this program.
> >
> >
> > Client Activation
> >
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconclientacti...
> >
> > Here's an excerpt:
> >
> > The client might even request an indefinite default lifetime,
effectively preventing the remote object from ever being recycled until the
server application domain is torn down. The difference between this and a
server-activated indefinite lifetime is that an indefinite server-activated
object will serve all client requests for that type, whereas the
client-activated instances serve only the client and the reference that was
responsible for their creation.
> >
> > Managing the Lifetime of Remote .NET Objects with Leasing and
Sponsorship by Juval Lowy
> > http://msdn.microsoft.com/msdnmag/issues/03/12/LeaseManager/de...
> >
> > Here's an excerpt:
> >
> > The case of the client-activated object is the one affected most by the
leasing mechanism. When using a client-activated model, every client that
creates a new object gets a dedicated server object. That object's lifetime
is governed by a lease, and the object will be disconnected from the clients
once its lease has expired. The only safe way to manage client-activated
objects is to use sponsors. All other options, such as global lease
properties or configuring
> individual objects' leases, are speculative at best. Ultimately, only the
client knows when it no longer needs the object.
> >
> > Console output from running attached test:
> >
> >
****************************************************************************
**********************************
> > Remote Client #1
> >
> > Note the URL & GUID of the CAO and the returned value from GetIntData
from both the CAO
> > and SAO MySharedObjects.
> >
****************************************************************************
**********************************
> > Configuring Remoting
> > 8/1/2004 8:33:22 AM
> > - ISAOGetter type URL: Type = SAO |
http://localhost:8085/ObjectPublisher
> > 8/1/2004 8:33:23 AM
> > - myTempBO type URL: Type = CAO |
http://192.0.2.2:8085/83f08688...
> > _9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
> > - Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
> > - GetIntData = 1 <-------------------
> > 8/1/2004 8:33:23 AM
> > - myTempBO type URL: Type = CAO |
http://192.0.2.2:8085/83f08688...
> > _9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
> > - Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
> > - GetIntData = 2 <-------------------
> > 8/1/2004 8:33:23 AM
> > - myTempBO2 type URL: Type = SAO |
http://localhost:8085/MySharedObject
> > - Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
> > - GetIntData = 1 <-------------------
> > 8/1/2004 8:33:23 AM
> > - myTempBO2 type URL: Type = SAO |
http://localhost:8085/MySharedObject
> > - Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
> > - GetIntData = 2 <-------------------
> > CAO reference set to Nothing.
> >
> >
****************************************************************************
**********************************
> > Remote Client #2 (launched 7 seconds after #1)
> >
> > Note the URL & GUID of the CAO are the same as for #1 and the returned
value from GetIntData
> > has continued where #1 left off for both the CAO and SAO.
> >
****************************************************************************
**********************************
> > Configuring Remoting
> > 8/1/2004 8:33:30 AM
> > - ISAOGetter type URL: Type = SAO |
http://localhost:8085/ObjectPublisher
> > 8/1/2004 8:33:30 AM
> > - myTempBO type URL: Type = CAO |
http://192.0.2.2:8085/83f08688...
> > _9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
> > - Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
> > - GetIntData = 3 <-------------------
> > 8/1/2004 8:33:30 AM
> > - myTempBO type URL: Type = CAO |
http://192.0.2.2:8085/83f08688...
> > _9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
> > - Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
> > - GetIntData = 4 <-------------------
> > 8/1/2004 8:33:30 AM
> > - myTempBO2 type URL: Type = SAO |
http://localhost:8085/MySharedObject
> > - Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
> > - GetIntData = 3 <-------------------
> > 8/1/2004 8:33:30 AM
> > - myTempBO2 type URL: Type = SAO |
http://localhost:8085/MySharedObject
> > - Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
> > - GetIntData = 4 <-------------------
> > CAO reference set to Nothing.
> >
> >
****************************************************************************
**********************************
> > Remote Client #3 (launched 7 MINUTES after #2)
> >
> > Note the URL & GUID of the CAO are NOT the same as for #1 and #2. This
is a
> > totally DIFFERENT object. This CANNOT be a Singleton by definition.
> > Note that the returned value from GetIntData has NOT been continued
where #2 left off
> > for the CAO, but has restarted at 1.
> > Note that the returned value from the GetIntData for the SAO
MySharedObject CONTINUES
> > to increment where #2 left off. This is THE SAME object answering
client requests
> > and is a Singleton by definition.
> >
****************************************************************************
**********************************
> >
> > Configuring Remoting
> > 8/1/2004 8:40:00 AM
> > - ISAOGetter type URL: Type = SAO |
http://localhost:8085/ObjectPublisher
> > 8/1/2004 8:40:00 AM
> > - myTempBO type URL: Type = CAO |
http://192.0.2.2:8085/83f08688...
> > _9d65_2e74985d3d3d/tShr4Faa2r2UEPsUfu8eEuAo_2.rem
> > - Guid: 40f316da-9c95-4daf-b14a-1776f7e0b476
> > - GetIntData = 1 <-------------------
> > 8/1/2004 8:40:00 AM
> > - myTempBO type URL: Type = CAO |
http://192.0.2.2:8085/83f08688...
> > _9d65_2e74985d3d3d/tShr4Faa2r2UEPsUfu8eEuAo_2.rem
> > - Guid: 40f316da-9c95-4daf-b14a-1776f7e0b476
> > - GetIntData = 2 <-------------------
> > 8/1/2004 8:40:00 AM
> > - myTempBO2 type URL: Type = SAO |
http://localhost:8085/MySharedObject
> > - Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
> > - GetIntData = 5 <-------------------
> > 8/1/2004 8:40:00 AM
> > - myTempBO2 type URL: Type = SAO |
http://localhost:8085/MySharedObject
> > - Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
> > - GetIntData = 6 <-------------------
> > CAO reference set to Nothing.
> >
> >
> > Thanks,
> >
> > Sam
> >




Sam Santiago

8/2/2004 9:14:00 PM

0

Thanks, Ken. I just notice that the lease on the factory object was not being set to a lifetime lease earlier and reposted. What type of object do you end up with on the client if you have a static instance that you return with RemotingService.Marshal? I started experimenting with this because I wanted to create a factory object that returned SAOs to the client. One reason I can think of to have the server activate an SAO and return it to the client is to simplify (or hide) the configuration from the client perspective. The client would only need to know about the factory object. The remaining SAOs will be configured on the server and activated and returned to the client without the client having to configure well known objects.

Thanks,

Sam

--
_______________________________
Sam Santiago
ssantiago@n0spam-SoftiTechture.com
http://www.SoftiTe...
_______________________________
"Ken Kolda" <ken.kolda@elliemae-nospamplease.com> wrote in message news:upccXWLeEHA.3132@TK2MSFTNGP11.phx.gbl...
Sam --

You can create a singleton SAO without going through the process you show in your code example #2. In that example, you're having the server register a well-known singleton type, but instead of having the client retrieve that object directly, you make a TCP connection from the server to itself to get the singleton (which is instantiated by the remoting framework) and then return that object to the client. That's not the best way to do this.

Generally, if you need a singleton, there are two main ways of accomplishing this, depending on your needs:

1) Register the well-known type and allow the remoting framework to instantiate and hold the reference to it. Do this if you do not need to use the object within the server-side code. Also, this method has the benefit in that the remoting framework will re-instantiate the singleton if its lease expires (but, in that case, it's really not a singleton in the way most people think about it).

2) Write the code in your server to create an object instance, store it in a static class variable somewhere and then call RemotingService.Marshal(). You now have effectively a singleton which you can return to multiple clients without a problem and access within the server code itself.

I can't think of any case where you would need to have the server use the Activator to get a singleton from itself only to return it to the client.

I think your example code has confused the issue a bit because your ObjectPublisher object, which you have made a singleton, doesn't override InitializeLifetimeServices(). Thus, it expired before your third test, which is why you get a different CAO for your third test run than you did for the first two. It has nothing to do with objects being SAO or CAO -- it's simply that your singleton was disconnected because it timed out.

Ken



"Sam Santiago" <ssantiago@n0spam-SoftiTechture.com> wrote in message news:%23ms6$x%23dEHA.720@TK2MSFTNGP11.phx.gbl...
Sunny,

Thanks for your reply. Your postings always get me thinking. Since there was nothing on TV last night I figured I would try your approach ;-). I created an example that uses both approaches: 1) A Singleton SAO factory that returns an MBR object and 2) A Singleton SAO factory that returns a ObjRef to another Singleton SAO. You can download the source here: http://www.softitechture.com/di....

Below is a summary and links to other articles but the conclusion is that in order to implement a true Singleton object you must return a Singleton SAO to the client, method #2. The only way to do so is to create an SAO on the server using the Activator class and to return an ObjRef to the client by Marshaling the SAO reference yourself.

I think your assumption that there is no difference between an SAO and CAO is not correct. There are fundamental differences between these two types of remote objects and the context of how you use an object alone does not determine whether it is an SAO or CAO. How you activate an object seem to determine this classification and most importantly any MBR object returned to a client that is created by another remote object (factory pattern) that is created with the New statement will be classified as a CAO.

The key fundamental difference between an SAO and CAO is their lifetime management with leases. SAO lifetimes are controlled by the server, whereas CAO lifetimes are controlled by the client. If you attempt to use a CAO as a singleton that services all clients it's lifetime will be controlled by the first client that creates it. Even if you give this CAO a lifetime lease, it is not the same as a lifetime lease on an SAO. As soon as the reference from the first client goes out of scope or is set to nothing your CAO singleton will be recycled on the server once it's lease expires. Below are some references to an MSDN article and the .NET documentation that discusses this in more depth.

I have attached a ZIP file to this message that is a Visual Studio solution based on the code you provided below that demonstrates this behavior. Below is also the output from an execution of this program.


Client Activation
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconclientacti...

Here's an excerpt:

The client might even request an indefinite default lifetime, effectively preventing the remote object from ever being recycled until the server application domain is torn down. The difference between this and a server-activated indefinite lifetime is that an indefinite server-activated object will serve all client requests for that type, whereas the client-activated instances serve only the client and the reference that was responsible for their creation.

Managing the Lifetime of Remote .NET Objects with Leasing and Sponsorship by Juval Lowy
http://msdn.microsoft.com/msdnmag/issues/03/12/LeaseManager/de...

Here's an excerpt:

The case of the client-activated object is the one affected most by the leasing mechanism. When using a client-activated model, every client that creates a new object gets a dedicated server object. That object's lifetime is governed by a lease, and the object will be disconnected from the clients once its lease has expired. The only safe way to manage client-activated objects is to use sponsors. All other options, such as global lease properties or configuring individual objects' leases, are speculative at best. Ultimately, only the client knows when it no longer needs the object.

Console output from running attached test:

**************************************************************************************************************
Remote Client #1

Note the URL & GUID of the CAO and the returned value from GetIntData from both the CAO
and SAO MySharedObjects.
**************************************************************************************************************
Configuring Remoting
8/1/2004 8:33:22 AM
- ISAOGetter type URL: Type = SAO | http://localhost:8085/ObjectPublisher
8/1/2004 8:33:23 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
- Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
- GetIntData = 1 <-------------------
8/1/2004 8:33:23 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
- Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
- GetIntData = 2 <-------------------
8/1/2004 8:33:23 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 1 <-------------------
8/1/2004 8:33:23 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 2 <-------------------
CAO reference set to Nothing.

**************************************************************************************************************
Remote Client #2 (launched 7 seconds after #1)

Note the URL & GUID of the CAO are the same as for #1 and the returned value from GetIntData
has continued where #1 left off for both the CAO and SAO.
**************************************************************************************************************
Configuring Remoting
8/1/2004 8:33:30 AM
- ISAOGetter type URL: Type = SAO | http://localhost:8085/ObjectPublisher
8/1/2004 8:33:30 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
- Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
- GetIntData = 3 <-------------------
8/1/2004 8:33:30 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/zDt2ajj8J4t1pfg7TRmpHm_A_1.rem
- Guid: 2edddb26-f812-4942-bbff-e65e99c0292e
- GetIntData = 4 <-------------------
8/1/2004 8:33:30 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 3 <-------------------
8/1/2004 8:33:30 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 4 <-------------------
CAO reference set to Nothing.

**************************************************************************************************************
Remote Client #3 (launched 7 MINUTES after #2)

Note the URL & GUID of the CAO are NOT the same as for #1 and #2. This is a
totally DIFFERENT object. This CANNOT be a Singleton by definition.
Note that the returned value from GetIntData has NOT been continued where #2 left off
for the CAO, but has restarted at 1.
Note that the returned value from the GetIntData for the SAO MySharedObject CONTINUES
to increment where #2 left off. This is THE SAME object answering client requests
and is a Singleton by definition.
**************************************************************************************************************

Configuring Remoting
8/1/2004 8:40:00 AM
- ISAOGetter type URL: Type = SAO | http://localhost:8085/ObjectPublisher
8/1/2004 8:40:00 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/tShr4Faa2r2UEPsUfu8eEuAo_2.rem
- Guid: 40f316da-9c95-4daf-b14a-1776f7e0b476
- GetIntData = 1 <-------------------
8/1/2004 8:40:00 AM
- myTempBO type URL: Type = CAO | http://192.0.2.2:8085/83f08688...
_9d65_2e74985d3d3d/tShr4Faa2r2UEPsUfu8eEuAo_2.rem
- Guid: 40f316da-9c95-4daf-b14a-1776f7e0b476
- GetIntData = 2 <-------------------
8/1/2004 8:40:00 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 5 <-------------------
8/1/2004 8:40:00 AM
- myTempBO2 type URL: Type = SAO | http://localhost:8085/MySharedObject
- Guid: 1f6bf760-57ee-4379-8006-62adf6cc200c
- GetIntData = 6 <-------------------
CAO reference set to Nothing.


Thanks,

Sam
--
_______________________________
Sam Santiago
ssantiago@n0spam-SoftiTechture.com
http://www.SoftiTe...
_______________________________