initial JSF1.1 bean after request parameters are set - jsf

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

Related

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

Whats the correct way to create multiple instances of managed beans in JSF 2.0

If I want to create more than one instance of managed bean in JSF 2.0, under different names in the same scope, how should I proceed? Ideally, I want the equivilant to (for example):
#ManagedBeans({name="myManagedBean1",name="myManagedBean2"})
#RequestScoped
public class MyManagedBean {
}
Thanks ..
You can't. It technically also doesn't make much sense. You're probably looking for a solution in the wrong direction for the particular functional requirement.
Your best bet is to have a parent bean and have those "multiple beans" as children.
#ManagedBean
#RequestScoped
public class Parent {
private Child child1;
private Child child2;
// ...
}
so that you can access it by #{parent.child1} and #{parent.child2}. You can of course also use a List<Child> property or even Map<String, Child> instead to be more flexible.
With the faces-config.xml it's however possible to define multiple bean classes with a different name. Still then, I don't see how that's useful.
In your case you should make use of the faces-config.xml. Implment your bean without the ManagedBean and RequestScope annotation. So your bean will not become a managed bean per default. You can than instance as much managedBeans as you need with different names, different scopes and at lease differnent properties.
For example:
<managed-bean>
<managed-bean-name>MyManagedBean1</managed-bean-name>
<managed-bean-class>org.MyManagedBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>value1</property-name>
<property-class>int</property-class>
<value>5</value>
</managed-property>
<managed-property>
<property-name>value2</property-name>
<property-class>int</property-class>
<value>2</value>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>MyManagedBean2</managed-bean-name>
<managed-bean-class>org.MyManagedBean</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>
<managed-property>
<property-name>value1</property-name>
<property-class>int</property-class>
<value>30</value>
</managed-property>
<managed-property>
<property-name>value2</property-name>
<property-class>java.lang.String</property-class>
<value>project</value>
</managed-property>
</managed-bean>
Don't think that descriptors are evil and annotations are the only way to implement your code.
One possibility is to make your class abstract and subclass it into as many named instances as you need, which you may leave empty. This will also help you separate future managed bean functionality which really only concerns one of the cases.
You will have to move the #ManagedBean (and scope) annotation to all the subclasses, regrettably, even though it is #Inherited. For the current version of Mojarra atleast, others I don't know.

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

How to pass url parameters to 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}")

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