We have a page that contains a command link:
<h:commandLink value="Go to Result Manager"
action="#{resultManagerDashboardHelper.navigateToTargetAll()}" />
This is supposed to redirect to the Result Manager view, secretly passing a list of two status flags representing "TODO" and "DONE", so that the filter will be set to "all statuses".
ResultManagerDashboardHelper.java:
@Named
@ViewScoped
public class ResultManagerDashboardHelper
{
...
public static final String SECRET_ARGS_KEY = "secretArgs";
...
private String navigateToPage( String outcome, String... args )
{
List<String> argsList = Arrays.asList( args );
FacesContext.getCurrentInstance().getExternalContext().getFlash().put( SECRET_ARGS_KEY, argsList );
String fullOutcome = outcome + "?faces-redirect=true";
System.out.println( "Setting flash secret args to " + argsList );
System.out.println( "Redirecting from '" + this.outcomeMapper.getCurrentOutcome() + "' to '" + fullOutcome + "'" );
return fullOutcome;
}
private String navigateToTargetPage( String... args )
{
return this.navigateToPage( "/view/resultmgmt/resultManager", args );
}
public String navigateToTargetAll()
{
return this.navigateToTargetPage( "TODO", "DONE" );
}
}
ResultManagerFilterHandler.java:
@Named
@ViewScoped
public class ResultManagerFilterHandler
{
...
// status flags secretly coming in via Flash from dashboard
private List<String> secretStatusFlags;
@Override
@PostConstruct
public void init()
{
...
@SuppressWarnings( "unchecked" )
List<String> secretStatusFlags = ( List<String> ) FacesContext.getCurrentInstance().getExternalContext().getFlash().get( ResultManagerDashboardHelper.SECRET_ARGS_KEY );
if ( secretStatusFlags != null )
{
System.out.println( "ResultManagerFilterHandler secret arguments have arrived via JSF Flash! Size = " + secretStatusFlags.size() );
}
else
{
System.out.println( "ResultManagerFilterHandler: NO secret arguments have arrived via JSF Flash!" );
}
// sits in view scope waiting to be picked up by search routine in ResultManager (also view-scoped)
this.secretStatusFlags = secretStatusFlags;
}
}
ResultManager.java:
@Named
@ViewScoped
public class ResultManager
{
...
@Inject
private ResultManagerFilterHandler filterHandler;
@Override
public void searchInitially()
{
// get Flash object from filter handler
List<String> statusFlags = this.getFilterHandler().getSecretStatusFlags();
System.out.println( "ResultManager statusFlags = " + statusFlags );
// if flash args have been passed, prefer that view over the standard one
if ( statusFlags != null && !statusFlags.isEmpty() )
{
System.out.println( "Flash search!" );
// set to today and decrypt the passed status flags (this is supposed to override the default search filter!)
this.filterHandler.setSelectedPeriod( EPeriod.TODAY );
this.filterHandler.calculateBeginEndDates( this.filterHandler.getSelectedPeriod() );
this.filterHandler.setTodoOnly( statusFlags.size() == 1 && statusFlags.get( 0 ).equals( "TODO" ) );
this.search();
}
else
{
System.out.println( "Non-flash search!" );
super.searchInitially();
}
}
}
When clicking the aforementioned link, the browser is redirected to the correct view. Then an event on the resultManager.xhtml
page
<f:event type="preRenderView"
listener="#{resultManager.searchInitially}" />
calls the searchInitially
method, which is supposed to pick up the stored status flags from the ResultManagerFilterHandler
bean. However the Flash arguments aren't there:
18:58:42,840 INFO [] (134) Setting flash secret args to [TODO, DONE]
18:58:42,840 INFO [] (134) Redirecting from '/view/dashboard' to '/view/resultmgmt/resultManager?faces-redirect=true'
18:58:43,039 INFO [] (135) ResultManagerFilterHandler: NO secret arguments have arrived via JSF Flash!
18:58:44,350 INFO [] (135) ResultManager statusFlags = []
18:58:44,350 INFO [] (135) Non-flash search!
Q:
What am I doing wrong? How do I get it to work?
Note that ?faces-redirect=true
URL parameter isn't appended to the URL... I wonder why?? Might this be the reason for the empty flash? Or is it normal behavior?
We're using Mojarra 2.1.22, which is known to have some issues keeping Flash instances longer, but this is something I'd like to solve later.
PS: sorry for the complex example, in reality it is even more complex... :-/
PPS: oh and never mind the combination of @Named
and @ViewScoped
, we're using Seam 3, which replaces the JSF @ViewScoped
with a CDI-compatible one.