Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retain original GET request parameters across postbacks [duplicate]

Tags:

jsf

jsf-2

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.

like image 766
AdrianX Avatar asked Apr 24 '13 08:04

AdrianX


1 Answers

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:

  • What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
  • ViewParam vs @ManagedProperty(value = "#{param.id}")
like image 106
BalusC Avatar answered Oct 15 '22 11:10

BalusC