Re: Session's persistance?!?!?
Re: Session's persistance?!?!?
- Subject: Re: Session's persistance?!?!?
- From: Chuck Hill <email@hidden>
- Date: Wed, 02 Apr 2003 18:33:33 -0800
- Organization: Global Village Consulting, Inc.
Posted a long time ago in a list far, far away...
Perhaps you will find his advice useful. Or terrifying.
Chuck
Date: Wed, 05 Dec 2001 02:47:38 +0000
From: Mark Gowdy
One small piece of advice..... 'Run away'
We have successfully written two apps that run in this fashion. and I can
honestly say to avoid it if possible. I presume your load balancer will send
requests to a random machine / random instance. This means your apps must not
return an instance number for each request.
The easiest way to do with would be to code your app with directActions and NO
session information (for us that was not an option)
1: In your session constructor you must put setDistributionEnabled(false); //
Stops the instance number being added.
2: In your application constructor you must put
setPageCacheSize(0); // This stops WOComponents being archived
(I was advised to do this by the great Dave Neumann, so who's to argue)
3: Use session.defaultEditingContext() for most things if possible.. This
automatically gets archived with the session. That also means that if create any
new EO's you should insert them into this context right away, so it can archive
them for you.
4: WOComponents can store stuff in session using:
session().objectForKey("ComponentName_varName");
session().setObjectForKey(obj, "ComponentName_varName");
You cannot store variables in the WOComponent as they will not be there by the
next click
5: This is the nightmare bit.. (EOs) If you have fetched something into an
EditingContext, it goes up the chain (ObjectStore stuff) and gets stored in
Application. I think this is called a 'snapshot' of the data. The words 'object
graph' also have some relevance (but it's 2:00am and my brain is not working) If
you have a reference to an EO in your session ec, but the next application has
never seen it before then it gets confused.. The other problem is that one app
might have a different snapshot to another (brain begins to melt)
This can be resolved by implementing the following..
You can store EO's via an accessor in session:
public void setEOGenericRecordForKey(EOGenericRecord a_eo, String a_key){
if (a_eo!=null)
setObjectForKey(a_eo.editingContext().globalIDForObject(a_eo), a_key);
else removeObjectForKey(a_key);
}
I would also check to make sure a_eo.editingContext() is not null (just incase)
The above stores the object as a globalID (which is basically the name of the
EO, and it's primary keys)
To get this objec back safely, you call something like this: where ec() is
probably your session.defaultEditingContext()
public EOGenericRecord eoGenericObjectForKey(String a_key){
return
(EOGenericRecord)ec().faultForGlobalID((EOGlobalID)objectForKey(a_key), ec());
}
I would do the usual null checks too..
The reason this works is the rather handy faultForGlobalID.. If the object has
already in the apps snapshot, then it returns a local instance in ec() If the
object is not in the snapshot, it faults it (which causes it to be
fetched from the database) Check out EOUtilities.localInstanceOfObject(ec, eo);
EOUtilities has other useful stuff, (it is our friend)
6: The session store: Go to WOInfoCenter and search for Distributed Session
Store and persistent session store. Most of the good stuff is in
WOExamples.framework (apparently)
We did it like this:
Extend WOSessionStore,
public class MySessionStore extends WOSessionStore {
protected EOEditingContext ec = null;
public MySessionStore(EOEditingContext a_ec){
super();
ec = a_ec; // if you are going to store session data in a database, you
probably need an ec..
}
You need to write:
public void saveSessionForContext(WOContext a_context)
// Useful archiving code:
WOSession aSession = a_context.session();
String aSessionID = aSession.sessionID();
NSMutableData sessionArchiveData = new NSMutableData();
NSArchiver archive = new NSArchiver(sessionArchiveData);
archive.encodeObject(aSession);
You might need to aSession.terminate() or figure out how to use checkIn / Out
properly..
public WOSession restoreSessionWithID(String a_sid, WORequest a_request)
// Useful unarchiving code:
NSData sessionArchiveData = // get the data object using a_sid as a key //
NSUnarchiver unarchiver = new NSUnarchiver(sessionArchiveData);
WOSession aSession = (WOSession)unarchiver.decodeObject;
// or aSession = (WOSession)NSUnarchiver.unarchiveObjectWithData(unarchiver);
Now in Application you must:
WOSessionStore newSessionStore = new
MySessionStore(someEditingContextFromApp);
this.setSessionStore(newSessionStore);
You may also have to do this (to make sure that the apps do not hand out the
same id for new instances)
public WOSession createSessionForRequest(WORequest a_request){
WOSession newSess = null;
String sessID = a_request.sessionID();
if (sessID != null) {
newSess = this.sessionStore().restoreSessionWithID(sessID, a_requst);
}
else {
make a new session and make sure it's id is unique
}
return newSess;
}
That is all I can remember for now..
Why not do it the easy way, and use WebObjects own loadbalancing methods.. Buy
a cheap linux box with apache and compile the WebObjects adaptor.. Set up a few
WO App servers.. Configure it (using monitor) to load balance between them..
EASY !! Each request gets routed back to the insance it came from.. The
advantages are simple:
1. No overhead due to storing the session in the database.
2. You code is less likely to break, due to accidently archiving something
incorrectly
3. It takes 1 third the time to construct an app from scratch.
Disadvantage:
If a machine falls over, all the users on that machine loose their session..
(but you code is more likely to explode if you do it the other way..)
The other option is to get the load balancer to maintain a connection to one
server for their session (somehow)
DONT DO IT !
Regards,
Mark
Disclaimer: Don't know, don't care.. The code above is there ONLY as a pointer,
you must understand what it is doing and put in better validation and the like..
Good luck..
Stefano Lesandrini wrote:
I will wondering if somebody could tell me it's possible
to have persistent sessions!
In other words, I would like a session, stopped due to a
crash of the wo thread (or by a failure of the whole
application server) could be acquired (and mainteined)
by another application server. I'm referring to a three tiers
architecture (hw & sw) :
--> client: browser/java
--> RAIC of wo servers (apache+wo)
--> RDBMS server
The goal is to reach the highest achievable RAS.
Thank You very much for any suggestion.
/Steve
_______________________________________________
webobjects-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/webobjects-dev
Do not post admin requests to the list. They will be ignored.
--
Chuck Hill email@hidden
Global Village Consulting Inc. http://www.global-village.net
_______________________________________________
webobjects-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/webobjects-dev
Do not post admin requests to the list. They will be ignored.