JSF datatable refresh on page load - jsf

I have a data table in JSF which gets populated when user selects a drop-down menu. The list that table shows comes from a backing bean. This backing bean is in the session scope. So when user clicks on other links of the webpage and comes back to this page, it still shows the data from the data list with the previous selections.
Question is - how to make sure, that data gets reset when user leaves the page so that when user comes back in, they can see a fresh page with no data in it.
I can not put the backing bean in request scope as that will make it impossible to have a cart type application.

Keep the datamodel in the session scoped bean, add a request scoped bean which copies the reference from the session scoped bean and let the form submit to that request scoped bean and let the view use the request scoped bean instead. You can access the session scoped bean from inside a request scoped bean by under each managed property injection. E.g.
<managed-bean>
<managed-bean-name>cart</managed-bean-name>
<managed-bean-class>com.example.Cart</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>showCart</managed-bean-name>
<managed-bean-class>com.example.ShowCart</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>cart</property-name>
<value>#{cart}</value>
</managed-property>
</managed-bean>
wherein the ShowCart can look like:
public class ShowCart {
private Cart cart;
private Cart show;
// +getters+setters
public String submit() {
show = cart;
// ...
}
}
and the view uses #{showCart.show} instead.

Related

Use many beans from the same class, different scopes

I want to use a ManagedBean class, Users.java, to create 2 bean instances with different scopes. I tried to do this in 2 ways:
1.
Use ManagedBean and SessionScope annotations for Users (this creates a "users" with a session scope), and declare in faces-config.xml another MenagedBean from User, with request scope.
#ManagedBean
#Component
#SessionScoped
public class Users implements Serializable {...}
Note: "Component" is from Spring framework, this can be ignored for the moment.
In faces-config.xml:
<managed-bean>
<managed-bean-name>newUser</managed-bean-name>
<managed-bean-class>ro.telacad.model.Users</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
In login page I use "#{users.}" inside . For this case, the login works fine (is made with Spring Security). I created also a "Sign up" page, and there, I need the "Users" bean with request scope to create a new user in database, "#{newUser.}". I put a breakpoint inside a method, and when the application stopes there, all the attributes of this object are null, and the application throws a NullPointerException.
2.
Remove annotations "ManagedBean" and "SessionsScoped" from Users.java, and declare the 2 managed beans in faces-config.xml:
<managed-bean>
<managed-bean-name>currentUser</managed-bean-name>
<managed-bean-class>ro.telacad.model.Users</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>newUser</managed-bean-name>
<managed-bean-class>ro.telacad.model.Users</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
Of course, this time I use in login page and in welcome page "#{currentUser.}". This time, the NullPointerException is thrown in both cases (login and sign up).
The file faces-config.xml is loaded. I tested this by creating a class TempBean.java with 1 attribute and 1 method, declaring a managed bean of this class in faces-config.xml and use this in a h:form. It worked.
I extended "Users" class, exactly like Selaron said in the comment. It works fine. But I think it is not a good idea to do this in a real application, but for the moment I don't have any better idea.

JSF CommandButton action before submit

I've created JSF 1.1 page.
In the page I have 2 textboxes and commandbutton.
The textboxes are connected to object in the backing bean, and thw object's values are showed there, and the user can edit it as he wants, and when he clicks on the button I want to go to the bean and save the new values in the object.
The bean must be request, not session!
<h:inputText value="myBean.PersonName"><\h:inputText>
<h:commandButton action="myBean.saveEditName"><\h:inputText>
backingBean:
public String saveEditName(){
//Go to database and save the new object
}
The problem is, when I click on the button, the bean is refreshed, the objects returns to its previous values, and then the action is invoked.
Why is that? How can I perform an action before the submit refreshes the bean? (Without using servlet in javascript).
Thanks!
Use Explicit Bean Declarations as Given Below:
<managed-bean>
<managed-bean-name>someName</managed-bean-name>
<managed-bean-class>
somePackage.SomeClass
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>

Passing t:savestate bean to another bean

I've two JSF 1.1 pages that I'm currently working with. One of them is viewDevices.jsp and the other is vewDevicesPrint.jsp. They are both running under the view scope (using tomahawk savestate, that is). In viewDevices, it has a img that user can click on to go to the viewDevicesPrint.jsp. Like so:
<img src="redesign/images/printicon2.png" alt="print records" border="0" width="16" height="16" onClick="javascript:window.open('/viewDevicesPrint.jsf','_blank','height=500,width=900,menubar=yes, toolbar=yes,scrollbars=yes')"/>
When this img is clicked, I would like to pass the current instance of viewDevicesBean to the viewDevicesPrintBean. Is there a way to do this?
I've the following in faces-config.xml. In debug, viewDevicesPrintBean is getting a new instance of viewDevicesBean, instead of the current instance of it.
<managed-bean>
<managed-bean-name>viewDevicesPrintBean</managed-bean-name>
<managed-bean-class>com.arch.myaccount.jsf.ViewDevicesPrintBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>param_viewDevicesBean</property-name>
<value>#{viewDevicesBean}</value>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>viewDevicesBean</managed-bean-name>
<managed-bean-class>com.arch.myaccount.jsf.ViewDevicesBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>param_flow</property-name>
<value>#{param.Flow}</value>
</managed-property>
</managed-bean>
A view scoped bean is tied to the current view. When you change the current view by navigating to a different view, then that different view would get a brand new instance of the view scoped bean. Note that it works also that way in JSF2.
Your best bet is to pass the desired data as request parameters in window.open() URL (escape them!), so that the print bean can get them as request parameters (via either managed property or ExternalContext). An alternative, especially if you've rather a lot of data, is to store the bean instance in the session scope under an unique and autogenerated key (e.g. java.util.UUID) and pass that key as request parameter so that the bean associated with the print page can obtain the data from the session scope by that key.

Get values of multiple backing beans from form save action method in JSF

In the jsf page I created, 3 other jsp pages are added through page include, each of these has its own backing bean and pre populates from webservices, values through scriptcollector prerender method. While saving, how to get the submitted values in my save action method? Is it possible to get each of these beans with their current values from Faces Context?
I am using JSF 1.1.
You can inject one managed bean in other managed bean as managed property. In JSF 1.x this is to be done with the <managed-property> declaration in faces-config.xml.
Here's a kickoff example of how 3 web service beans are to be injected in 1 form bean.
<managed-bean>
<managed-bean-name>webServiceBean1</managed-bean-name>
<managed-bean-class>com.example.WebServiceBean1</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>webServiceBean2</managed-bean-name>
<managed-bean-class>com.example.WebServiceBean2</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>webServiceBean3</managed-bean-name>
<managed-bean-class>com.example.WebServiceBean3</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>formBean</managed-bean-name>
<managed-bean-class>com.example.FormBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>webServiceBean1</property-name>
<value>#{webServiceBean1}</value>
</managed-property>
<managed-property>
<property-name>webServiceBean2</property-name>
<value>#{webServiceBean2}</value>
</managed-property>
<managed-property>
<property-name>webServiceBean3</property-name>
<value>#{webServiceBean3}</value>
</managed-property>
</managed-bean>
This way you can just access them "the usual way" inside the form submit method.
public class FormBean {
private WebServiceBean1 webServiceBean1;
private WebServiceBean2 webServiceBean2;
private WebServiceBean3 webServiceBean3;
public String submit() {
// Here you can just access the submitted data through the injected beans.
}
// Add/generate setters. Getters are not necesary.
}
As an alternative, you can use Application#createValueBinding() to evaluate EL programmatically.
public String submit() {
FacesContext context = FacesContext.getCurrentInstance();
Application application = context.getApplication();
WebServiceBean1 webServiceBean1 = (WebServiceBean1) application.createValueBinding("#{webServiceBean1}").getValue(context);
WebServiceBean1 webServiceBean1 = (WebServiceBean2) application.createValueBinding("#{webServiceBean2}").getValue(context);
WebServiceBean1 webServiceBean1 = (WebServiceBean3) application.createValueBinding("#{webServiceBean3}").getValue(context);
// ...
}
Note that above methods are deprecated in JSF 1.2 and newer in favor of unified EL API. See also Get JSF managed bean by name in any Servlet related class.
While saving, how to get the submitted values in my save action method?
In apply request values phase, the submitted values assigned and and can be accessed with the following method input.getSubmittedValue() where input is an input based UIComponent. The submitted value will be validated and converted during the validations phase and if this happens successfully then the value of the UIComponent will be set appropriately. You should be able to find the UIComponent you are looking from FacesContext.
Is it possible to get each of these beans with their current values from Faces Context?
I am really not sure what your aim is, but if all you want is just the other managed beans then you can get their values from the HttpSession which is available from the ExternalContext.
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("nameOfManagedBean");

How to invoke a JSF backing bean method from a non-faces request?

We have a requirement to replace our current login, for a web-application written in JSF using single sign-on. Currently our login.jsp invokes the authenticate method on a backing bean to achieve this and perform additional role validations. Now authentication will be done by my single sign-on server, but how do i invoke the authenticate method on the backing bean to perform the role validations
Set request parameters as managed properties and use the #PostConstruct annotation to execute some code immediately after bean construction and managed property setting.
You can set GET or POST request parameters as managed properties as follows:
<managed-bean>
<managed-bean-name>bean</managed-bean-name>
<managed-bean-class>mypackage.Bean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>name1</property-name>
<value>#{param.name1}</value>
</managed-property>
<managed-property>
<property-name>name2</property-name>
<value>#{param.name2}</value>
</managed-property>
</managed-bean>
Or if you're already on JSF 2.0, then you can just use #ManagedProperty:
#ManagedProperty(value="#{param.name1}")
private String name1;
#ManagedProperty(value="#{param.name2}")
private String name2;
Those parameters will be set when the enduser fires a GET or POST request with a name1=value1&name2=value2 query string. The #{param.name1} EL expression basically stands for the result of request.getParameter("name1").
Now create a #PostConstruct method like follows:
#PostConstruct
public void init() {
if (name1 != null && name2 != null) {
// Both request parameters are been set. Do your thing here!
}
}

Resources