MarcelK
MarcelK

Reputation: 283

JSF/Primefaces - CommandButton: open new browser tab without ViewScoped bean getting killed

I'm trying to open a new browser tab with a JSF view (in a portlet, deployed in Liferay) from within a view backed by a ViewScoped bean. Using a normal action redirect kills the bean. I've tried the method provided here and here, but unfortunately without success.

The button looks more or less like this:

<p:commandButton value="#{msg.label}" onclick="target='_blank'" 
                 action="#{sessionScopedBean.action(param)}" ajax="false" />

Moving the target='_blank' to the form attribute did not help. I've tried both returning null and void with no success. Changing ajax to true broke the navigation, didn't open a new tab but also did not kill the ViewScoped bean.

The action method content looks like this:

public void action(String param) throws IOException {
   //some business logic

   FacesContext.getCurrentInstance().getExternalContext().redirect("viewName.xhtml");
}

The view does not contain tag handlers like <c:if test="..."> or <ui:include src="...">. It did contain a <ui:repeat id="..." value="#{viewScopedBean.collection}" var="..." varStatus="..."> tag, but removing it changed noting. The form is enclosed in <ui:composition> and <ui:define> tags.

The view I redirect to has no connection with the ViewScoped bean. Any ideas? :)

Upvotes: 3

Views: 11465

Answers (1)

BalusC
BalusC

Reputation: 1108732

The view scope broke because you're with the redirect action basically instructing the client to fire a brand new GET request on the given URL. You should instead be returning null or void and conditionally render the results in the same view.

See also:


The solution was already given in the links you found: put the data of interest in the flash scope before redirect and obtain them from the flash scope in the bean associated with target view. If this isn't working for you for some reason, an alternative would be to generate an unique key (java.util.UUID maybe?) and store it in the session scope as key associated with some data you'd like to retain in the redirected request,

String key = UUID.randomUUID().toString();
externalContext.getSessionMap().put(key, data);

and then pass that key along as request parameter in the redirect URL

externalContext.redirect("nextview.xhtml?key=" + key);

so that you can in the postconstruct of the bean associated with the target view obtain the data:

String key = externalContext.getRequestParameterMap().get("key");
Data data = (Data) externalContext.getSessionMap().remove(key);
// ...

Upvotes: 3

Related Questions