I have an application that is authenticating against an external server in a filter. In that filter, I'm trying to set a couple of session attributes on the user by using Symfony's setAttribute() method:
$this->getContext()->getUser()->setAttribute( 'myAttribute', 'myValue' );
What I'm finding is that, if I dump $_SESSION immediately after setting the attribute. On the other hand, if I call getAttribute( 'myAttribute' ), I get back exactly what I put in.
All along, I've assumed that reading/writing to user attributes was synonymous with reading/writing to the session, but that seems to be an incorrect assumption. Is there a timing issue? I'm not getting any non-object errors, so it seems that the user is fully initialized.
Where is the disconnect here?
Thanks.
UPDATE
The reason this was happening is because I had some code in myUser::shutdown() that cleared out a bunch of stuff. Because myUser is loosely equivalent to $_SESSION (at least with respect to attributes), I assumed that the shutdown() method would be called at the end of each session. It's not. It seems to get called at the close of each request which is why my attributes never seemed to get set.
Now, though, I'm left wondering whether there's a session closing callback. Anyone know?
Depending on how you are doing your session handling the session storage class has two methods, sessionGC (called on garbage collection) and sessionDestroy.
You can create your own session class extending what ever one you are using currently, we use Doctrine/PDO. The default is sfSessionStorage.
To change what class you use edit factories.yml:
all:
storage:
class: mySuperNewSessionStorageClass
Related
We have a controller where we are trying to carry out search on a domain class. The actual search logic is handled in a service. This search involves use of SomeDomain.withCriteria, fetchMode set to SELECT and createAlias. The search comes back fine with the required results. Once we have the results we redirect to another action in the same controller which handles results. Returning from a controller flushes the session and this is where the controller throws the following exception:
object references an unsaved transient instance - save the transient
instance before flushing
Well it appears as somehow and somewhere in our code a domain object is created and is never saved. The error message is kind enough to show the type of the transient object but it does not inform where and when was it created. This remains a mystery that where this object is created from and I am now looking for ways to get hold of a reference to this object. So my question here is that how can I find all objects which are in a transient state?
I want the reference of this mystery unsaved object just because I want to call discard on it and see how things go on from there. I know that I don't need this object so if it is hanging around somewhere I want to discard it so that it does not end up in throwing exceptions. If someone can also figure out why and where that object gets created then that would be great.
We've had this problem too, and it can be an obnoxious bug to find. Presumably it's possible to find all transients by walking through Hibernate's internal structures, but I've never gone very far into it. Instead, we typically debug via flush() and binary search: flush the session more and more aggressively until it's obvious which operation introduced a transient to your object graph.
I have an after_initialize callback that I would like to happen whenever the model is created or instantiated directly, as opposed to loaded through an association in some other place. Something like this:
after_initialize :check_status, if: "instantiated_directly?"
such that MyModel.find(1) will trigger the check, but other_model.my_model will not.
The status is a state variable for a long process, which only needs to be verified before some long-running process starts. I want to prevent the user from loading the model if the process seems to be in progress. I'd like to still be able to acces attributes in that model for various other reasons elsewhere.
Preventing the read is probably not the best vector for ameliorating this issue, nor is a model that tries to reach out of its own scope to determine how to load a wise idea. I would instead recommend you simply add a validation to ensure the record can be modified without interfering with your background processes, a la…
validate :safe_to_edit?
def safe_to_edit?
some_state_variable
end
Your model also exposes a safe_to_edit? method here that allows your controller or another object to determine the best behavior independently of checking validations, such as if you had a client-side service polling to flag the user when it was safe to edit, or you wanted to delay response and try again in a few seconds in a background job, etc.
I was skimming some of the Grails documentation and found this bit about the read() method in Grails. If I'm understanding this correctly, you can pull a "read-only" version of an object from the database that will only be saved on an explicit save() call. It seems to me then, that you should use a read() call whenever you have an object that you don't expect to be changed.
But why wouldn't you just always use a read() call? Since the object will be changed to read/write permissions if you save() it anyway, wouldn't it be safer to just read in the object instead of getting it?
You're probably correct - it'd be equivalent in most cases. But Hibernate doesn't require that you call save() since it does dirty checking during a flush and since Grails uses an "Open Session in View" interceptor there will always be a flush at the end of each request. This surprises people who make changes in an instance retrieved by get() that were meant to only be temporary while rendering the view but then the changes get persisted anyway without a save() call. read() would make more sense in that scenario.
One performance optimization is to use http://grails.org/doc/latest/ref/Database%20Mapping/dynamicUpdate.html to only push changed fields to the database. The default is to push all fields whether they're changed or not since then there's no need to generate new SQL for each update. If you read() an instance Hibernate doesn't keep the original data so dynamic update wouldn't be possible since there would be no way to know which fields are dirty.
I have a simple web-site. Almost every action takes int toonId as an argument (toonId does not equate to the user: one user can own multiple toons).
At the moment I provide that value to every view from controller, and every link and submit button sends this value back to the controller.
This works. I am just looking for an easier way to accomplish this (AOP comes to mind).
I use cookies to persist "favorite/default toon", and this works fine (used with ActionAttribute, that takes toonId from cookie and passes is to the toonId argument, if toonId wasn't provided). But I want to support cookie-less sessions as well.
Question: What is an easy way to add ambient variable to the page, without passing it explicitly all over? Such that it would work with cookie-less browsers.
Is Viewstate a way to go (which isn't supposed to be in the MVC)?
Is server-side session a way to go?
This is exactly what session is meant for.
There is no page lifecycle in asp.net mvc, hence no viewstate.
I believe you can automatically pass query string parameters for use cookie-less browsers if you plug in your own implementation of IRouteHandler. I have not tried it though. I found an example of implementing IRouteHandler although it does not show how to implement the query string parameter functionality.
I'm not clear on what 'toonid' represents. If it's 'ambient per user session', then as womp stated, Session state would work well for this. However, if it's somethign that has a larger scope (e.g. a colleciton of toonids that are commonly accessed by all users) then teh Cache would be a better and more scalable strategy.
I am using the Redirect After Post pattern in my ASP.NET MVC application. I have
the following scenario:
User goes to /controller/index where he is asked to fill a form.
Form values are POSTed to /controller/calculate.
The Calculate action performs calculation based on input and instantiates a complex object containing the results of the operation. This object is stored in TempData and user is redirected to /controller/result.
/controller/result retrieves the result from TempData and renders them to the user.
The problem with this approach is that if the user hits F5 while viewing the results in /controller/result the page can no longer be rendered as TempData has been expired and the result object is no longer available.
This behavior is not desired by the users. One possible solution would be instead of redirecting after the POST, just rendering the results view. Now if the user hits F5 he gets a browser dialog asking if he wants to repost the form. This also was not desired.
One possible solution I thought of was to serialize the result object and passing it in the URL before redirecting but AFAIK there are some limitations in the length of a GET request and if the object gets pretty big I might hit this limitation (especially if base64 encoded).
Another possibility would be to use the Session object instead of TempData to persist the results. But before implementing this solution I would like to know if there's a better way of doing it.
UPDATE:
Further investigating the issue I found out that if I re-put the result object in TempData inside the /controller/result action it actually works:
public ActionResult Result()
{
var result = TempData["result"];
TempData["result"] = result;
return View(result);
}
But this feels kind of dirty. Could there be any side effects with this approach (such as switching to out-of-process session providers as currently I use InProc)?
Store it in the Session with some unique key and pass the key as part of the url. Then as long as the session is alive they can use the back/forward button to their heart's content and still have the URL respond properly. Alternatively, you could use the ASP cache, but I'd normally reserve that for objects that are shared among users. Of course, if you used the parameters to the calculation as the key and you found the result in the cache, you could simply re-use it.
I think redirect after post makes much more sense when the resulting Url is meaningfull.
In your case it would mean that all data required for the calculation is in the Url of /controller/result.
/controller/calculate would not do the calculation but /controller/result.
If you can get this done thinks get pretty easy: You hash the values required for the calculation and use it as the key for the cache. If the user refreshes he only hits the cache.
If you cant have a meaningfull url you could post to /controller/index. If the user hits F5 calculation would start again, but a cache with the hash as key would help again.
TempData is generally considered useful for passing messages back to the user not for storing working entities (a user refresh will nuke the contents of TempData).
I don't know of more appropriate place than the session to store this kind of information. I think the general idea is keep session as small as possible though. Personally I usually write some wrappers to add and remove specific objects to session. Cleaning them up manually where possible.
Alternatively you can store in a database in which you purge stale items on a regular basis.
I might adopt a similar idea to a lot of banks on their online banking sites by using one-time keys to verify all POSTs. You can integrate it into a html helper for forms and into your service layer (for example) for verification.
Let's say that you only want to post any instance of a form once. Add a guid to the form. If the form does not post back and the data is committed then you want to invalidate the guid and redirect to the GET action. If say the form was not valid, when the page posts back you need a new (valid) guid there in the form waiting for the next post attempt.
GUIDs are generated as required and added to a table in your DB. As they are invalidated (by POSTS, whether successful or not) they are flagged in the table. You may want to trim the table at 100 rows.. or 1000, depending on how heavy your app will be and how many rendered but not yet posted forms you may have at any one time.
I haven't really fine tuned this design but i think it might work. It wont be as smelly as the TempData and you can still adhere to the PRG pattern.
Remember, with PRG you dont want to send the new data to the GET action in a temp variable of some sort. You want to query it back from the data store, where it's now committed to.
As Michael stated, TempData has a single purpose -> store an object for one trip only and only one trip. As I understand it, TempData is essentially using the same Session object as you might use but it will automatically remove the object from the session on the next trip.
Stick with Session imho rather than push back in to TempData.