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

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!
}
}

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.

initial JSF1.1 bean after request parameters are set

I need to perform some initialization of a JSF1.1 bean after all URL request parameters are set. Is there a good way to do so? For example, if the manage-bean is setup in faces-config like below, I need to perform some initialization after all there param (Param1, 2, 3) are set.
<managed-bean>
<managed-bean-name>someBean</managed-bean-name>
<managed-bean-class>com.arch.SomeBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>param1</property-name>
<value>#{param.param1}</value>
</managed-property>
<managed-property>
<property-name>param2</property-name>
<value>#{param.param2}</value>
</managed-property>
<managed-property>
<property-name>param3</property-name>
<value>#{param.param3}</value>
</managed-property>
</managed-bean>
Normally, you would use a #PostConstruct annotated method for this, but the support for #PostConstruct is only available since JSF 1.2.
Your best bet is to lazily execute it in the setter method of the managed property. E.g.
public void setParam3(String param3) {
boolean wasNull = this.param3 == null;
this.param3 = param3;
if (wasNull) {
init();
}
}
See also:
Communication in JSF - Passing GET parameters to backing bean
Alternatively, just upgrade to JSF 1.2. JSF 1.1 is fully forward compatible with JSF 1.2 without any changes in the code (expect of code where in you're incorrectly assuming a JSF 1.1 specific bug to be correct behavior).

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");

JSF datatable refresh on page load

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.

Notifying one bean from another in ICEFaces

I have an ICEFaces we application. One page has two beans that display different things on the page.
I want to be able to notify one bean when another bean changes something on the bean so that the first bean update its content on the page.
Is that possible in ICEFaces? if so how?
Thanks,
Tam
What you can do is to "inject" bean1 into bean2, so the bean2 will have access to any method present in bean1.
If you are using Spring, this can be easily done when defining the beans:
<bean id="bean1" class="foo.bar.Bean1"/>
<bean id="bean2" class="foo.bar.Bean2">
<property id="bean1" ref="bean1"/>
</bean>
and in Java code of bean2:
public class Bean2 {
private Bean1 bean1 = null;
// The setter will be used by Spring to inject Bean1 in Bean2...
public void setBean1(Bean1 bean1) {
this.bean1 = bean1;
}
...
public void someMethod() {
...
// Now, you can call the bean1 instance to update what you want...
bean1.updateSomething();
}
}
If you are not using Spring:
You can directly access the bean1 instance within bean2 code like that:
Bean1 bean1 = (Bean1) FacesContext.getCurrentInstance().getCurrentInstance()
.getExternalContext().getSessionMap().get("bean1");
As has already been noted, JSF can do simple injection as well. Something like this in your faces-config.xml file:
<managed-bean>
<managed-bean-name>bean1</managed-bean-name>
<managed-bean-class>org.icefaces.sample.Bean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>bean2</managed-bean-name>
<managed-bean-class>org.icefaces.sample.Bean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>bean1</property-name>
<value>#{bean1}</value>
</managed-property>
</managed-bean>
As for updating the user interface when bean values change, that can be triggered through regular client interaction with the page. However, if you are doing a collaborative type application (where one user's change can update values that other user's can see), then ICEfaces has a feature called Ajax Push that you can use. Check their docs for more info.
I was going to post some examples of my own work, but the guys on the ICEFaces blog already have a really good blog post of their own. Take a look.

Resources