There is a managed bean(DemoManagedBean.java) which holds some data on the (sample.xhtml)XHTML page.
There is a redirection link in the sample.xhtml which opens a new tab of the same page(sample.xhtml) but with different data loaded.
Issue - since there is only one instance of the DemoManagedBean.java, therefore not able to process anything further i.e; changes on one tab affect all the other tabs.
Is there a way so that I can have a multiple instances for every tab holding the data for the particular tabs?
Thanks,
Dinesh
You control that by setting the right bean scope. In your particular case, you need to put the bean in the request scope or in the view scope, depending on if you need a per-view based state or not.
Using the standard JSF bean management API, that would be just this (no XML needed!):
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean
#RequestScoped
public class DemoManagedBean {
// ...
}
When the #XxxScoped scope annotation is not specified, it defaults to #NoneScope. Your description however matches the session or application scope. Perhaps you've explicitly set the #SessionScoped or #ApplicationScoped annotation while not really understanding what you were actually doing. Or perhaps you're for some reason using Spring to manage beans, a Spring #Controller without any explicit scope specified defaults to application scope.
See also:
How to choose the right bean scope?
Related
I am creating a web application using JSF 2.2.20 in which I am implementing a "kinda wizard" flow which lets the user filling input fields and go back and forth the view pages through navigation. I am using a single bean for all these views.
Let's say I have views A.xhtml, B.xhtml, C.xhtml and D.xhtml, all managed by the same bean MyBean.java
I want my application to be "browser tab scoped", which means that
I do not want my bean's data be re-instantiated after every HTTP Request as it happens with #RequestScoped beans or after view changing as it happens with #ViewScoped, I want the data of my bean to be kept between view changes and redirections so the user can go back and forth between pages without losing the data he has already given.
I do not want to use the #SessionScoped scope since each time the user opens a new tab I want the bean to be re-instantiated starting from page "A.xhtml.
Is there any built-in way to achieve the scenario described above using the current JSF version? In case there is not any, could you please propose any workarounds?
Thanks in advance!
I think #ViewScoped is what you are looking for, but it depends on your exact usage.
Couple of notes:
Use javax.faces.view.ViewScoped. Don't use the deprecated managed bean annotation as it works differently.
#ViewScoped works by storing the beans in the view. So each time you load the page you get a view and a viewId that corresponds to that view. So effectively each load of the page (could be read as 'each browser tab') gets its own bean.
#ViewScoped is a passivating scope. That means your beans, and their injected Dependencies, do need to be Serializable.
Use a recent, up-to-date version of your app server, or if you bring in MyFaces manually, use the latest release. I found a number of older versions implementations buggy 5+ years ago, but it seems to work flawlessly now.
If there is a Page Navigation occurring, you probably want to use FlowScoped. This is a multi-page bean that stays alive until you end the 'flow'.
If neither of these two work, you can always implement your own scope which is surprisingly easy with CDI.
could some explain what a none scope is and purpose of it?
Suppose if i have a bean in
request scope as r1
session scope as s1
application scope a1
and say i inject none scope bean n1 in to each of above scopes then i find that n1 gets
instantiated for each parent bean when ever its parent bean[r1/s1/a1] is instantiated.
none scope bean in a1 is available throughout in a1 since a1 is appl scope.
none scope bean in s1 is available only until s1 is not destroyed and when s1 is created
again n1 is instanciated and made available to it.
Is it correct?
and what the purpose of using it? only to avoid creating such bean our self?
many thanks
A bean with a <managed-bean-scope> of none or a #NoneScoped annotation will be created on every single EL expression referencing the bean. It isn't been stored by JSF anywhere. The caller has got to store the evaluated reference itself, if necessary.
E.g. the following in the view
<p>#{noneScopedBean.someProperty}</p>
<p>#{noneScopedBean.someProperty}</p>
<p>#{noneScopedBean.someProperty}</p>
on a none-scoped bean will construct the bean 3 (three) times during a request. Every access to the bean gives a completely separate bean which is been garbaged immediately after the property access.
However, the following in for example a session scoped bean
#ManagedProperty("#{noneScopedBean}")
private NoneScopedBean noneScopedBean;
will make it to live as long as the session scoped bean instance. You should only make sure that you access it in the view by #{sessionScopedBean.noneScopedBean.someProperty} instead.
So it may be useful when you want scope-less data being available as a managed property in an arbitrary bean.
I'm using #nonescoped when my "view logic" dont need to be in any scope but be referenced by another ManagedBean.
I'm working with Liferay, as I want to make my architecture and design independent of liferay, I create my services interfaces and Dto, but when you need to persistence data, Liferay need that the companyId and companyGroupId be sended from the view layer (in this case JSF).
To maintain independence, I did a "Adapter pattern" creating a ServiceLayer ManagedBean with #noneScope with an interface independent from Liferay. This way I can get the companyId and the companyGroupId needed by the Liferay Apis.
The advantage of using #noneScope is that you can use it as a #ManagedProperty in any bean of any scope.
#NoneScoped would be beneficial in the following scenario.
Assume that we have to inject the same bean in two different scoped beans, we can mark that bean as #NoneScoped. Say a bean BeanOne with #NoneScoped can be easily injected in any bean with any scope like #Request or #Session.
Without using #NoneScoped for BeanOne, we may have to duplicate the bean with different scopes and inject them accordingly.
In a JSF 1.2 application, can I override a session-scoped Managed Bean returned with a subclass?
Class structure
I have a session-scoped Managed Bean, MainViewMB, and its subclass, RestrictedViewMB:
faces-config.xml
<managed-bean>
<managed-bean-name>mainViewMB</managed-bean-name>
<managed-bean-class>com.example.MainViewMB</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
Problem statement
The EL expression #{mainViewMB} returns an instance of MainViewMB.
I would like to rebind the name #{mainViewMB} with an instance of RestrictedViewMB, so that the EL expression #{mainViewMB} returns an instance of the subclass for the rest of the session.
Is there a way to accomplish my goal?
Motivating example
MainViewMB handles the GUI logic behind the application's main page. When a user enters the application from a special-purpose login page, I need to provide a restricted, simplified view of the main page. Overriding some of MainViewMB's properties in a subclass seems the obvious solution.
Do it manually at the moment you can/need to do it.
externalContext.getSessionMap().put("mainViewMB", new RestrictedViewMB());
This puts a new instance of RestrictedViewMB in the session scope with the name mainViewMB, effectively making it a session scoped managed bean.
You only need to take into account that managed properties and #PostConstruct/#PreDestroy are not invoked this way, you'd also have to do it manually.
I have three screens(views) associated with separate managed beans for each view.
And, I have a common pop-up dialog which can be opened in all the views.
Can I define a managedbean separately for the pop-up with state #NoneScoped; and maintain an instance of it in each parent bean?? or
Do I need to maintain pop-up data in all three parent views?
Please, suggest me the best practice.
I think this is what you are looking for (check out the answer by BalusC) -
Whats the correct way to create multiple instances of managed beans in JSF 2.0
And since you are using #NoneScoped (unlike #RequestScoped in the above question), I also recommend you to look at this answer by BalusC (about #NoneScoped) -
what is none scope bean and when to use it?
And according to this answer, you can't maintain any instances of a managedbean that is none-scoped, as they are garbaged as soon as they are used.
So, in your case since you have three separate views, for each view, the bean is constructed and used to build the view and garbaged. (Looks like it does not even last for a request cycle). When you request another view, it will be a separate instance.
To have multiple intances of a bean, you can have three properties in a Session-Scoped been (to make them survive across multiple views).
#ManagedBean
#SessionScoped
public class Parent {
private Child child1;
private Child child2;
private Child child3;
// ...
}
Im currently using JSF2, and i notice the JSF bean could have a lot of responsibility, and if combined will look like lots of codes. These include :
holding the state / data
could be a backing bean for the UI component
action methods definition
action listener methods definition
navigation
calling the services
all the setter n getters
Does it make anysense to break these into several classes or do you usually combine all of them together ?
Currenly for every JSF Bean, i define another class to hold the view data / state along with the setter getters.
How do you usually do it ? Please share your experience !
Thank you =)
Every property which is been used in action(listener) methods needs to stay in the backing bean. The remnant most likely belongs in its own class which can in turn be a different (managed/entity)bean, eventually as a (managed)property of the bean where it originated.