You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.
| Online: | 17 Members of 4546 |
| Forum: Seam Users |
15. Jul 2008, 19:58 CET | Link |
I am guessing this has been discussed before but I can't figure a way to search for it so my apologies if this has already been covered.
Basically, what I need is to keep certain variables in a scope that is session-wide, but on a per-browser-window/tab basis. In other words a setting that will remain with any browser page until reset by the user on that page. Other views open by the user should not be affected by changes on another window.
In past projects, we have handled this using Tomahawk's t:saveState (which is embedded in every page in the application), but I am hoping that there is a Seam-specific solution.
Can anyone suggest a way to do this?
Is there any consideration of adding such a scope to the Seam core? Thanks, ken
Have you tried with ScopeType.PAGE?
I believe that imagination is stronger than knowledge -- myth is more potent than history -- dreams are more powerful than facts -- hope always triumphs over experience -- laughter is the cure for grief -- love is stronger than death.
_Francisco Peredo wrote on Jul 15, 2008 22:53:_<br/>
Have you tried with |ScopeType.PAGE|?
</blockquote>
No, that would only get the value through to the next page request (I think).
What I would like is to be able to say something like:
@In(scope=ScopeType.SESSION_BY_BROWSER_WINDOW)
String myConfigVar;
and know that I would get the same value every time from every request that originated from the same browser window.
Note: sorry for the poor choice of title originally -- I changed the word "page" to "window".
Thanks,
ken
Hi!
Well then use ScopeType.CONVERSATION. (Of course, you need to use @Begin to enable long running conversations)
I believe that imagination is stronger than knowledge -- myth is more potent than history -- dreams are more powerful than facts -- hope always triumphs over experience -- laughter is the cure for grief -- love is stronger than death.
I have not looked much into nested conversations, but my gut feeling is that that is going to add a lot of complexity. I will have several individual conversations specifically for handling various user transactions, yet there will be a few attributes I want to share basically across the session (yet not across browser windows.) I can add a conversation to handle this, but then must deal with all my other conversations as nested conversations -- right?
Thanks, ken
Hi!
I didn't mention nested conversations... I wrote long running conversations
I agree about nested conversations adding complexity, but... I thought you wanted the same value every time from every request that originated from the same browser window and for that you do not need nested conversations, good old long running conversations are good enough.
Well you can use ScopeType.SESSION for those few attributes you want to share basically across the session (still no need for nested conversations)
Now if you want to share them across the session (yet not across browser windows.)... First thing that comes to my mind is that is a contradiction... scopes go from more general to specific ScopeType.APPLICATION -> ScopeType.SESSION -> ScopeType.CONVERSATION -> ScopeType.PAGE (there are other scope types but they follow that basic rule) so, either you want somethig to be shared for all the browser windows inside the same session (ScopeType.SESSION) , or you want something fora particular window (ScopeType.CONVERSATION) or for a particular page (ScopeType.PAGE), I just do not see how something could be shared them across the session (yet not across browser windows.)
Perhaps (If what you need is smaller conversations inside a long running conversation across many pages... because if it is going to be in the same page you can use ScopeType.PAGE) , I would have to be more familiarized with the effect you want to achieve... one thing is for sure, I can not think of an easier way to do this without Seam ScopeTypes (with or without nested conversations). Of course you can reinvent ScopeTypes, but I bet using what seam provides for this will a much better idea (and specially easier to implement).
Another options is to build your UI like a RIA, with all this nested conversations coming and going as javascript functions, and essentially building a heavy client with javascript (I feel that is where everything will end sooner or later when we realize that all RIAs are doing is bringing back the heavy client) (Welcome back Swing!)
Hope that helps.
Regards,
I believe that imagination is stronger than knowledge -- myth is more potent than history -- dreams are more powerful than facts -- hope always triumphs over experience -- laughter is the cure for grief -- love is stronger than death.
Here is a use case that illustrates what is needed:
1) User logs in and enters a part of the application where he needs to select a portfolio -- he has multiple choices, and every screen (or many screens anyway) hereafter will make use of the currently selected portfolio.
2) User goes to the projects page, which lists all projects for said portfolio. He selects one to edit. (At this point I start a conversation which will be used over a number of pages to manage his edit session).
3) User can either complete the edit session or perhaps may exit using the menu -- in the menu all the links are s:link with propagation btw.
4) User does various other activities, most of which use conversations.
5) At some point user opens another browser window, and selects a different portfolio -- because perhaps he wants to retrieve some information from that portfolio while editing the first, and would like to cut and paste or view screens side by side or whatever.
6) Back in the original window, the user should still have that original portfolio value as the current portfolio for that window.
Now, then, is using nested conversations the only way to handle this use case?
Thanks, ken
Hi!
If it is true that hereafter will make use of the currently selected portfolio and only the selected portafolio the SESSION should be enough.
Right, conversation is a good idea for this. (IMO)
I have had some performance problems with s:link in menus when the .page.xml have many of parameter references <param name="" value="#{}", so I prefer to use h:outputlink.
Well, if those are of a smaller scope, I guess you will have to use nested conversations after all (or you may use parallel conversations)
Well that means it is not true that hereafter will make use of the currently selected portfolio and only the selected portafolio and therefore you will have to use CONVERSATION for that (and that means you will need NESTED for subsequent operations (in this case projects) on the selected portfolio)
But, not only for that window, also for any window called by that window... and any window with that exact same url? don't you agree?
I think here you might have a conceptual problem, it is not right (from a server perspective) to say that something happens for that window, but you can say that it happens for that url o for that conversation id... unless, as I said in the previous post, you are building a RIA and then, since all interaction is handled in javascript, you may only need CONVERSATION for the moment when you select the portfolio (or perhaps not even than, nothing prevents you from building portfolio browser -all in javascript- on the same window), and after that, all operations done for a particular conversations are handled in the client
The way I see it you have 2 options, if you want to make the server aware of what is going on, then you have to use conversations, or, you can build this as a RIA using something like... i don't know, ExtJS o Flex and do all this conversational handling on the client.
Regards,
I believe that imagination is stronger than knowledge -- myth is more potent than history -- dreams are more powerful than facts -- hope always triumphs over experience -- laughter is the cure for grief -- love is stronger than death.
Hi!
Oh, and by the way, I read about Tomahawk uiSaveState,and if what it is stated in that page is correct t:saveState it is the exact same thing as ScopeType.PAGE.
Regards,
I believe that imagination is stronger than knowledge -- myth is more potent than history -- dreams are more powerful than facts -- hope always triumphs over experience -- laughter is the cure for grief -- love is stronger than death.
All web pages had to include the following (not a big deal -- we just stuck this in the common jsp that is included in every page):
<t:saveState id="savestateUserctx" value="#{userctx}"/>
and then this snippet goes into faces-config:
<managed-bean>
<managed-bean-name>userctx</managed-bean-name>
<managed-bean-class>myapp.MyUserContext</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
and thats *it*. Now every single piece of code in the application can pull userctx out of FacesContext and use it to store/retrieve configuration information.
I have not figured out a way to duplicate this in Seam using PAGE scope. I can of course create a bean object that Injects and Outjects "userctx", but unless that bean is actually used during a user transaction, the Injection/Outjection will not happen and thus the value will be lost. (Or is there an easy way you can think of to force the injection/outjection on every single user transaction?)
Thanks,
ken
Well, I haven't used Tomahawk, but I think it migth be lot easier in Seam: all you have to do is go to your MyUserContext.java and write:
@Name("userctx") @Scope(ScopeType.PAGE) public class MyUserContext{ }And that is it, now, if you want it autocreated:
@Name("userctx") Scope(ScopeType.PAGE) @AutoCreate public class MyUserContext{ }And if you want to use it in SomeWhere.java:
Scope(ScopeType.PAGE) @AutoCreate public class SomeWhere.java{ @In MyUserContext userctx; }have you tried this?
I believe that imagination is stronger than knowledge -- myth is more potent than history -- dreams are more powerful than facts -- hope always triumphs over experience -- laughter is the cure for grief -- love is stronger than death.
I have not actually tried it, no, but I believe it will not work, because as soon as there is any transaction that does not explicitly use userctx, it will not be created/outjected into the next Page scope, and therefore will never be available again for any subsequent transaction that does need it (except of course it would be auto-created, though that does not help because it will have lost any values previously stored in it.)
Do I misunderstand how the Seam life cycle works?
Thanks, ken
Well then... why don't your try?
I don't quite get what do you mean by transaction... and why would you want to have it outjected into the next Page scope (AFAIK pages scopes are for stuff in the same page, no in the next page, and that (I think) should be true for both Tomahawk and Seam)
I have to admit I don't like when someone else post this as an answer to one of my questions but in this case I think: you should really try and see.
I believe that imagination is stronger than knowledge -- myth is more potent than history -- dreams are more powerful than facts -- hope always triumphs over experience -- laughter is the cure for grief -- love is stronger than death.
A user transaction is any single unit of work that a user executes via a single http request. Every link click or form submission in the application is a user transaction.
Not to be confused in any way with a persistence transaction.
The reason I need this to follow up in the next page scope is that I would be using this page scope trick to pass a variable value from page to page to page forever, thereby placing the users current selection as available to any downstream code, even if it is 100 user transactions down the road. The nice thing about using said trick is that when the user opens a second browser window and changes his selection, it cannot affect the original browser window.
Or at least that is how I used t:saveState (and it has worked quite well.) Note one drawback I'd like to fix is that we could never redirect as the variable in the request scope is lost in doing so.
I am not yet ready to try this because I am still relatively sure that even though everything will work great going from A to B (really I do believe this), when the user then goes from B to C and there is no explicit use of userctx, then any values in userctx will be gone.
The difference between savestate and Seam Page scope is that in the former, it goes from embedded in the page to into the request scope and then back out embedded in the next page. Whereas in Seam, the value will be outjected only if something specifically outjects it -- and I would prefer not to have to go into every single action class and write an Inject/Outject userctx, which it seems to me would be the only way to get this to work.
However, I do have a hope that there is some trick I could use to do this. I am afraid that the inability to redirect is going to be too restrictive for Seam (plus I just generally would prefer to find a Seam solution.)
Thanks again, ken
Quick update -- I did try this since it was easy enough to do, and I can confirm that it worked as I expected. The userctx value does not survive past a user transaction in which the underlying action class does not inject the userctx bean.
Thanks, ken