How I can store an instance object foreach user session?
I have a class to modeling a complex algorithm. This algorithm is designed to run step-by-step. I need to instantiate objects of this class for each user. Each user should be able to advance step by step their instance.
You can only store the objects in the Cache. The objects must be serializable for this. In the session you can store a key (which must be a String) to the Cache. Make sure that your code still works if the object was removed from the cache (same as a session-timeout). It's explained in http://www.playframework.org/documentation/1.0.3/cache.
Hope that solve your problem.
To store values in the session:
//first get the user's session
//if your class extends play.mvc.Controller you can access directly to the session object
Session session = Scope.Session.current();
//to store values into the session
session.put("name", object);
If you want to invalidate / clear the session object
session.clear()
from play documentation: http://www.playframework.org/documentation/1.1.1/cache
Play has a cache library and will use Memcached when used in a distributed environment.
If you don’t configure Memcached, Play will use a standalone cache that stores data in the JVM heap. Caching data in the JVM application breaks the “share nothing” assumption made by Play: you can’t run your application on several servers, and expect the application to behave consistently. Each application instance will have a different copy of the data.
You can put any object in the cache, as in the following example (in this example from the doc http://www.playframework.org/documentation/1.1.1/controllers#session, you use session.getId() to save messages for each user)
public static void index() {
List messages = Cache.get(session.getId() + "-messages", List.class);
if(messages == null) {
// Cache miss
messages = Message.findByUser(session.get("user"));
Cache.set(session.getId() + "-messages", messages, "30mn");
}
render(messages);
}
Because it's a cache, and not a session, you have to take into account that the data might no longer be available, and have some mean to retrieve it once again from somehere (the Message model, in this case)
Anyway, if you have enough memory and it involves a short interaction with the user the data should be there, and in case it's not you can redirect the user to the beginning of the wizard (you are talking about some kind of wizard page, right?)
Have in mind that play, with it's stateless share-nothing approach, really have no sessión at all, underneath it just handles it through cookies, that's why it can only accept strings of limited size
Here's how you can save "objects" in a session. Basically, you serialize/deserialize objects to JSON and store it in the cookie.
https://stackoverflow.com/a/12032315/82976
Related
I'm implementing a PAS plugin that handles authentications against mailservers. Actually only DBMail is implemented.
I realized, that the enumerateUsers function from the PAS plugin is called numerous times per request and requires my plugin to open/close an SQL connections for every (subsequent) request. Of course, this is very expensive.
The connections itself are handled in a plone tool, which is able to handle multiple different mailservers and delegeates the enumerateUsers call to wrapper objects that represent registered servers.
My question is now, what sort of cache (OOBTree, Session?) I should use to provide a temporary local storage for repeating enumerations and avoid subsequent SQL connections?
Another idea was, to hook into the user creation process that takes place on the first login, an external user issues and completely "localize" the users.
Third idea was, to store the needed data in the specific member, if possible.
What would be best practice here?
I'd cache the query results, indeed. You need to make a decision on how long to cache the results, and if stored long term, how to invalidate that cache or check for changes.
There are no best practices for these decisions, as they depend entirely on the type of data stored and the APIs of the backends. If they support some kind of freshness query, for example, then you store everything forever and poll the backend to see if the cache needs updating.
You can start with a simple request cache; query once per request, store it on the request object. Your cache will automatically be invalidated at the end of the request as the request object is cleaned up, the next request will be a clean slate.
If your backend users rarely change, you can cache information for longer, in a local cache. I'd use a volatile attribute on the plugin. Any attribute starting with _v_ is ignored by the persistence machinery. Thus, anything stored in a _v_ volatile attribute is both thread-local and only exists for the lifetime of the process, a restart of the server clears these automatically.
At the very least you should use an _v_ volatile attribute to store your backend SQL connections. That way they can stay open between requests, and can be re-used. Something like the following method would do nicely:
def _connection(self):
# Return a backend connection
if getattr(self, '_v_connection', None) is None:
# Create connection here
self._v_connection = yourdatabaseconnection
return self._v_connection
You could also use a persistent attribute on your plugin to store your cache. This cache would be committed to the ZODB and persist across restarts. You then really need to work out how to invalidate the contents; store timestamps and evict data when to old, etc.
Your cache datastructure depends entirely on your application needs. If you don't persist information, a dictionary (username -> information) could be more than enough. Persisted caches could benefit from using a OOBTree instead of a dictionary as they reduce chances of conflicts between different threads and are more efficient when it comes to large sets of data.
Whatever you do, you do not need to use a Session. Sessions are prone to conflicts, do not scale well, and are in any case not the place to store a cache of this kind.
I have been using the session factory (Singleton Bean injected into the DAO objects) in my Spring/Hibernate application, I am using the service layers architecture, and I have the following issue:
Anytime I get a domain object from the database, it uses a new session provided by the hibernate session factory. In the case of requesting several times the same row, this leads to having multiple instances of that same domain object. (If using a single session, it would return multiple objects pointing to the same reference) Thus, any changes made to one of those domain object is not taken into account by the other domain objects representing this same row.
I am developing a SWING application with multiple views and I get the same DB row from different locations (And queries), and I thus need to obtain domain objects pointing to the same instance.
My question is then, Is it a way to make this happen using the SessionFactory? If not, is it a good practice to use a single session for my whole application? In that case, how and where should I declare this session? (Should it be a bean injected into the DAO objects just like the sessionFactory?)
Thank you in advance for your help
Hibernate session (I will call it h-session) in Spring usually bound to thread (see JavaDoc for HibernateTransactionManager), so h-session acquired once per thread.
First level cache (h-session cache - always turned on) used to retrieve same object if you call "get" or "load" several times on one h-session. But this cache doesn't work for queries.
Also, you shouldn't forget about problems related to transaction isolation. In most applications "Read committed" isolation level is used. And this isolation level affected by phenomenon known as "non-repeatable reads". Basically, you could receive several versions of the same row in one transaction if you query for this row several times (because row could be updated between queries in another transaction).
So, you shouldn't query several times for same data in one h-session/transaction.
You're looking for the Open Session in View Pattern. Essentially, you want to bind a Session to your thread on application startup and use the same Session throughout the lifetime of the application. You can do this by creating a singleton util class which keeps a session like so (note that the example I have uses an EntityManager instead of a Session, but your code will be essentially the same):
private static EntityManager entityManager;
public static synchronized void setupEntityManager() {
if (entityManager == null) {
entityManager = entityManagerFactory.createEntityManager();
}
if (!TransactionSynchronizationManager.hasResource(entityManagerFactory)) {
TransactionSynchronizationManager.bindResource(entityManagerFactory, new EntityManagerHolder(entityManager));
}
}
public static synchronized void tearDownEntityManager() {
if (entityManager != null) {
if (entityManager.isOpen()) {
entityManager.close();
}
if (TransactionSynchronizationManager.hasResource(entityManagerFactory)) {
TransactionSynchronizationManager.unbindResource(entityManagerFactory);
}
if (entityManagerFactory.isOpen()) {
entityManagerFactory.close();
}
}
}
Note that there are inherent risks associated with the Open Session in View pattern. For example, I noticed in the comments that you intend to use threading in your application. Sessions are not threadsafe. So you'll have to make sure you aren't trying to access the database in a threaded manner.*
You'll also have to be more aware of your fetching strategy for collections. With an open session and lazy loading there's always the chance that you'll put undue load on your database.
*I've used this approach in a NetBeans application before, which I know uses threading for certain tasks. We never had any problems with it, but you need to be aware of the risks, of which there are many.
Edit
Depending on your situation, it may also be possible to evict your domain objects from the Session and cache the detached objects for later use. This strategy would of require that your domain objects not be updated very often, otherwise your application would become unnecessarily complicated.
Since Wicket automatically manages session state by serializing the components in my page, I'm left wondering, at which level I should attach my state data. More specifically, it seems like a bug I'm having is caused by the WebApplication object being shared among sessions.
Is the application instance shared between sessions?
Should I always attach session data to the Page instance?
What happens if I reuse components with attached session state on multiple pages? Are those instances shared, i.e. if I set the state on the component on one page, is it carried over to another?
I'm guessing, the third bullet point depends on object identity. What does Wicket use to determine that, equals() (like, is it using a Map)?
The data I attached to the application object is state I would need in many pages, so I didn't attach it to the page objects. Is that the correct way to do it in Wicket?
Yes, that's the point of having an Application object. You can store and access application-wide data (usually config) through your Application subclass at any point.
No. There are cases when you need to share session data across multiple pages where storing it in a Session object is more adequate. (An example could be a user login, which definitely belongs to the session and may be used by any page.) Of course you can pass the data around between the pages but it's not a very good strategy. Where the cutoff point is will be your decision: if data is shared between two pages, you might want to pass it from one to the other, if there are 20 pages, you definitely won't want to.
You're not supposed to reuse component instances across different pages. Of course you'll reuse the class but you'll have to construct a new one on each page. This is exactly where storing data in the Session object might come handy.
To clarify: The number of pages sharing state is an indication of where to put the data, but what really matters is how tightly you want the items sharing data to be coupled:
If you pass data as parameters between pages, they will form a tightly coupled group. Depending on what the pages represent, this might be desirable. An example for this may be a wizard-like sequence of pages, with each page knowing what the pages before and after are.
But in the login example we see the opposite: the component populating the login name (probably some kind of login form) must not know about what other components are going to use it. So the logical solution is to store the login name in the session and let each component fetch it as and when they need it.
There are multiple ways to get hold of the current Session object. Check the documentation of the class to see how.
To summarize the information there: Wicket discourages type-unsafe session properties by not providing generic setProperty-like methods. Instead, you are supposed to extend Session, or for most projects, more adequately, WebSession and place typesafe properties in that class. You then override newSession on your application class.
My C# 3.5 application uses SQL Server 2008 R2, NHibernate and CastleProject ActiveRecord. The application imports emails to database along with their attachments. Saving of emails and attachments is performed by 50 emails in new session and transaction scope to make sure they are not stored in memory (there can be 100K of emails in some mailbox).
Initially emails are saved very quickly. However, closer to 20K emails performance degrades dramatically. Using dotTrace I got the following picture:
Obviously, when I save an attachment, NHibernate tries to see if it really should save it and probably compares with another attachments in the session. To do so, it compares them byte by byte what takes almost 500 seconds (for the snapshot on the picture) and 600M enumerator operations.
All this looks crazy, especially when I know for sure that SaveAndFlush indeed should save the attachment without any checks: I know for sure that it is new and should be saved.
However, I cannot figure out, how to instruct NHibernate to avoid this check (IsUpdateNecessary). Please advise.
P.S. I am not sure but it might appear that degradation of performance closer to 20K is not connected with having some older mails in memory: I noticed that in mailbox I am working with, larger emails are stored later than smaller so the problem may be only in attachments comparison.
Update:
Looks like I need something like StatelessSessionScope, but there is no documentation on it even at CastleProject site! If I do something like
using (TransactionScope txScope = new TransactionScope())
using (StatelessSessionScope scope = new StatelessSessionScope())
{
mail.Save();
}
it fails with exception that Save is not supported by stateless session. I am supposed to insert objects into session, but I do not have any Session (only SessionScope, which adds up to SessionScope only single OpenSession method which accepts strange paramenters).
May be I missed it in that long text, but are you using stateless session for importing data? Using that prevents a lot of checks and also bypasses first level cache, thus using minimal resources.
Looks like I've found an easy solution: for my class Attachment, causing biggest performance penalty, I overridden the following method:
protected override int[] FindDirty(
object id,
System.Collections.IDictionary previousState,
System.Collections.IDictionary currentState, NHibernate.Type.IType[] types)
{
return new int[0];
}
Thus, dirty check always consider it dirty and does not do that crazy per-byte comparison.
Throughout the application I need to access User object (Doctrine) several times per execution (I mean each time page is displayed) so on some, and instead of retrieving it from database every time, I thought it would be better to store it once and then reuse it.
Can I store it in sfContext?
Symfony discourages saving objects into the session, see here for example: http://www.symfony-project.org/gentle-introduction/1_4/en/06-Inside-the-Controller-Layer#chapter_06_sub_accessing_the_user_session
... But you can save user_ids and other bits that save on queries. It really depends on whether the things you need to do on all those pages require the entire user object. If yes, $this->getUser()->getGuardUser() is what you'll end up using everywhere.
If you're referring to the currently logged in user object, it should already automatically be loaded for you. At the point of authentication, the system loads the user record and it will remain there in the session.
In actions, you can retrieve the user object with:
$this->getUser()
In a view, it's already loaded into the variable:
$sf_user