Skip to content

Commit 191ddb8

Browse files
committed
use cfadmin restart instead of updateRHExtension to trigger reflection fallback
1 parent 8f651f5 commit 191ddb8

4 files changed

Lines changed: 110 additions & 77 deletions

File tree

.github/workflows/main.yml

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -486,11 +486,37 @@ jobs:
486486
echo "CONFIG_OVERRIDE_FAILED=true" >> $GITHUB_OUTPUT
487487
fi
488488
489-
- name: Run reflection hot-reinstall test
489+
- name: Trigger Lucee engine restart (LDEV-6221 scenario)
490+
id: restart-trigger
491+
continue-on-error: true
492+
run: |
493+
# Calls cfadmin action="restart" — reloads the CFMLEngine while Tomcat
494+
# stays up. Forces the fresh extension to hit its reflection fallback
495+
# because Tomcat's endpoint registry still has the pre-restart class.
496+
RESPONSE=$(curl -s -w "\n%{http_code}" http://localhost:8888/tests/integration/trigger-lucee-restart.cfm)
497+
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
498+
BODY=$(echo "$RESPONSE" | sed '$d')
499+
echo "$BODY"
500+
if [ "$HTTP_CODE" != "200" ] || echo "$BODY" | grep -q "FAILED"; then
501+
echo "RESTART_TRIGGER_FAILED=true" >> $GITHUB_OUTPUT
502+
fi
503+
504+
- name: Wait for Lucee to come back online
505+
run: |
506+
# Engine restart takes a few seconds — poll a trivial endpoint until 200
507+
for i in {1..60}; do
508+
if curl -s -o /dev/null -w "%{http_code}" http://localhost:8888/tests/test-websocket-info.cfm | grep -q "200"; then
509+
echo "Lucee responding after $i attempts"
510+
break
511+
fi
512+
sleep 1
513+
done
514+
515+
- name: Run post-restart reflection round-trip
490516
id: reflection-test
491517
continue-on-error: true
492518
run: |
493-
RESPONSE=$(curl -s -w "\n%{http_code}" http://localhost:8888/tests/integration/test-reflection-reinstall.cfm)
519+
RESPONSE=$(curl -s -w "\n%{http_code}" http://localhost:8888/tests/integration/test-reflection-restart.cfm)
494520
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
495521
BODY=$(echo "$RESPONSE" | sed '$d')
496522
echo "$BODY"

tests/integration/test-reflection-reinstall.cfm

Lines changed: 0 additions & 75 deletions
This file was deleted.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<cfscript>
2+
// Post-restart round-trip. Assumes Lucee has already been restarted via
3+
// trigger-lucee-restart.cfm — the CI job orders these correctly and polls
4+
// for the engine to come back before calling this.
5+
//
6+
// Proves the websocket extension's reflection fallback works: Tomcat's endpoint
7+
// registry still points at the pre-restart class, but the fresh extension injected
8+
// itself into the static slot via reflection. A successful round-trip confirms the
9+
// path works; the CI job separately greps catalina.out for the reflection warning
10+
// to prove the path was actually exercised.
11+
12+
writeOutput( "=== Post-Restart Reflection Round-Trip ===" & chr( 10 ) );
13+
14+
try {
15+
if ( !structKeyExists( getFunctionList(), "CreateWebSocketClient" ) )
16+
throw( message="CreateWebSocketClient not available", type="TestSetupError" );
17+
18+
wsUrl = "ws://localhost:8888/ws/TestListener";
19+
listener = new tests.integration.ClientListener();
20+
ws = CreateWebSocketClient( wsUrl, listener );
21+
sleep( 500 );
22+
23+
ws.sendText( "reflectionCheck" );
24+
sleep( 500 );
25+
26+
ws.disconnect();
27+
sleep( 500 );
28+
29+
received = listener.getMessages();
30+
writeOutput( "Received: " & received.toJSON() & chr( 10 ) );
31+
32+
errors = [];
33+
if ( !received.find( "ECHO:reflectionCheck" ) )
34+
arrayAppend( errors, "expected ECHO:reflectionCheck post-restart; got: " & received.toJSON() );
35+
36+
if ( arrayLen( errors ) ) {
37+
writeOutput( chr( 10 ) & "FAILED:" & chr( 10 ) );
38+
for ( err in errors )
39+
writeOutput( " - #err#" & chr( 10 ) );
40+
cfheader( statuscode=500, statustext="Test Failed" );
41+
}
42+
else {
43+
writeOutput( chr( 10 ) & "SUCCESS: round-trip works post-restart — CI will confirm the reflection warning in catalina.out" & chr( 10 ) );
44+
}
45+
}
46+
catch ( any e ) {
47+
writeOutput( "FAILED with exception:" & chr( 10 ) );
48+
writeOutput( e.stacktrace );
49+
cfheader( statuscode=500, statustext="Test Failed" );
50+
}
51+
</cfscript>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<cfscript>
2+
// Triggers a Lucee engine restart via the server admin API.
3+
// Tomcat stays up — only the CFMLEngine reloads. This is the LDEV-6221 scenario:
4+
// when the fresh engine's extension classes try to register their endpoint, Tomcat
5+
// already has the endpoint class from before the restart, so the extension falls
6+
// back to inject() via reflection.
7+
//
8+
// The CI job curls this, then waits for Lucee to come back, then runs
9+
// test-reflection-restart.cfm which proves round-trip still works.
10+
11+
writeOutput( "=== Triggering Lucee engine restart ===" & chr( 10 ) );
12+
13+
try {
14+
adminPassword = server.system.environment.LUCEE_ADMIN_PASSWORD ?: "";
15+
if ( adminPassword == "" )
16+
throw( message="LUCEE_ADMIN_PASSWORD env var not set", type="TestSetupError" );
17+
18+
cfadmin(
19+
action = "restart",
20+
type = "server",
21+
password = adminPassword
22+
);
23+
24+
writeOutput( "Restart call returned — engine is reloading" & chr( 10 ) );
25+
}
26+
catch ( any e ) {
27+
writeOutput( "FAILED to trigger restart: " & e.message & chr( 10 ) );
28+
writeOutput( e.stacktrace );
29+
cfheader( statuscode=500, statustext="Restart Trigger Failed" );
30+
}
31+
</cfscript>

0 commit comments

Comments
 (0)