Question

I have a facelet template with:

<f:metadata>
    <o:viewParam name="id" value="#{homeBean.id}" />
</f:metadata>                

<h:form>
    <h:inputHidden value="#{homeBean.id}" />
    <h:inputText value="#{homeBean.user.firstName}" />
    <h:commandButton value="Submit" action="#{homeBean.onSave()}" />
</h:form>

and a request scoped bean with:

@Named
@RequestScoped
public class HomeBean {
    private Integer id;
    private User user;

    public void setId(Integer id) {
      System.out.println("setId called");
      user = // code for loading User entity bean with supplied id
    }

    // other accessors for id and user
}

Initial page load works well, entity is loaded and displayed in a form, inputHidden is set to entity id. Problem is that submit throws:

javax.el.PropertyNotFoundException - Target unreachable, base expression '. user' resolved to null

probably because getUser is called before setId. How can I solve this? I really would like to have a request scoped bean, I know that this can be easily solved with at least viewaccess scoped bean.

EDIT: Now i noticed that exception is thrown in Process Validations phase, I initially thought that exception is thrown in Update Model Values phase. I changed "private User" to "private User user = new User()" and now it's OK, but it feels little weird.

Regards, Pavel

Was it helpful?

Solution

The OmniFaces <o:viewParam> sets the request parameter only in the initial request and not in postbacks. This is intented to be used with @ViewScoped beans so that the request parameter isn't unnecessarily been validated, converted and updated on every single postback (because it's already still present in a view scoped bean). The API documentation and the showcase example also explicitly mentions that it should be used with view scoped beans.

You've there however a request scoped bean which get trashed and recreated on every single request, also on postbacks to the same view. So the user property disappears and falls back to default null on every subsequent postback request.

There are basically 2 ways to fix it:

  1. Replace <o:viewParam> by <f:viewParam>. It will call the setter on every request, also on postbacks.

  2. Replace @Named @RequestScoped by @ManagedBean @ViewScoped, this way the bean will live as long as you're interacting with the same view. Or if you insist in using CDI, use @Named @ConversationScoped instead, but you have to manage the begin and end of the conversation yourself.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top