How to pass url parameters to JSF? - jsf

I haven't managed to find a way to pass parameters to JSF pages through URL parameters.
http://www.example.com/jsfApp.jsp?param1=value1&param2=value2
Could someone point me at the right direction with this?

As you're using JSPs, I'll assume that you're using JSF 1.x.
To create a link with query parameters, use h:outputLink with f:param:
<h:outputLink value="page.jsf">
<f:param name="param1" value="value1" />
<f:param name="param2" value="value2" />
</h:outputLink>
The value can be set dynamically with help of EL.
To set them in the managed bean automagically, you need to define each as managed-property in faces-config.xml:
<managed-bean>
<managed-bean-name>bean</managed-bean-name>
<managed-bean-class>com.example.Bean</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-bean>
The imlicit EL variable #{param} refers to the request parameter map as you know it from the Servlet API. The bean should of course already have both the param1 and param2 properties with the appropriate getters/setters definied.
If you'd like to execute some logic directly after they are been set, make use of the #PostConstruct annotation:
#PostConstruct
public void init() {
doSomethingWith(param1, param2);
}
For more hints about passing parameters and that kind of stuff around in JSF, you may find this article useful.
The JSF 2.x approach would be using either #ManagedProperty in the backing bean class, or <f:viewParam> in the target view. See also this question: ViewParam vs #ManagedProperty(value = "#{param.id}")

Related

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).

JSF Property references object in a scope with shorter lifetime than the target scope view

I have a view-scoped managed bean with a managed property bound to a querystring parameter. JSF gives me the familiar exception:
javax.faces.FacesException:
Property reset references object in a scope with shorter lifetime than the target scope session
For example:
<managed-bean>
<managed-bean-name>userBean</managed-bean-name>
<managed-bean-class>project.UserBean</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>
<managed-property>
<property-name>reset</property-name>
<value>#{param['reset']}}</value>
</managed-property>
</managed-bean>
Any idea to solve this?
This is by design. The managed property cannot have a scope which is narrower than the scope of the managed bean itself. The managed property is only set during bean's construction (which is in your case thus the start of a view), but in any subsequent request within the same view scope the request parameter may not be valid anymore and the bean would possibly become in an invalid state. This design limitation prevents that.
To achieve the particular functional requirement anyway, just use <f:viewParam> instead.
<f:metadata>
<f:viewParam name="reset" value="#{userBean.reset}" />
</f:metadata>
See also:
ViewParam vs #ManagedProperty(value = "#{param.id}")

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 send selectOneMenu value as direct request managed bean

I have a selectOneMenu that manages a relation between two Objects A and B.
Where A is fixed and B is selectable via the menu.
On form submit B is send to the bean for further processing (creating and saving relationship object AToB).
Not working case!
<h:selectOneMenu value=#{b}>
<!-- b items from bean -->
</h:selectOneMenu>
<h:commandButton action="#{bean.addBToSelA(b)}"/>
<managed-bean>
<description>B Entity Request Bean</description>
<managed-bean-name>b</managed-bean-name>
<managed-bean-class>B</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
Working case!
But if the selectOneMenu value is a nested property of a different managed bean it works. (as example AToB)
<h:selectOneMenu value=#{aToB.b}>
<!-- b items from bean -->
</h:selectOneMenu>
<h:commandButton action="#{bean.addBToSelA(aToB.b)}"/>
<managed-bean>
<description>AToB Entity Request Bean</description>
<managed-bean-name>aToB</managed-bean-name>
<managed-bean-class>AToB</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
Note: It is enough if my "b" is just a property of a different request managed bean.
Can someone be so kind and explain why?
Because JSF has already created the bean instance beforehand. It won't be overridden with the model value if the instance already exist in the scope. Remove the <managed-bean> from faces-config.xml and it'll work just fine.
Unrelated to the concrete problem, you seem to be already using JSF 2.x. Why sticking to the old JSF 1.x style faces-config.xml configuration? Just use #ManagedBean annotation (on real backing bean classes only, of course).

JSF bookmarking problem

I have a h:datatable that display employees data.
I want the user when click the employee name to navigate to a new page which URL looks like
employees?id=<some id>
I've tried to combine JSP EL with JSF EL, but no way out.
If you're not on JSF 2.0 yet, then you can just make use of h:outputLink in combination with <f:param>, #{param} and faces-config.xml.
Basic table example:
<h:dataTable value="#{bean.employees}" var="employee">
<h:column>
<h:outputLink value="employees.jsf">
<f:param name="id" value="#{employee.id}" />
<h:outputText value="View employee #{employee.name}" />
</h:outputLink>
</h:column>
</h:dataTable>
Basic faces-config.xml example:
<managed-bean>
<managed-bean-name>employeeManager</managed-bean-name>
<managed-bean-class>com.example.EmployeeManager</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>id</property-name>
<value>#{param.id}</value>
</managed-property>
</managed-bean>
Basic com.example.EmployeeManager example:
public class EmployeeManager {
private Long id;
private Employee employee;
#PostConstruct
public void init() {
this.employee = employeeDAO.find(this.id);
}
}
The #PostConstuct annotated methods will be invoked after bean construction and all of injection and managed property setting. Also see this article for more info and examples.
There are two possible solutions I can think of:
Use JSF 2 (part of Java EE 6)
If you are stuck in JSF 1.x, use PrettyFaces.
If it's possible to switch to a Java EE 6 server, I highly recommend option number 1.
Edit: There are 2 tags that were added in JSF 2: <h:link /> and <h:button />. These use GET instead of POST. Also, look into <f:viewparam />. On top of this, there are many other wonderful additions in JSF 2. For a brief overview, see this article.

Resources