Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
None
-
None
Description
When AlertManager.alert is used during the rendering (such as from setupRender) of an ajax request, where the Alerts component is not rendered in the ajax request, the alert doesn't get shown on that request but on the next one (respectively when the Alerts component is rendered the next time).
The use case where this problem was found is when components that render inside a progressive display try to add alerts during rendering. A workaround is to catch the progressive display's event, and then delegate it to the embedded progressively-displayed component which wants to add the alert, so that it can add the alert before rendering. Another option is to completely decorate the AlertManager service with the fixed version below
The bug can easily be reproduced by including the following component inside an ajax-rendered zone (with the Alerts component outside of the zone):
public class AlertManagerAjaxRenderBugComponent
{
@Inject
private Request request;
@Inject
private AlertManager alertManager;
@SetupRender
void setupRender()
{
if (request.isXHR())
}
}
The reason is that in AlertManagerImpl the alerts are added with ajaxResponseRenderer.addCallback, which doesn't work when rendering has already begun. The proposed solution is to use the ajaxResponseRenderer before rendering, and the JavaScriptSupport from the environment during rendering.
The following change to the AlertManagerImpl fixes this problem:
private void addCallbackForAlert(final Alert alert)
{
JavaScriptCallback callback = new JavaScriptCallback()
{
public void run(JavaScriptSupport javascriptSupport)
};
// In order to support the creation of alerts both before and during rendering,
// run the callback against the appropriate service
final JavaScriptSupport javaScriptSupport = environment.peek(JavaScriptSupport.class);
if (javaScriptSupport != null)
else
{ ajaxResponseRenderer.addCallback(callback); } addAlertStorageCleanupCallback();
}
A similar problem exists for the cleanup of the alerts, which is not executed under these circumstances for the same reason. Use of the perThreadManager.addThreadCleanupListener instead fixes this problem.
The attached patch contains both these fixes.