I just started learning with JSF and I'm wondering about this issue.
I have 16 Checkboxes. When I open the Page and my Brother is opening it too it seems like we have the same session. When I click one of the checkboxes it is checked on my brothers browser too.
The selected checkboxes are saved in a private ArrayList<String> selectedBoes = new ArrayList<String>();
My ManagedBean ist SessionScoped.
Why is this happening and how to avoid it?
My brothers session ID is cdbbb126e96060ddb924b9d5e591. Mine is cd9a5c4180bd9dfef0ec8db2ac4d
Then the only possible cause is that you're actually not storing them in the session scope. The symptoms indicate that you're either storing them in the application scope, or even that you declared it static (and thus the code in the question does not represent the real code at all; the code in your comments indicate that also less or more, you used a different property name, apparently you attempted to type it from top of head, you should not do that, you should copypaste the real code).
Note that when you're using CDI's #Named instead of JSF's #ManagedBean, then it would default to the application scope, unless otherwise specified with a javax.enterprise.context scope annotation. So if you're using JSF's own javax.faces.bean.SessionScoped annotation, which is not supported by CDI, then it would still be in the application scope.
Related
In JSF 2.0, the most obvious use-case for the view scope is a single page with potentially multiple AJAX post-backs. Using CDI instead of JSF managed beans leaves us without the view scope so we're either left to implement our own, use a (possibly bug-ridden) third party implementation or use the conversation scope.
My question: Is the conversation scope a worthy substitute for the view scope in the typical AJAX situation? Like the view scope, does it allow multiple instances per session? What are the pitfalls?
I'm aware of one of the pitfalls, namely that the conversation scope isn't automatically deleted when the user navigates away from the page, but instead is deleted after a time-out. But I'm not sure what happens when the user navigates back to that page before the conversation has timed out.
UPDATE
The conversation scope does indeed support multiple instances per session. This book states as much and I was able to confirm this using code from ch. 2.
In any #ConversationScoped CDI beans, you must have the following field:
#Inject
private Conversation conversation;
Whenever you want to begin the conversation, you need to check if the bean is in transient state. Otherwise, IllegalStateException will be thrown. It would be something like this:
public void beginConversation() {
if (conversation.isTransient()) conversation.begin();
}
By doing this, your bean will be in the long-running state. Hence, if the user navigate aways from the page and navigates back later on, you can always check if his conversation has timed-out or not and bring him to the page where he left.
Besides, I have been using #ViewScoped ManagedBean together with CDI bean for a while. You can still use #Inject to inject a CDI bean into a MangedBean. I don't think you can do the other way around though. Anyway, I have no idea if this would cause anything bad to happen later. However, up until now, I have never met any issues. If you really want to use #ViewScoped, I think you can try :P.
UPDATE:
Is the conversation scope a worthy substitute for the view scope in the typical AJAX situation?
I don't think #ConversationScoped can ever fully replace #ViewScoped.
Like the view scope, does it allow multiple instances per session?
No, you cannot have multiple instances per session. As I mentioned, if you start a new Conversation while the old conversation is still in long-running state, you will get IllegalStateException.
What are the pitfalls?
Well, one of the main advantages of #ViewScoped over #RequestScoped is that you don't need to re-initiate data every time the user submits the form to the same View. However, with #ConversationScoped, this advantage is over-used. While this problem is not as serious as if you use #SessionScoped, you still need to hold the initiated data as long as the #ConversationScoped bean lives. The longer the conversation, the more data you may need to hold.
I want to do something like this: index.xhtml -> createPerson.xhtml -> addAddress.xhtml -> index.xhtml.
In Managed-Bean CreatePerson a new Person-Object will be created, filled and saved, in Managed-Bean AddAddress I need the Person-Object in order to add an address to this person and after this, it should navigate back to the starting point. I think, the Managed-Bean CreatePerson should be #SessionScoped, because I have to inject the Person-Object into AddAdress (here #ViewScoped).
I want to have a loop or rather the possibility to create more than one person, but how can I do this if I have a SessionScoped-Bean, that lives longer than I need it? Is there any command or annotation to destroy it? How do you handle such workflows related to the scopes?
I know about MyFaces Orchestra with conversation-scope, but I will, if possible, do it only with Eclipse/Tomcat (7.0.11)/Mojarra (2.0.3).
Use a single view and make use of the rendered attribute to show/hide included views with "subforms" depending on each other. This way you can go with a #ViewScoped bean.
Alternatively, just save the Person in the DB after create and pass its id as request parameter to the next view and let it load from the DB again.
If you only want (or can) use Tomcat and Mojarra then both solutions mentioned by BalusC work perfectly, although with the limitations that you have to stay on a single page or redo queries between page navigation. Your use case is exactly what the conversation scope in Java EE 6 (through CDI) is made for. You can add this too to Tomcat via the Weld reference implementation.
When using the method BalusC outlined for staying on a single page, to give the user a tiny bit the impression of dealing with separate pages, it might be an option to display the rendered parts of the page using 'dialogs' (floating, css, ...). If using a third party component library is an option for you, you could add RichFaces or PrimeFaces that both contain ready to use dialog components.
And my confusion with JSF continues. This is a continuation of a question asked yesterday, but I feel it warrants a new question. I have a single seam component that expects a URL parameter to be injected for retrieving a List<String> from a method. This works perfectly on the first navigation to the page. The List is used to display many different selectOneRadio groups that populate a <h:form/>.
Now on the submit, I cannot get the URL parameter to be injected or otherwise set on the component! Adding <h:inputHidden/> causes FacesExceptions to be thrown.
Then I tried setting the List as an instance variable on the object, and when the subsequent call is made on the submit (which I also do not understand why that is done) I check to see if the variable is non-null: if it isn't, return it.
Now I found that a new instance of the component is created on submit!!!
getList() called
this.toString(): .BeanAction#5fd98420
#### This is when submit is clicked
getList() called
this.toString(): .BeanAction#22aacbce
The component has the following annotations:
Stateful
#Scope(ScopeType.CONVERSATION)
#Name("bean")
#Restrict("#{identity.loggedIn}")
Can someone explain why there is a new instance of the component created?
I'm really not quite sure how to go about handling this. I thought the hidden parameter would work, because that is how I would do it with straight HTML, and I'm a little surprised that its not working for JSF/Seam.
I hit upon the solution, but I still dont understand why it is required. By adding <S:conversationId/> to the <h:commandButton/> tag I am now getting the conversationId propagated across the form submit.
However, the seam documentation states:
If you don't do anything special, a non-faces request (a GET request for example)
will not propagate the conversation context and will be processed in a new
temporary conversation.
Which means Seam/JSF was treating my form submit as a "non-faces request". Why is that?
When you enter the page (or after the submit), do you see a conversation id in the url? I am concerned that perhaps the Seam Conversation is not being initialized correctly.
We have a search form where the filter is bound to a property on a managed bean (session scope). It's not component binding, its property binding like <h:inputText value="#{searchBean.filter}"/>.
Submitted data from different machines (different sessions, then) is getting mixed. You search "john", and get "mary" just because the guy beside you have just searched "mary". The value of your searchBean.filter is getting his submitted data instead of yours.
I've already googled around a lot and found no solution, just an ocurrence of the same problem.
Have anybody faced this issue already? Any clues?
Thanks!
This can have two causes:
The bean is actually in application scope.
The property in question is declared static.
To fix 1), just ensure that it's in session scope.
To fix 2), just remove the illegal modifier.
Solved! Finally. Thanks guys, for your attention!
It was something like what Balus guessed at the first time. It was a static hidden in a dark corner. I had really double, triple checked everything looking for statics, but -- don't ask me why -- someone created a second bean (Foo) which was holding a static reference for SearchBean.
In the JSP, there was an action="#{foo.search}" instead of searchBean.search. Class Foo had a method with the same name as in SearchBean, that was doing no more than a searchBean.search();.
I think pressure for fixing this bug for yesterday didn't allow me to see this trap in the JSP.
Anyone know of any other custom spring scopes than Servlet Context Scope and ThreadScope ?
If you've made some closed-source custom scope I'd really also be interested in hearing what it does and how it worked out for you. (I'd imagine someone would make a WindowScope in a desktop app ?)
I'm open to all use cases, I'm looking to expand my horizon here.
We implemented our own custom Spring scope. A lot of our code works at a relatively low level, close to the database, and we maintain a conceptual level on top of that with its own object model of data sources, links, attributes etc.
Anyway, a lot of beans require a so-called StorageDictionary (an encapsulation of this object graph) to do their work. When we make non-trivial changes to the object graph, the dictionary sometimes needs to be blown away and recreated. Consequently, we implemented a custom scope for objects that were dictionary scoped, and part of the invalidation of a given dictionary involves clearing this custom scope. This lets Spring handle a nice form of automatic caching for these objects. You get the same object back every time up until the dictionary is invalidated, at which point you get a new object.
This helps not only with consistency but also allows the objects themselves to cache references to entities within the dictionary, safe within the knowledge that the cache will be valid for as long as they themselves are retrievable by Spring. This in turn lets us build these as immutable objects (so long as they can be wired via constructor injection), which is a very good thing to do anyway wherever possible.
This technique won't work everywhere and does depend heavily on the characteristics of the software (e.g. if the dictionary was modified regularly this would be horribly inefficient, and if it was updated never this would be unnecessary and slightly less efficient than direct access). However, it has definitely helped us pass off this management of lifecycle to Spring in a way that is conceptually straightforward and in my opinion quite elegant.
In my company we've created two custom scopes, one that will use Thread or Request and another that will use either Thread or Session. The idea is that a single scope can be used for scoped beans without having to change configuration based on the execution environment (JUnit or Servlet container). This also really comes in handy for when you run items in Quartz and no longer have a Request or Session scope available.
Background:
I work on a single web app that runs 4 different web sites under the same servlet context. Each site has its own domain name, e.g. www.examplesite1.com, www.examplesite2.com, etc.
Problem:
Sites sometimes require their own customised instance of a bean from the app context (usually for customised display of messages or formatting of objects).
For example, say sites 1 and 2 both use the "standardDateFormatter" bean, site 3 uses the "usDateFormatter" bean and site 4 uses the "ukDateFormatter" bean.
Solution:
I'm planning on using a "site" scope.
We have a Site enum like this:
enum Site {
SITE1, SITE2, SITE3, SITE4;
}
Then we have a filter that stores one of these Site values in the request's thread using a ThreadLocal. This is the site scope's "conversation id".
Then in the app context there'd be a bean named "dateFormatter", with 'scope="site"'. Then, wherever we want to use a date formatter, the correct one for the user's current site will be used.
Added later:
Sample code here:
http://github.com/eliotsykes/spring-site-scope
Oracle Coherence has implemented a datagrid scope for Spring beans. To sum it up:
A Data Grid Bean is a proxy to a
java.io.Serializable Bean instance
that is stored in a non-expiring
Coherence Distributed Cache (called
near-datagridbeans).
Never used them myself but they seem cool.
Apache Orchestra provides SpringConversationScope.
In a Spring Batch application, we have implemented an item scope.
Background
We have lots of #Service components which compute something based on the current batch item. Many of them need the same workflow:
Determine relevant item parts.
Init stuff based on the item.
For each item part, compute something (using stuff).
We moved the workflow into a base class template method, so the subclasses implement only findItemParts(Item) (doing 1 and 2) and computeSomething(ItemPart) (doing 3). So they became stateful (stuff initialized in findItemParts is needed in computeSomething), and that state must be cleared before the next item.
Some of those services also involve injected Spring beans which are also derived from the current item and must be removed afterwards.
Design
We implemented an AbstractScopeRegisteringItemProcessor which registers the item and allows subclasses to register derived beans. At the end of its process method, it removes the item from its scope context, and the derived beans using DefaultSingletonBeanRegistry.destroySingleton.
How it worked out
It works, but has the following problems:
We did not manage to get the derived beans cleaned up without registration (just based on their #Scope). The concrete processor must create and register them.
AbstractScopeRegisteringItemProcessor would have been nicer using composition and dynamically implementing all interfaces of the underlying processor. But then the resulting #StepScope bean is a proxy for the declared return type (i.e. AbstractScopeRegisteringItemProcessor or ItemProcessor) without the required callback interfaces.
EDIT
With the aid of #Eliot Sykes's solution and shared code plus #Cheetah's BeanDefinition registration, I was able to get rid of the registration as singleton beans. Instead, ItemScopeContext (the storage used by both the processor and the Scope implementation; Java-configured via a static #Bean method) implements BeanDefinitionRegistryPostProcessor. It registers a FactoryBean whose getObject() returns the current item or throws an exception if there is none. Now, a #Component annotated with #Scope(scopeName = "Item", proxyMode = ScopedProxyMode.TARGET_CLASS) can simply inject the item and need not be registered for end-of-scope cleanup.
So in the end, it did work out well.
A spring locale scope based on the users locale wihtin a web application
See related wiki page
In my company, we have also implemented spring custom scope. We have a multi tenant system where every customer can customize settings. Instance based scope of ours, caches the beans which are customer specific. So each time user of a customer logs in, these settings are cached and reused again when other users of the same customers sign in.
I once used a kind of conversation scope to store some objects in the session scope, in order to keep them when re-entering the same page, but limited to a single page to avoid to leave useless objects in the session. The implementation just stored the page URL and cleaned the conversation scope on each page change.