From df5bd9829bcda24f33bbbf8a88bcf9f462c82e85 Mon Sep 17 00:00:00 2001 From: Gonzalo Gallotti Date: Wed, 16 Mar 2022 19:04:17 -0300 Subject: [PATCH 1/4] Add GAM basic support. --- .../core/provider/AndroidLogger.java | 3 ++ .../com/genexus/diagnostics/core/ILogger.java | 6 +-- .../serverless/aws/AwsGxServletResponse.java | 21 ++++++++ .../aws/GxAwsProxyHttpServletRequest.java | 19 +++++++ .../cloud/serverless/aws/LambdaHandler.java | 50 +++++++++++++------ .../core/provider/Log4J2Logger.java | 4 +- 6 files changed, 83 insertions(+), 20 deletions(-) create mode 100644 gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/AwsGxServletResponse.java create mode 100644 gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/GxAwsProxyHttpServletRequest.java diff --git a/android/src/main/java/com/genexus/diagnostics/core/provider/AndroidLogger.java b/android/src/main/java/com/genexus/diagnostics/core/provider/AndroidLogger.java index 238b71dc4..af0ee4d96 100644 --- a/android/src/main/java/com/genexus/diagnostics/core/provider/AndroidLogger.java +++ b/android/src/main/java/com/genexus/diagnostics/core/provider/AndroidLogger.java @@ -159,4 +159,7 @@ public void trace(String msg, Throwable ex) { AndroidLog.debug(msg); } + public boolean isDebugEnabled() { + return true; + } } diff --git a/common/src/main/java/com/genexus/diagnostics/core/ILogger.java b/common/src/main/java/com/genexus/diagnostics/core/ILogger.java index 606128d4b..dc8f1ce48 100644 --- a/common/src/main/java/com/genexus/diagnostics/core/ILogger.java +++ b/common/src/main/java/com/genexus/diagnostics/core/ILogger.java @@ -43,8 +43,7 @@ public interface ILogger { void info(String[] list); void info(String msg); - - + void trace(String msg); void trace(Throwable ex, String[] list); @@ -55,7 +54,8 @@ public interface ILogger { void trace(String msg, Throwable ex); - + boolean isDebugEnabled(); + // Lambda Functions not supported JAVA 7. Only Java 8. /* * public static void debug(Logger log, String startMsg, Func buildMsg) diff --git a/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/AwsGxServletResponse.java b/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/AwsGxServletResponse.java new file mode 100644 index 000000000..1a043d986 --- /dev/null +++ b/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/AwsGxServletResponse.java @@ -0,0 +1,21 @@ +package com.genexus.cloud.serverless.aws; + +import com.amazonaws.serverless.proxy.model.AwsProxyResponse; + +public class AwsGxServletResponse { + private AwsProxyResponse response; + + public AwsGxServletResponse(AwsProxyResponse response){ + this.response = response; + } + public AwsGxServletResponse(){ + } + + public boolean wasHandled(){ + return response != null; + } + + public AwsProxyResponse getAwsProxyResponse() { + return response; + } +} diff --git a/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/GxAwsProxyHttpServletRequest.java b/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/GxAwsProxyHttpServletRequest.java new file mode 100644 index 000000000..f807b5da1 --- /dev/null +++ b/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/GxAwsProxyHttpServletRequest.java @@ -0,0 +1,19 @@ +package com.genexus.cloud.serverless.aws; + +import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletRequest; +import com.amazonaws.serverless.proxy.model.AwsProxyRequest; +import com.amazonaws.serverless.proxy.model.ContainerConfig; +import com.amazonaws.services.lambda.runtime.Context; + +import javax.ws.rs.core.SecurityContext; + +public class GxAwsProxyHttpServletRequest extends AwsProxyHttpServletRequest { + + public GxAwsProxyHttpServletRequest(AwsProxyRequest awsProxyRequest, Context lambdaContext, SecurityContext awsSecurityContext) { + super(awsProxyRequest, lambdaContext, awsSecurityContext); + } + + public GxAwsProxyHttpServletRequest(AwsProxyRequest awsProxyRequest, Context lambdaContext, SecurityContext awsSecurityContext, ContainerConfig config) { + super(awsProxyRequest, lambdaContext, awsSecurityContext, config); + } +} diff --git a/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/LambdaHandler.java b/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/LambdaHandler.java index 9a3b6ef5c..400b24dd8 100644 --- a/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/LambdaHandler.java +++ b/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/LambdaHandler.java @@ -4,13 +4,13 @@ import javax.servlet.ServletContext; import javax.ws.rs.core.Application; +import com.amazonaws.serverless.proxy.RequestReader; import com.amazonaws.serverless.proxy.internal.servlet.AwsHttpServletResponse; import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletRequest; import com.amazonaws.serverless.proxy.internal.servlet.AwsServletContext; import com.amazonaws.serverless.proxy.model.MultiValuedTreeMap; import com.genexus.specific.java.LogManager; import com.genexus.webpanels.GXWebObjectStub; -import org.apache.logging.log4j.Logger; import org.glassfish.jersey.server.ResourceConfig; import com.amazonaws.serverless.proxy.jersey.JerseyLambdaContainerHandler; @@ -48,28 +48,44 @@ public LambdaHandler() throws Exception { } } - @Override public AwsProxyResponse handleRequest(AwsProxyRequest awsProxyRequest, Context context) { - dumpRequest(awsProxyRequest); + if (logger.isDebugEnabled()) { + dumpRequest(awsProxyRequest); + } String path = awsProxyRequest.getPath(); - awsProxyRequest.setPath(path.replace(BASE_REST_PATH, "/")); - handleSpecialMethods(awsProxyRequest); + prepareSpecialMethods(awsProxyRequest); dumpRequest(awsProxyRequest); logger.debug("Before handle Request"); - AwsProxyResponse response = this.handler.proxy(awsProxyRequest, context); + AwsProxyResponse response = null; + + awsProxyRequest.setPath(path.replace(BASE_REST_PATH, "/")); + response = this.handler.proxy(awsProxyRequest, context); + + //This code should be removed when GAM services get implemented via API Object. + if (response.getStatusCode() == 404) { + awsProxyRequest.setPath(path); + logger.debug("Trying servlet request: " + path); + AwsGxServletResponse servletResponse = handleServletRequest(awsProxyRequest, context); + if (servletResponse.wasHandled()){ + response = servletResponse.getAwsProxyResponse(); + } + } + int statusCode = response.getStatusCode(); logger.debug("After handle Request - Status Code: " + statusCode); - if (statusCode >= 400 && statusCode <= 599) { + if (statusCode >= 404 && statusCode <= 499) { logger.warn(String.format("Request could not be handled (%d): %s", response.getStatusCode(), path)); } return response; } - private void handleSpecialMethods(AwsProxyRequest awsProxyRequest) { - if (awsProxyRequest.getPath().startsWith("/gxmulticall")) { //Gxmulticall does not respect queryString standard, so we need to transform. + private void prepareSpecialMethods(AwsProxyRequest awsProxyRequest) { + String path = awsProxyRequest.getPath(); + + if (path.startsWith("/gxmulticall")) { //Gxmulticall does not respect queryString standard, so we need to transform. String parmValue = awsProxyRequest.getQueryString().replace("?", "").replace("=", ""); MultiValuedTreeMap qString = new MultiValuedTreeMap<>(); qString.add("", parmValue); @@ -86,13 +102,14 @@ private void handleSpecialMethods(AwsProxyRequest awsProxyRequest) { } } - private AwsProxyResponse handleServletRequest(AwsProxyRequest awsProxyRequest, Context context) { + private AwsGxServletResponse handleServletRequest(AwsProxyRequest awsProxyRequest, Context context) { try { GXWebObjectStub servlet = resolveServlet(awsProxyRequest); if (servlet != null) { CountDownLatch latch = new CountDownLatch(0); - ServletContext servletContext = new AwsServletContext(null);//AwsServletContext.getInstance(lambdaContext, null); + ServletContext servletContext = new AwsServletContext(null); AwsProxyHttpServletRequest servletRequest = new AwsProxyHttpServletRequest(awsProxyRequest, context, null); + servletRequest.setAttribute(RequestReader.API_GATEWAY_CONTEXT_PROPERTY, awsProxyRequest.getRequestContext()); servlet.init(new ServletConfig() { @Override public String getServletName() { @@ -117,14 +134,14 @@ public Enumeration getInitParameterNames() { AwsHttpServletResponse response = new AwsHttpServletResponse(servletRequest, latch); servletRequest.setServletContext(servletContext); servlet.service(servletRequest, response); - return new AwsProxyHttpServletResponseWriter().writeResponse(response, context); + return new AwsGxServletResponse(new AwsProxyHttpServletResponseWriter().writeResponse(response, context)); } else { - return new AwsProxyResponse(404); + return new AwsGxServletResponse(new AwsProxyResponse(404)); } } catch (Exception e) { logger.error("Error processing servlet request", e); } - return new AwsProxyResponse(500); + return new AwsGxServletResponse(); } private GXWebObjectStub resolveServlet(AwsProxyRequest awsProxyRequest) { @@ -142,7 +159,7 @@ private GXWebObjectStub resolveServlet(AwsProxyRequest awsProxyRequest) { handler = new GXOAuthUserInfo(); break; default: - logger.error("Could not handle Servlet Path: " + path); + logger.debug("Could not handle Servlet Path: " + path); } return handler; } @@ -174,4 +191,5 @@ private void dumpRequest(AwsProxyRequest awsProxyRequest){ reqData += String.format("Body: %sn", awsProxyRequest.getBody()) + lineSeparator; logger.debug(reqData); } -} \ No newline at end of file +} + diff --git a/wrappercommon/src/main/java/com/genexus/diagnostics/core/provider/Log4J2Logger.java b/wrappercommon/src/main/java/com/genexus/diagnostics/core/provider/Log4J2Logger.java index 7c8821ca8..c0d2d7b7f 100644 --- a/wrappercommon/src/main/java/com/genexus/diagnostics/core/provider/Log4J2Logger.java +++ b/wrappercommon/src/main/java/com/genexus/diagnostics/core/provider/Log4J2Logger.java @@ -216,6 +216,8 @@ public void trace(String msg, Throwable ex) { } } - + public boolean isDebugEnabled() { + return log.isDebugEnabled(); + } } From 52a85bae7925aa43e15055413e9def2b99c5447c Mon Sep 17 00:00:00 2001 From: Gonzalo Gallotti Date: Wed, 16 Mar 2022 19:13:46 -0300 Subject: [PATCH 2/4] Remove unnecesary class. --- .../aws/GxAwsProxyHttpServletRequest.java | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/GxAwsProxyHttpServletRequest.java diff --git a/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/GxAwsProxyHttpServletRequest.java b/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/GxAwsProxyHttpServletRequest.java deleted file mode 100644 index f807b5da1..000000000 --- a/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/GxAwsProxyHttpServletRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.genexus.cloud.serverless.aws; - -import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletRequest; -import com.amazonaws.serverless.proxy.model.AwsProxyRequest; -import com.amazonaws.serverless.proxy.model.ContainerConfig; -import com.amazonaws.services.lambda.runtime.Context; - -import javax.ws.rs.core.SecurityContext; - -public class GxAwsProxyHttpServletRequest extends AwsProxyHttpServletRequest { - - public GxAwsProxyHttpServletRequest(AwsProxyRequest awsProxyRequest, Context lambdaContext, SecurityContext awsSecurityContext) { - super(awsProxyRequest, lambdaContext, awsSecurityContext); - } - - public GxAwsProxyHttpServletRequest(AwsProxyRequest awsProxyRequest, Context lambdaContext, SecurityContext awsSecurityContext, ContainerConfig config) { - super(awsProxyRequest, lambdaContext, awsSecurityContext, config); - } -} From 832324eb5ee7c8ab88b143feffcd94d26a946ed3 Mon Sep 17 00:00:00 2001 From: Gonzalo Gallotti Date: Wed, 16 Mar 2022 19:14:33 -0300 Subject: [PATCH 3/4] Minor improvement --- .../java/com/genexus/cloud/serverless/aws/LambdaHandler.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/LambdaHandler.java b/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/LambdaHandler.java index 400b24dd8..7bb2394a0 100644 --- a/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/LambdaHandler.java +++ b/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/LambdaHandler.java @@ -58,10 +58,9 @@ public AwsProxyResponse handleRequest(AwsProxyRequest awsProxyRequest, Context c dumpRequest(awsProxyRequest); logger.debug("Before handle Request"); - AwsProxyResponse response = null; - + awsProxyRequest.setPath(path.replace(BASE_REST_PATH, "/")); - response = this.handler.proxy(awsProxyRequest, context); + AwsProxyResponse response = this.handler.proxy(awsProxyRequest, context); //This code should be removed when GAM services get implemented via API Object. if (response.getStatusCode() == 404) { From 580496083f6959211eb689c5b91826190e74e8d9 Mon Sep 17 00:00:00 2001 From: Gonzalo Gallotti Date: Thu, 31 Mar 2022 11:07:55 -0300 Subject: [PATCH 4/4] Fix broken after ENVVars changes. Support for empty package Names. Remove deprecated code. --- .../com/genexus/cloud/serverless/aws/LambdaHandler.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/LambdaHandler.java b/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/LambdaHandler.java index 7bb2394a0..c782c76d4 100644 --- a/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/LambdaHandler.java +++ b/gxawsserverless/src/main/java/com/genexus/cloud/serverless/aws/LambdaHandler.java @@ -9,6 +9,7 @@ import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletRequest; import com.amazonaws.serverless.proxy.internal.servlet.AwsServletContext; import com.amazonaws.serverless.proxy.model.MultiValuedTreeMap; +import com.genexus.specific.java.Connect; import com.genexus.specific.java.LogManager; import com.genexus.webpanels.GXWebObjectStub; import org.glassfish.jersey.server.ResourceConfig; @@ -34,6 +35,7 @@ public class LambdaHandler implements RequestHandler handler = null; private static ResourceConfig jerseyApplication = null; private static final String BASE_REST_PATH = "/rest/"; + private static final String GX_APPLICATION_CLASS = "GXApplication"; public LambdaHandler() throws Exception { if (LambdaHandler.jerseyApplication == null) { @@ -165,12 +167,13 @@ private GXWebObjectStub resolveServlet(AwsProxyRequest awsProxyRequest) { private static Application initialize() throws Exception { logger = LogManager.initialize(".", LambdaHandler.class); + Connect.init(); IniFile config = com.genexus.ConfigFileFinder.getConfigFile(null, "client.cfg", null); String className = config.getProperty("Client", "PACKAGE", null); Class cls; try { - cls = Class.forName(className + ".GXApplication"); - Application app = (Application) cls.newInstance(); + cls = Class.forName(className.isEmpty() ? GX_APPLICATION_CLASS: String.format("%s.%s", className, GX_APPLICATION_CLASS)); + Application app = (Application) cls.getDeclaredConstructor().newInstance(); ApplicationContext appContext = ApplicationContext.getInstance(); appContext.setServletEngine(true); appContext.setServletEngineDefaultPath("");