I would like to store some object in the session. I know, that there are at least two ways to do it:
in the service define scope = "session", and then define property def myObject
use httpSession: session['myObject'] = myObject
What is more useful approach to store object in the session?
Update: What the benefites of using of every method? Can I invalidate session if I would use scope = 'session'?
Update 2 If I would like to use object of another class in the service with session = "session", I have an exception about bean with scope session.
Based on the information you have provided storing an object in the session itself would be the simpler approach. Just be sure whatever you do store there is as small as possible.
session['someKey'] = new MyObject()
The documentation has some more information about using the session.
Unless you have a requirement for using an actual instance of an object you may find it easier to simply store a map in the session instead.
session['someKey'] = [mapKey1: 'value', meaningKey: 42]
...
println session['someKey'].meaningKey // 42
Related
In Grails If I have a Command object such as
class MyCommand {
MyObject object;
}
If the incoming request data has an ID value for object then when the Grails data binding occurs my command object is actually populated with a instance of the object from the database.
I don't want this. I just want a new instance of MyObject populated with the incoming request data. I don't care of if there is already an instance in the DB with the same ID, I will handle that on my own.
How can disable this DB type data-binding at either a global level or preferably some way (annotation?) at the property level.
The only other alternative I can think of is when I send the request data I will have the ID values and object properties separate and join them later. I don't want to do that if it can be avoided.
You can have endpoints called differently using ROLES. For example:
def show(){
Person user = new Person()
if(isSuperuser() && params?.id){
user = Person.get(params.id.toLong())
}else{
user = Person.get(springSecurityService.principal.id)
}
...
}
This sets it up so only admin's can supply the ID otherwise it uses the principal to get the logged in user.
In our Rails application we want to store an instance of a class in a session. This is because we want to set the class with some parameters when the user first logs into the application and then re-use this class by pulling it back out of the same session. When their session expires or they log out, this instance of the class is destroyed.
We're doing this to avoid using a Singleton class because that would live at Application-level and be available on different processes and stick around longer than the user's session, and have security implications due to it also being available to other users who haven't created a session yet.
So this is how it works:
session[:example_class] = ExampleClass.new(field_one: 'field_one', field_two: 'field_two')
This works fine!
However if I then do this:
current_instance = session[:example_class]
current_instance.do_something
session[:example_class] = current_instance
Whereby I am calling a method on this instance or whatever and then want to push that updated instance back into the session again so it's stored somewhere... we get this error:
TypeError in HomeController#index
ExampleClass can't be referred to from /Users/cameron/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/bundler/gems/activerecord-session_store-376ed7f7aba1/lib/active_record/session_store.rb:64:in `dump'
And that method that is failing in session_store.rb is:
def self.dump(value)
::Base64.encode64(Marshal.dump(value))
end
And the value it's trying to store is:
{"_csrf_token"=>"nrw4m2ZAECwD3TiaPZoaSt4vL1DvjO+COnBpUQGwpXs=", "example_class"=>#<ExampleClass:0x00007f7fa7b1b998 #field_one="field_one", #field_two="field_two">}
Why can I write the class in the first time around... but afterwards it throws that error?
And how we get around this?
I can't answer you fully why it fails, but I wouln't rely on implicit serialization of Ruby objects.
I would find a way to serialize the object of ExampleClass explicitly (similar to as_json) - convert to a hash, then store the hash in the session. When you need this object again, initialize ExampleClass instance with the params from session and then serialize it back to session.
I don't have an answer for why the above error happened but it turns out if you're storing an instance of a class inside the session, you're in fact storing the instance and not just the current state of the class as I originally thought it was doing.
This basically means that whenever you interact with that class and change it's attributes the session is still reading from the same instance you are interacting with and therefore has the same information without having to write back into the session.
In short you have the behaviour of a Singleton class but using a session to maintain state.
In HttpContext(Or some thing like this) I need to add a temperory variable from a controller which need to available through out the request processing(Request wise variable). But the HttpContext.Current.Request is readonly. If i'm adding in Items its not getting outside. How can i achieve this
Thanks & Regards
Binesh Nambiar C
You are looking for HttpContext.Items, which is a dictionary that can be used to store items for the duration of the current request. It goes out of scope at the end of the request.
// Set
HttpContext.Items["Customer"] = customer;
// Get
var customer = HttpContext.Items["Customer"];
I have array of objects. I can't store it in DB for performance reason. I tried store array in Global ($var) and Class (##var) variables (in controller), but it was the same array for all users. It should be unique for each user session and in each session it should be able to be modified quickly.
I understand that the session[] - is not the best solution. What is the best way?
I'm doing something like this $lines_rules << Processing::rule_creator(...) in every time, when run action in controller.
$lines_rules - it is my array of objects.
Why DB is not right for store $lines_rules? In $lines_rules I store objects with lambda function. When user press button I need call every lambda function with user input and keep result. Then I load new objects into $lines_rules. Thus every request change $lines_rules. I think work with memory is the better way for perfomance.
UPDATE
I use $global_hash [ session[:session_id] ] and this technique for resource saving:
def dead_sessions_killer
ActiveRecord::SessionStore::Session.where(["updated_at < ?", 30.minutes.ago]).each do |session|
$global_hash.delete_if {|key, value| key == session.session_id }
session.delete
end
end
Use a global, but a global hash, keyed by the user's session id.
Store whatever you want in there, although with proper caching, hard to say if this is a great idea.
You could declare the array as a class variable (only 1 # sign), and provide an accessor method.
That is:
class Foo
#some_array
def some_array
#some_array
end
end
From other classes, this lets you call foo_instance.some_array, which keeps the array specific to the user, but allows public access from any class.
You could store the user session in memory with memcache. That would be convenient and fast.
http://awesomerails.wordpress.com/2011/08/23/rails-3-memcached-session-store/
if I put a custom class in session, then in an action method I get an instance of that class from session, and populate some fields, I noticed that when a different controller gets that class from session, those fields are populated. Even though after the first call didn't save the updated class back in session.
is this typical behavior for session objects?
I thought I had to use keyword 'static' on the class in session for this to happen
thanks
As your class is a reference type this is the normal behavior. Here's what's happening in memory:
You instantiate an object and put it in session
var someObj = new SomeObject();
Session["someObj"] = someObj;
At this stage a new object is created on the heap and Session["someObj"] is pointing to this object.
You retrieve the object from session in controller A and modify some property but you do not call Save:
var someObj = (SomeObject)Session["someObj"];
someObj.SomeProp = "new value";
Now someObj is pointing to this same object you created earlier on the heap. As someObj is only a reference you are actually modifying the original object in memory.
You retrieve the object from session in Controller B:
var someObj = (SomeObject)Session["someObj"];
Now someObj points to the same memory location which has been modified.
is this typical behavior for session objects?
Well yes, but, it is typical of .NET objects in general. You took a reference, so you were changing the original object still pointed to by the session.
Since your session is in memory this is the expected behavior. If you store the session in an external store then you have to save the objects back to the session to get that same behvior. I would try to avoid such development becuase when you do change the store the behavior is totally different.