From dfdaac8151f568eaf3fd57f2481f0a03dd8313c9 Mon Sep 17 00:00:00 2001 From: Justin Johnson Date: Sat, 4 Jul 2026 15:37:34 -0500 Subject: [PATCH 1/3] commit fix mnjustin/hnr1#73 --- .../fuseless/CFMLLambdaContainerHandler.java | 2 +- .../fuseless/FuseLessExceptionHandler.java | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 java/src/main/java/com/foundeo/fuseless/FuseLessExceptionHandler.java diff --git a/java/src/main/java/com/foundeo/fuseless/CFMLLambdaContainerHandler.java b/java/src/main/java/com/foundeo/fuseless/CFMLLambdaContainerHandler.java index 2e4b131..c85f621 100644 --- a/java/src/main/java/com/foundeo/fuseless/CFMLLambdaContainerHandler.java +++ b/java/src/main/java/com/foundeo/fuseless/CFMLLambdaContainerHandler.java @@ -39,7 +39,7 @@ public static CFMLLambdaContainerHandler getA new AwsProxyHttpServletRequestReader(), new AwsProxyHttpServletResponseWriter(), new AwsProxySecurityContextWriter(), - new AwsProxyExceptionHandler() + new FuseLessExceptionHandler() ); newHandler.setLogFormatter(new ApacheCombinedServletLogFormatter<>()); diff --git a/java/src/main/java/com/foundeo/fuseless/FuseLessExceptionHandler.java b/java/src/main/java/com/foundeo/fuseless/FuseLessExceptionHandler.java new file mode 100644 index 0000000..7c8c6ba --- /dev/null +++ b/java/src/main/java/com/foundeo/fuseless/FuseLessExceptionHandler.java @@ -0,0 +1,35 @@ +package com.foundeo.fuseless; + +import com.amazonaws.serverless.proxy.AwsProxyExceptionHandler; +import com.amazonaws.serverless.proxy.model.AwsProxyResponse; +import com.amazonaws.serverless.proxy.model.Headers; + +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; + +/** + * The Lambda runtime interrupts the request-handling thread's CountDownLatch.await() as a + * transient signal (not a container shutdown - the next request on the same container succeeds + * normally). AwsProxyExceptionHandler's default handling of this returns a 502 with + * Content-Type: application/json, which browsers render as a raw JSON blob and which HTML-expecting + * clients (e.g. Cypress cy.visit()) reject outright. Override just this case to return HTML instead. + */ +public class FuseLessExceptionHandler extends AwsProxyExceptionHandler { + + private static final Headers HTML_HEADERS = new Headers(); + + static { + HTML_HEADERS.putSingle(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_HTML); + } + + @Override + public AwsProxyResponse handle(Throwable ex) { + if (ex instanceof InterruptedException) { + Thread.currentThread().interrupt(); // restore interrupt status + StreamLambdaHandler.log("Request interrupted by Lambda runtime", ex); + return new AwsProxyResponse(503, HTML_HEADERS, + "

Service temporarily unavailable. Please refresh the page.

"); + } + return super.handle(ex); + } +} From 1e63fa3d2e5da70f1e0204980dc0ceb5bc1fd90c Mon Sep 17 00:00:00 2001 From: Justin Johnson Date: Sat, 4 Jul 2026 11:00:17 -0500 Subject: [PATCH 2/3] Fix test.sh SAM local startup race condition in CI mnjustin/hnr1#65 --- test.sh | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/test.sh b/test.sh index 0cda4d7..69d2683 100755 --- a/test.sh +++ b/test.sh @@ -1,6 +1,6 @@ #!/bin/bash -if [[ !$LUCEE_VERSION ]]; then +if [[ -z "$LUCEE_VERSION" ]]; then LUCEE_VERSION=5.4.5.23 fi @@ -33,9 +33,19 @@ sam local start-api --port 3003 --debug & SAM_PID=$! -#give it a chance to startup -echo -e "Sleeping for 5...\n" -sleep 5 +echo "Waiting for SAM local to be ready..." +max_wait=60 +elapsed=0 +until curl -s -o /dev/null http://127.0.0.1:3003/ || [ $elapsed -ge $max_wait ]; do + sleep 2 + elapsed=$((elapsed + 2)) +done + +if [ $elapsed -ge $max_wait ]; then + echo "SAM local did not start within ${max_wait}s" + kill $SAM_PID + exit 1 +fi echo "Running: http://127.0.0.1:3003/assert.cfm" From 13cd9d6511fe9044e1312d1a595d1fcf13eaf112 Mon Sep 17 00:00:00 2001 From: Justin Johnson Date: Sat, 4 Jul 2026 18:33:45 -0500 Subject: [PATCH 3/3] lucee 7 upgrade mnjustin/hnr1#25 add fourth gradle build mnjustin/hnr1#25 --- java/build.gradle | 6 +- .../ApacheCombinedServletLogFormatter.java | 9 +-- .../fuseless/CFMLLambdaContainerHandler.java | 4 +- .../foundeo/fuseless/CFMLServletConfig.java | 4 +- .../fuseless/FuseLessExceptionHandler.java | 4 +- .../com/foundeo/fuseless/RequestWrapper.java | 4 +- .../fuseless/ServletContextWrapper.java | 70 ++++++++++++------- .../foundeo/fuseless/StreamLambdaHandler.java | 6 +- test.sh | 2 +- test/build.gradle | 6 +- 10 files changed, 67 insertions(+), 48 deletions(-) diff --git a/java/build.gradle b/java/build.gradle index d8892c4..509c20d 100644 --- a/java/build.gradle +++ b/java/build.gradle @@ -12,9 +12,9 @@ repositories { dependencies { implementation ( - 'com.amazonaws.serverless:aws-serverless-java-container-core:1.8.2', - 'javax.servlet.jsp:javax.servlet.jsp-api:2.3.1', - 'javax.el:javax.el-api:3.0.0', + 'com.amazonaws.serverless:aws-serverless-java-container-core:2.1.5', + 'jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.1.1', + 'jakarta.el:jakarta.el-api:5.0.1', 'com.amazonaws:aws-xray-recorder-sdk-core:2.15.3', 'com.amazonaws:aws-lambda-java-log4j2:1.6.0' ) diff --git a/java/src/main/java/com/foundeo/fuseless/ApacheCombinedServletLogFormatter.java b/java/src/main/java/com/foundeo/fuseless/ApacheCombinedServletLogFormatter.java index 625d160..2e3bc4c 100644 --- a/java/src/main/java/com/foundeo/fuseless/ApacheCombinedServletLogFormatter.java +++ b/java/src/main/java/com/foundeo/fuseless/ApacheCombinedServletLogFormatter.java @@ -5,10 +5,11 @@ import com.amazonaws.serverless.proxy.model.AwsProxyRequest; import com.amazonaws.serverless.proxy.model.AwsProxyRequestContext; +import com.amazonaws.serverless.proxy.model.RequestSource; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.SecurityContext; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.ws.rs.core.SecurityContext; import java.time.LocalDateTime; import java.time.ZoneId; @@ -78,7 +79,7 @@ public String format(ContainerRequestType servletRequest, ContainerResponseType logLineBuilder.append(" "); // %l - if (gatewayContext != null && req.getRequestSource() == AwsProxyRequest.RequestSource.API_GATEWAY) { + if (gatewayContext != null && req.getRequestSource() == RequestSource.API_GATEWAY) { if (gatewayContext.getIdentity().getUserArn() != null) { logLineBuilder.append(gatewayContext.getIdentity().getUserArn()); } else { diff --git a/java/src/main/java/com/foundeo/fuseless/CFMLLambdaContainerHandler.java b/java/src/main/java/com/foundeo/fuseless/CFMLLambdaContainerHandler.java index c85f621..94fc950 100644 --- a/java/src/main/java/com/foundeo/fuseless/CFMLLambdaContainerHandler.java +++ b/java/src/main/java/com/foundeo/fuseless/CFMLLambdaContainerHandler.java @@ -13,7 +13,7 @@ import com.amazonaws.xray.entities.Subsegment; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; @@ -71,7 +71,7 @@ protected AwsHttpServletResponse getContainerResponse(HttpServletRequest request protected void handleRequest(HttpServletRequest httpServletRequest, AwsHttpServletResponse httpServletResponse, Context lambdaContext) throws Exception { - RequestWrapper req = new RequestWrapper((javax.servlet.http.HttpServletRequest)httpServletRequest); + RequestWrapper req = new RequestWrapper((jakarta.servlet.http.HttpServletRequest)httpServletRequest); req.setAttribute("lambdaContext", lambdaContext); Object seg = null; try { diff --git a/java/src/main/java/com/foundeo/fuseless/CFMLServletConfig.java b/java/src/main/java/com/foundeo/fuseless/CFMLServletConfig.java index 76093b5..111b283 100644 --- a/java/src/main/java/com/foundeo/fuseless/CFMLServletConfig.java +++ b/java/src/main/java/com/foundeo/fuseless/CFMLServletConfig.java @@ -1,9 +1,9 @@ package com.foundeo.fuseless; -import javax.servlet.*; +import jakarta.servlet.*; import java.util.Enumeration; -public class CFMLServletConfig implements javax.servlet.ServletConfig { +public class CFMLServletConfig implements jakarta.servlet.ServletConfig { private ServletContext sc; public CFMLServletConfig(ServletContext servletContext) { diff --git a/java/src/main/java/com/foundeo/fuseless/FuseLessExceptionHandler.java b/java/src/main/java/com/foundeo/fuseless/FuseLessExceptionHandler.java index 7c8c6ba..394e982 100644 --- a/java/src/main/java/com/foundeo/fuseless/FuseLessExceptionHandler.java +++ b/java/src/main/java/com/foundeo/fuseless/FuseLessExceptionHandler.java @@ -4,8 +4,8 @@ import com.amazonaws.serverless.proxy.model.AwsProxyResponse; import com.amazonaws.serverless.proxy.model.Headers; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; /** * The Lambda runtime interrupts the request-handling thread's CountDownLatch.await() as a diff --git a/java/src/main/java/com/foundeo/fuseless/RequestWrapper.java b/java/src/main/java/com/foundeo/fuseless/RequestWrapper.java index 4ca1481..220b907 100644 --- a/java/src/main/java/com/foundeo/fuseless/RequestWrapper.java +++ b/java/src/main/java/com/foundeo/fuseless/RequestWrapper.java @@ -1,7 +1,7 @@ package com.foundeo.fuseless; -import javax.servlet.http.HttpServletRequestWrapper; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import jakarta.servlet.http.HttpServletRequest; public class RequestWrapper extends HttpServletRequestWrapper { diff --git a/java/src/main/java/com/foundeo/fuseless/ServletContextWrapper.java b/java/src/main/java/com/foundeo/fuseless/ServletContextWrapper.java index 5e8b79b..d7b088b 100644 --- a/java/src/main/java/com/foundeo/fuseless/ServletContextWrapper.java +++ b/java/src/main/java/com/foundeo/fuseless/ServletContextWrapper.java @@ -1,7 +1,7 @@ package com.foundeo.fuseless; -import javax.servlet.*; -import javax.servlet.descriptor.JspConfigDescriptor; +import jakarta.servlet.*; +import jakarta.servlet.descriptor.JspConfigDescriptor; import java.io.InputStream; import java.net.MalformedURLException; @@ -85,35 +85,11 @@ public RequestDispatcher getNamedDispatcher(String name) { return this.servletContext.getNamedDispatcher(name); } - @Override - @Deprecated - public Servlet getServlet(String name) throws ServletException { - return this.servletContext.getServlet(name); - } - - @Override - @Deprecated - public Enumeration getServlets() { - return this.servletContext.getServlets(); - } - - @Override - @Deprecated - public Enumeration getServletNames() { - return this.servletContext.getServletNames(); - } - @Override public void log(String msg) { this.servletContext.log(msg); } - @Override - @Deprecated - public void log(Exception exception, String msg) { - this.servletContext.log(exception, msg); - } - @Override public void log(String msg, Throwable throwable) { this.servletContext.log(msg, throwable); @@ -193,6 +169,12 @@ public ServletRegistration.Dynamic addServlet(String s, Class } + @Override + public ServletRegistration.Dynamic addJspFile(String s, String s1) { + return this.servletContext.addJspFile(s, s1); + } + + @Override public T createServlet(Class aClass) throws ServletException { return this.servletContext.createServlet(aClass); @@ -320,4 +302,40 @@ public String getVirtualServerName() { } + @Override + public int getSessionTimeout() { + return this.servletContext.getSessionTimeout(); + } + + + @Override + public void setSessionTimeout(int sessionTimeout) { + this.servletContext.setSessionTimeout(sessionTimeout); + } + + + @Override + public String getRequestCharacterEncoding() { + return this.servletContext.getRequestCharacterEncoding(); + } + + + @Override + public void setRequestCharacterEncoding(String encoding) { + this.servletContext.setRequestCharacterEncoding(encoding); + } + + + @Override + public String getResponseCharacterEncoding() { + return this.servletContext.getResponseCharacterEncoding(); + } + + + @Override + public void setResponseCharacterEncoding(String encoding) { + this.servletContext.setResponseCharacterEncoding(encoding); + } + + } diff --git a/java/src/main/java/com/foundeo/fuseless/StreamLambdaHandler.java b/java/src/main/java/com/foundeo/fuseless/StreamLambdaHandler.java index 71d2a1d..0f043f8 100644 --- a/java/src/main/java/com/foundeo/fuseless/StreamLambdaHandler.java +++ b/java/src/main/java/com/foundeo/fuseless/StreamLambdaHandler.java @@ -5,7 +5,7 @@ import com.amazonaws.serverless.proxy.model.AwsProxyResponse; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import lucee.loader.servlet.CFMLServlet; +import lucee.loader.servlet.jakarta.CFMLServlet; import com.amazonaws.services.lambda.runtime.LambdaRuntime; import com.amazonaws.services.lambda.runtime.LambdaLogger; @@ -13,8 +13,8 @@ import java.lang.StringBuilder; -import javax.servlet.ServletConfig; -import javax.servlet.http.HttpServlet; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.http.HttpServlet; import java.io.*; public class StreamLambdaHandler implements RequestStreamHandler { diff --git a/test.sh b/test.sh index 69d2683..7a91f06 100755 --- a/test.sh +++ b/test.sh @@ -1,7 +1,7 @@ #!/bin/bash if [[ -z "$LUCEE_VERSION" ]]; then - LUCEE_VERSION=5.4.5.23 + LUCEE_VERSION=7.0.4.34 fi if [ -f "java/jars/lucee-light-$LUCEE_VERSION.jar" ]; then diff --git a/test/build.gradle b/test/build.gradle index 351e239..ef3de9c 100644 --- a/test/build.gradle +++ b/test/build.gradle @@ -6,9 +6,9 @@ repositories { dependencies { implementation ( - 'com.amazonaws.serverless:aws-serverless-java-container-core:1.8.2', - 'javax.servlet.jsp:javax.servlet.jsp-api:2.3.1', - 'javax.el:javax.el-api:3.0.0', + 'com.amazonaws.serverless:aws-serverless-java-container-core:2.1.5', + 'jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.1.1', + 'jakarta.el:jakarta.el-api:5.0.1', 'com.amazonaws:aws-lambda-java-core:1.2.3', 'com.amazonaws:aws-lambda-java-log4j2:1.6.0' )