Execute a bean action on page load using JSF2 and richFaces4 - jsf-2

Im working on a JSF2 and richFaces4 application and I want to execute a backing bean action on load of one of my xhtml view.
Thanks.

If you make a bean #ViewScoped, a method with a #PostConstruct annotation will be invoked exactly once when rendering an xhtml view that references it.
For example:
#ManagedBean
#ViewScoped
public class Foo {
#PostConstruct
public void onPageLoad() {
...
}
}
<h:outputText value=#{foo.property}"/>

Related

Call session scoped bean method on every view

Perhaps this is a question I should be able to find documentation on, but I'm unfamiliar with a lot of the jargon so I'm struggling.
Basically, I'm using JSF2. I have a SessionScoped bean, and it uses a postconstruct init() method. I want the init() method to be called everytime the session starts, which works fine, but I also want it to be called every time the view loads.
Is there an easy way to do this?
Thanks!
Replace #PostConstruct by <f:event type="preRenderView">.
<f:event type="preRenderView" listener="#{sessionScopedBean.init}" />
Better, however, is to split it into 2 beans: a #SessionScoped one and a #ViewScoped one. Then just reference the #ViewScoped one in the view instead and inject the #SessionScoped one as a property of the #ViewScoped one.
#Named
#ViewScoped
public class ViewScopedBean {
#Inject
private SessionScopedBean sessionScopedBean;
#PostConstruct
public void init() {
// ...
}
// ...
}
See also:
When to use f:viewAction / preRenderView versus PostConstruct?
How to choose the right bean scope?

How to prevent #PostConstruct from being called on postback

When the page loads for the first time, the #PostConstruct is called, but when I perform a postback on this page, the #PostConstruct is called again.
How can I make it to run only on the initial request and not on every postback?
#PostContruct
public void init() {
// charge combos....
}
public void submit() {
// action
}
Apparently your bean is request scoped and thus reconstructed on every HTTP request. I'm not exactly sure why you'd like to prevent the #PostConstruct from being called again, as you would otherwise end up with an "empty" bean state which might possibly lead to form submit errors, but okay, you could add a check if the current request is not a postback.
public void init() {
if (!FacesContext.getCurrentInstance().isPostback()) {
// charge combos....
}
}
This way the "charge combos" part won't be invoked on postbacks.
Or, maybe your actual question is not "How to prevent postconstruct from being called on postback?", but more "How to retain the same bean instance on postback?". In that case, you'd need to put the bean in the view scope instead of in the request scope.
#ManagedBean
#ViewScoped
public class Bean implements Serializable {
// ...
}
As long as you return null from action methods, this way the same bean instance will live as long as you're interacting with the same view by postbacks. This way the #PostConstruct won't be invoked (simply because the bean isn't been reconstructed).
See also:
How to choose the right bean scope?
use this import:
import javax.faces.view.ViewScoped; for #ViewScoped

Setting ManagedBean values in another ManagedBean's method

If I am navigating from page one to page two, When I click on Page one's submit button, control goes to the managed bean written corresponding to page one, I want to fetch some result from database and show them to page two, If I set the Database values into the Managed bean corresponding to page two in the first Managed Bean's action method, then will I be able to get those on page two.
Please suggest if my approach is right?
You can inject let's say bean named Bean1 into Bean2 this way
#ManagedBean
#RequestScoped
public Bean2 {
#ManagedProperty(value="#{bean1}")//this is EL name of your bean
private Bean1 injectedBean;
public void setBean1(Bean1 value) {
injectedBean = value; //provide setter for it
}
#PostConstruct
private void init() {
List<YourData> list = injectedBean.getDBData(); //now you can fetch your list
}
Note that you have to provide setter for injection and scope of the injected bean should be always same or higher then the your beans scope (in this case Bean1 has to be at least RequestScope)
P.S. Also you could have some kind of DAO bean which could do all the database database operations for you (it can be EJB bean or even JSF Managed Bean) and then inject it to every ManagedBean which will require cooperation with your DB.

Use Bean inside Managed Bean

how can i use a bean inside other bean ?
I use this solution, what's the best way ?
#ManagedBean(name="firstBean")
public class FirstBean implements Serializable{
#ManagedProperty(value="#{myBean}")
private MyBean myBean;
...
//(get/set method)
}
I'm new in JSF and JSP so probably it's a bad practies.
Your solution is the right one to inject another bean.
You only need the setter for the injected bean.
Are you having any issues\errors with it?

Passing a JSF2 managed pojo bean into EJB or putting what is required into a transfer object

Currently i am calling EJB 3 Session Beans from JSF 2. However, i am not sure if i should be passing JSF managed beans into EJB?
Assuming that whatever on the form (and thus the backing bean) was everything i needed to persist through the EJB layer, should i clone out all the attributes by hand into a transfer object, or is there a better way of doing this?
The backing bean though POJO is heavily annotated with JSF lifecycle tags (Such as #ManagedBean) and resides in the Web project while the EJBs reside separately in the EJB project.
It sounds like as if you've tight-coupled the model with the controller like as shown in most basic JSF tutorials. You should decouple the model from the controller into its own class. As you're using EJBs, the chance is big that you're also using JPA (how else would EJBs be really useful for persistence?), you can just use the existing JPA #Entity class as model.
E.g.
#Entity
public class Product {
#Id
private Long id;
private String name;
private String description;
private Category category;
// ...
}
with
#ManagedBean
#ViewScoped
public class ProductController {
private Product product;
#EJB
private ProductService service;
public void save() {
service.save(product);
}
// ...
}
which is to be used as
<h:form>
<h:inputText value="#{productController.product.name}" />
<h:inputTextarea value="#{productController.product.description}" />
<h:selectOneMenu value="#{productController.product.category}">
<f:selectItems value="#{applicationData.categories}" />
</h:selectOneMenu>
<h:commandButton value="Save" action="#{productController.save}" />
</h:form>
I was trying to do the same with CDI and the main diffrence (excluding using #Named instead of #ManagedBean) was that I had to initialize my transport object in the Controller class.
So instead of:
private Product product;
I had to use:
private Product product = new Product();
Maybe it will help someone :)

Resources