6

I have simply page to which is associated @RequestScoped backing bean. I get to this page from other page on which one I passed parameter "project". So when I get on right page I have url like contextRoot/faces/jsf.xhtml?project=123.

View:

<f:metadata>
    <f:viewParam name="project" value="#{entityBean.projectId}" />
</f:metadata>       
...
<p:commandButton value="#{msg['button.add']}"
    actionListener="#{entityBean.addNewEntity((entityName),(entityDescritpion))}"
    ajax="true" update=":projectDetailForm"/>

Backing bean:

@Named("entityBean")
@RequestScoped
public class EntityBean implements Serializable{
    private String projectId;

    @PostConstruct
    public void init() {
        params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();

        for (Map.Entry<String, String> entry : params.entrySet()) {
            System.out.println(entry.getKey() + " / " + entry.getValue());
        }

        if (params.get("project") != null) {
            projectId = params.get("project");
        } else {
            HttpServletRequest request =
                (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
            String projectId = request.getParameter("project");
        }
    }

    //projectId getter and setter
    //public void addNewEntity(String name, String desc) {}
}

Everything works fine when the page is opened for the first time. The GET parameter is successfully processed. However, as the bean is request scoped, it is destroyed by end of request and recreated on the subsequent postback(s). During those postbacks, the GET parameter is not available anymore even though it is visible in the browser address bar. I tried three methods of getting parameter by f:viewParam and ExternalContext and even from ServletContext but I can't get those parameters.

I don't want to change @RequestScoped to @SessionsScoped and I can't use @ViewScoped, beacuse I'm using CDI beans and I don't want to mix them.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
AdrianX
  • 163
  • 1
  • 5
  • 17
  • change Scope of Bean from "Requested" to "View". – MRX Apr 24 '13 at 09:12
  • 1
    @kshitij: unfortunately, OP is using CDI instead of JSF to manage beans. So the JSF-specific view scope isn't going to work. The OP also explicitly mentioned it in the last sentence of the question. – BalusC Apr 24 '13 at 11:30

1 Answers1

10

You need the <f:param> in the UICommand component to retain request parameters for the subsequent request. E.g.

<p:commandButton ...>
    <f:param name="project" value="#{param.project}" />
</p:commandButton>

Alternatively, you can use the <o:form> of the JSF utility library OmniFaces, it basically extends the <h:form> with an additional attribute includeViewParams which enables you to retain request parameters registered via <f:viewParam> for the subsequent request.

<o:form includeViewParams="true">
    ...
</o:form>

This may end up to be easier if you have multiple command buttons/links and ajax actions.

The URL in browser address bar is in your case not changed because you're firing an ajax request. But the actual URL, which you can see in <form action> of the generated HTML output via rightclick - View Source in browser, does by default not contain the current GET parameters.


Unrelated to the concrete problem, with manually collecting the parameter in postconstruct, you're basically ignoring the usefulness and powers of the <f:viewParam>. I recommend to carefully go through the following answers to learn how to utilize them properly:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • To solved this problem I used Apache MyFaces CODI. It provides very useful extensions for CDI scopes like ViewAccessScoped. Wokrs fine with JSF 2.0 and Primefaces. – AdrianX Apr 24 '13 at 14:18
  • @AdrianX: Can also. It only leaves ugly `windowId` parameters in the URLs. Note that it also bridges JSF `@ViewScoped` transparently to CDI so that you can use `@Named @ViewScoped`. – BalusC Apr 24 '13 at 14:24