How this implementation works
This class is an application singleton. It has one ivar, innerMap. Entries are added to and removed from this map as needed according to how the flash scope is defined in the spec. This implementation never touches the session, nor does it cause the session to be created.
Most of the hairy logic is encapsulated with in the inner class PreviousNextFlashInfoManager. An instance of this class is obtained by calling one of the variants of getCurrentFlashManager(). When the instance is no longer needed for this request, call releaseCurrentFlashManager().
Two very important methods are getPhaseMapForWriting() and getPhaseMapForReading(). These methods are the basis for the Map implementation methods. Methods that need to write to the map use getPhaseMapForWriting(), those that need to read use getPhaseMapForReading(). These methods allow for the laziness that allows us to only incur a cost when the flash is actually written to.
The operation of this class is intimately tied to the request processing lifecycle. Let's break down every run thru the request processing lifecycle into two parts called "previous" and "next". We use the names "previous" and "next" to indicate the persistence and timing of the data that is stored in the flash. Consider two runs through the requset processing lifecle: N and N+1. On request N, there is no "previous" request. On Request N, any writes to the flash that happen during RENDER RESPONSE go to the "next" flash map. This means they are available for the ENTIRE run though the request processing lifecycle on request N+1. Any entries put into the "next" flash map on request N will be expired at the end of request N+1. Now, when we get into request N+1 what was considered "next" on request N, is now called "previous" from the perspective of request N+1. Any reads from the flash during request N+1 come from the "previous" map. Any writes to the flash before RENDER RESPONSE go to the "previous" map. Any writes to the flash during RENDER RESPNOSE go to the "next" map.
-
Nested Class Summary
-
Field Summary
Fields inherited from class jakarta.faces.context.Flash
NULL_VALUE
-
Method Summary
Modifier and TypeMethodDescriptionvoid
clear()
protected Object
clone()
boolean
containsKey
(Object key) boolean
containsValue
(Object value) void
doLastPhaseActions
(FacesContext context, boolean outgoingResponseIsRedirect) This is the most magic of methods.void
doPostPhaseActions
(FacesContext context) Called after the execution of every lifecycle phase, this method allows implementations to take the necessary actions to provide the Flash scope contract as it applies to the request procesing lifecycle.void
doPrePhaseActions
(FacesContext context) Called before the execution of every lifecycle phase, this method allows implementations to take the necessary actions to provide the Flash scope contract as it applies to the request procesing lifecycle.entrySet()
getFlash()
Returns the flashMap
for this application.boolean
isEmpty()
boolean
Return the value of this JavaBeans property for the flash for this session.boolean
Return the value of this property for the flash for this session.void
Causes a value stored with a previous call toFlash.putNow(java.lang.String, java.lang.Object)
, its Jakarta Expression Language equivalent, or to the requestMap
, to be promoted to the flash so that is available on the next traversal through the lifecycle on this session.keySet()
void
void
Puts a value in the flash so that it can be accessed on this traversal of the lifecycle, rather than on the next traversal.void
setKeepMessages
(boolean newValue) Setter forkeepMessages
JavaBeans property.void
setRedirect
(boolean newValue) Setting this property totrue
indicates that the next request on this session will be a redirect.int
size()
toString()
values()
Methods inherited from class java.lang.Object
equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
Methods inherited from interface java.util.Map
compute, computeIfAbsent, computeIfPresent, equals, forEach, getOrDefault, hashCode, merge, putIfAbsent, remove, replace, replace, replaceAll
-
Field Details
-
ACT_AS_DO_LAST_PHASE_ACTIONS
-
-
Method Details
-
getFlash
-
isKeepMessages
public boolean isKeepMessages()Description copied from class:Flash
Return the value of this JavaBeans property for the flash for this session. This value determines whether or not any
FacesMessage
instances queued in the currentFacesContext
must be preserved so they are accessible on the next traversal of the lifecycle on this session, regardless of the request being a redirect after post, or a normal postback.Map
accesses for the special key “keepMessages
” must return the value of this JavaBeans property.Jakarta Expression Language Usage Example
First page
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="jakarta.tags.core"> <!-- extra code removed --> <c:set target="#{flash}" property="keepMessages" value="true" />
Next page
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="jakarta.faces.html"> <!-- extra code removed --> <h:messages /> Any messages present on the first page must be displayed on this page.
- Specified by:
isKeepMessages
in classFlash
- Returns:
- the boolean flag whether keeping messages or not.
-
setKeepMessages
public void setKeepMessages(boolean newValue) Description copied from class:Flash
Setter for
keepMessages
JavaBeans property. SeeFlash.isKeepMessages()
.- Specified by:
setKeepMessages
in classFlash
- Parameters:
newValue
- the new value for this property on this session.
-
isRedirect
public boolean isRedirect()Description copied from class:Flash
Return the value of this property for the flash for this session. This must be
false
unless:-
Flash.setRedirect(boolean)
was called for the current lifecycle traversal withtrue
as the argument. -
The current lifecycle traversal for this session is in the “execute” phase and the previous traversal had
Flash.setRedirect(boolean)
called withtrue
as the argument.
- Specified by:
isRedirect
in classFlash
- Returns:
- the value of this property for the flash for this session.
-
-
setRedirect
public void setRedirect(boolean newValue) Description copied from class:Flash
Setting this property to
true
indicates that the next request on this session will be a redirect. Recall that on a redirect, the server sends a special response to the client instructing it to issue a new request to a specific URI. The implementation must insure that reading the value of this property on that request will returntrue
.Jakarta Expression Language Usage Example
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="jakarta.tags.core"> <!-- extra code removed --> <c:set target="#{flash}" property="redirect" value="true" />
- Specified by:
setRedirect
in classFlash
- Parameters:
newValue
- the new value for this property on this session.
-
get
-
put
-
remove
-
containsKey
-
containsValue
-
putAll
-
values
-
size
public int size() -
clear
public void clear() -
clone
- Overrides:
clone
in classObject
- Throws:
CloneNotSupportedException
-
entrySet
-
isEmpty
public boolean isEmpty() -
keySet
-
keep
Description copied from class:Flash
Causes a value stored with a previous call to
Flash.putNow(java.lang.String, java.lang.Object)
, its Jakarta Expression Language equivalent, or to the requestMap
, to be promoted to the flash so that is available on the next traversal through the lifecycle on this session.- Specified by:
keep
in classFlash
- Parameters:
key
- if argumentkey
is the name of an entry previously stored to the flash on this traversal through the lifecycle via a call toFlash.putNow(java.lang.String, java.lang.Object)
, or to a set to the EL expression#{flash.now.<key>}
, or to the requestMap
, to be promoted to the flash as if a call toput()
or a set to the expression#{flash.<key>}
was being called.
-
putNow
Description copied from class:Flash
Puts a value in the flash so that it can be accessed on this traversal of the lifecycle, rather than on the next traversal. This is simply an alias for putting a value in the request map.
Jakarta Expression Language Usage Example
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="jakarta.tags.core"> <!-- extra code removed --> <c:set target="#{flash.now}" property="bar" value="barValue" /> <p>Value of \#{flash.now.bar}, should be barValue.</p> <h:outputText value="#{flash.now.bar}" />
-
doPrePhaseActions
Description copied from class:Flash
Called before the execution of every lifecycle phase, this method allows implementations to take the necessary actions to provide the Flash scope contract as it applies to the request procesing lifecycle.
- Specified by:
doPrePhaseActions
in classFlash
- Parameters:
context
- theFacesContext
for this request.
-
doPostPhaseActions
Description copied from class:Flash
Called after the execution of every lifecycle phase, this method allows implementations to take the necessary actions to provide the Flash scope contract as it applies to the request procesing lifecycle.
- Specified by:
doPostPhaseActions
in classFlash
- Parameters:
context
- theFacesContext
for this request.
-
doLastPhaseActions
This is the most magic of methods. There are several scenarios in which this method can be called, but the first time it is called for a request it takes action, while on subsequent times it returns without taking action. This is due to the call to
releaseCurrentFlashManager(java.util.Map<java.lang.Object, java.lang.Object>)
. After this call, any calls togetCurrentFlashManager(java.util.Map<java.lang.Object, java.lang.Object>, boolean)
will return null.Scenario 1: normal request ending. This will be called after the RENDER_RESPONSE phase executes. outgoingResponseIsRedirect will be false.
Scenario 2: navigationHandler asks extContext for redirect. In this case, extContext calls this method directly, outgoingResponseIsRedirect will be true.
Scenario 3: extContext.flushBuffer(): As far as I can tell, this was only called in the JSP case, but it's good to call it from there anyway, because we need to write our cookie before the response is committed. outgoingResponseIsRedirect is false.
Scenario 4: after rendering the response in JSP, but before the buffer is flushed. In the JSP case, I've found this necessary because the call to extContext.flushBuffer() is too late, the response has already been committed by that point. outgoingResponseIsRedirect is false.
- Parameters:
context
- the involved faces contextoutgoingResponseIsRedirect
- whether outgoing response is redirect
-
toString
-