1

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

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Pavel Arnošt
  • 97
  • 2
  • 8

1 Answers1

1

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.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Hi Bauke, I tested my code with with Mojarra 2.1.10 and MyFaces 2.1.8. In Mojarra, f:viewParam behaves as you described. In MyFaces, setter is not called on postback, so f:viewParam works like o:viewParam there. O:viewParam can then be used to circumvent compatibility issues. I would like to use request scoped beans as much as possible. I had an idea that in edit form I will store entity id in hidden field and in setId setter I will load that entity and other components will store their values in Update Model Values into newly loaded entity. – Pavel Arnošt Jun 28 '12 at 21:56
  • Problem is that Process Validations phase requires object for conversion to find out what Converter should be used. I solved my problem with initilization of user object in declaration of HomeBean class - this empty object is used for converter detection and in Update Modes Values this object is replaced with entity loaded from database. – Pavel Arnošt Jun 28 '12 at 21:56