From 6d8610b98eb363c04d8915a65139ff2e0a22d539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vanesa=20Smo=C4=BEakov=C3=A1?= Date: Sun, 10 May 2026 01:09:47 +0200 Subject: [PATCH 1/2] MID-9998 Fix stale page recovery after view-source --- .../security/LoggingRequestCycleListener.java | 11 ++++- .../web/LoggingRequestCycleListenerTest.java | 43 +++++++++++++++++++ gui/admin-gui/testng-unit.xml | 1 + release-notes.adoc | 1 + 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 gui/admin-gui/src/test/java/com/evolveum/midpoint/web/LoggingRequestCycleListenerTest.java diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/LoggingRequestCycleListener.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/LoggingRequestCycleListener.java index b6e63e6eb9b..266992aeab0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/LoggingRequestCycleListener.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/LoggingRequestCycleListener.java @@ -9,6 +9,8 @@ import org.apache.wicket.Application; import org.apache.wicket.core.request.handler.PageProvider; import org.apache.wicket.core.request.handler.RenderPageRequestHandler; +import org.apache.wicket.core.request.handler.RenderPageRequestHandler.RedirectPolicy; +import org.apache.wicket.core.request.mapper.StalePageException; import org.apache.wicket.request.IRequestHandler; import org.apache.wicket.request.Url; import org.apache.wicket.request.component.IRequestablePage; @@ -49,6 +51,14 @@ public IRequestHandler onException(RequestCycle cycle, Exception ex) { REQUEST_LOGGER.trace("REQUEST CYCLE: Exception: {}, handler {}", ex, WebComponentUtil.debugHandler(cycle.getActiveRequestHandler()), ex); } + if (ex instanceof StalePageException stalePageException) { + // Wicket uses this exception for stale render-count recovery, e.g. after browser view-source. + // Do not convert it to PageError/500, recover by re-rendering the stale page. + LOGGER.debug("Recovering stale Wicket page request by re-rendering page {}", stalePageException.getPage()); + return new RenderPageRequestHandler( + new PageProvider(stalePageException.getPage()), + RedirectPolicy.ALWAYS_REDIRECT); + } LoggingUtils.logUnexpectedException(LOGGER, "Error occurred during page rendering", ex); return new RenderPageRequestHandler(new PageProvider(new PageError(ex))); } @@ -136,4 +146,3 @@ public void onUrlMapped(RequestCycle cycle, IRequestHandler handler, Url url) { } } } - diff --git a/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/LoggingRequestCycleListenerTest.java b/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/LoggingRequestCycleListenerTest.java new file mode 100644 index 00000000000..f6cfa0e7f3b --- /dev/null +++ b/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/LoggingRequestCycleListenerTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010-2026 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.web; + +import com.evolveum.midpoint.web.security.LoggingRequestCycleListener; +import org.apache.wicket.core.request.handler.RenderPageRequestHandler; +import org.apache.wicket.core.request.handler.RenderPageRequestHandler.RedirectPolicy; +import org.apache.wicket.core.request.mapper.StalePageException; +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.request.IRequestHandler; +import org.apache.wicket.util.tester.WicketTester; +import org.testng.Assert; +import org.testng.annotations.Test; + +public class LoggingRequestCycleListenerTest { + + @Test + public void testStalePageExceptionIsRecoveredInsteadOfConvertedToPageError() { + WicketTester tester = new WicketTester(); + try { + LoggingRequestCycleListener listener = new LoggingRequestCycleListener(tester.getApplication()); + TestPage page = new TestPage(); + + IRequestHandler handler = listener.onException(null, new StalePageException(page)); + + Assert.assertTrue(handler instanceof RenderPageRequestHandler); + + RenderPageRequestHandler renderHandler = (RenderPageRequestHandler) handler; + Assert.assertSame(renderHandler.getPage(), page); + Assert.assertSame(renderHandler.getRedirectPolicy(), RedirectPolicy.ALWAYS_REDIRECT); + } finally { + tester.destroy(); + } + } + + private static class TestPage extends WebPage { + } +} diff --git a/gui/admin-gui/testng-unit.xml b/gui/admin-gui/testng-unit.xml index 43012931e59..3a361644b9b 100644 --- a/gui/admin-gui/testng-unit.xml +++ b/gui/admin-gui/testng-unit.xml @@ -13,6 +13,7 @@ + diff --git a/release-notes.adoc b/release-notes.adoc index eec0f0a89cf..c16e9249b10 100644 --- a/release-notes.adoc +++ b/release-notes.adoc @@ -137,6 +137,7 @@ Overall, midPoint 4.10 opens up the world of identity management and governance * Fixed skipped approval processing for role ADD operations that could leave empty ADD deltas. See bug:MID-11101[] * Fixed loss of unsaved resource detail changes after running Test connection. See bug:MID-10966[] * Fixed dashboard widget collections with inline filters by allowing explicit object type specification. See bug:MID-9879[] +* Fixed stale page recovery after viewing page source causing internal server error. See bug:MID-9998[] === Releases Of Other Components From 4c6d66340629f2b1fa4847289604f024e888e898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vanesa=20Smo=C4=BEakov=C3=A1?= Date: Wed, 10 Jun 2026 10:02:29 +0200 Subject: [PATCH 2/2] MID-9998 Add test comments --- .../midpoint/web/LoggingRequestCycleListenerTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/LoggingRequestCycleListenerTest.java b/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/LoggingRequestCycleListenerTest.java index f6cfa0e7f3b..9df959f9e3f 100644 --- a/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/LoggingRequestCycleListenerTest.java +++ b/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/LoggingRequestCycleListenerTest.java @@ -17,8 +17,16 @@ import org.testng.Assert; import org.testng.annotations.Test; +/** + * Tests exception handling behavior in {@link LoggingRequestCycleListener}. + */ public class LoggingRequestCycleListenerTest { + /** + * MID-9998: Verifies that Wicket stale page recovery, e.g. after browser + * view-source, is handled by re-rendering the stale page instead of being + * converted to the error page / HTTP 500. + */ @Test public void testStalePageExceptionIsRecoveredInsteadOfConvertedToPageError() { WicketTester tester = new WicketTester();