From 2ad941a5771f500c71303726920226bfb62ab26f Mon Sep 17 00:00:00 2001 From: iroqueta Date: Fri, 21 Jul 2023 11:08:35 -0300 Subject: [PATCH 01/15] Spring boot support in Java Generator First commit Issue: 103655 --- wrapperjakarta/pom.xml | 28 ++++++++++--------- .../com/genexus/GXRestServiceWrapper.java | 4 +++ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/wrapperjakarta/pom.xml b/wrapperjakarta/pom.xml index d657ad7c3..4ce5cd464 100644 --- a/wrapperjakarta/pom.xml +++ b/wrapperjakarta/pom.xml @@ -72,20 +72,19 @@ com.fasterxml.jackson.core jackson-annotations - ${jackson.version} + 2.15.2 com.fasterxml.jackson.core jackson-databind - ${jackson.version} + 2.15.2 - com.fasterxml.jackson.jaxrs - jackson-jaxrs-json-provider - 2.12.2 - jakarta + com.fasterxml.jackson.jakarta.rs + jackson-jakarta-rs-json-provider + 2.15.2 * @@ -95,23 +94,26 @@ - com.fasterxml.jackson.jaxrs - jackson-jaxrs-base - 2.12.2 - jakarta + com.fasterxml.jackson.jakarta.rs + jackson-jakarta-rs-base + 2.15.2 com.fasterxml.jackson.module - jackson-module-jaxb-annotations - 2.12.2 - jakarta + jackson-module-jakarta-xmlbind-annotations + 2.15.2 jakarta.annotation jakarta.annotation-api 2.0.0 + + org.springframework + spring-beans + 5.3.28 + diff --git a/wrapperjakarta/src/main/java/com/genexus/GXRestServiceWrapper.java b/wrapperjakarta/src/main/java/com/genexus/GXRestServiceWrapper.java index 68bb48850..09a96e1ba 100644 --- a/wrapperjakarta/src/main/java/com/genexus/GXRestServiceWrapper.java +++ b/wrapperjakarta/src/main/java/com/genexus/GXRestServiceWrapper.java @@ -10,16 +10,20 @@ import com.genexus.ws.rs.core.IUriInfo; import jakarta.ws.rs.core.Context; +import org.springframework.beans.factory.annotation.Autowired; public class GXRestServiceWrapper { @Context private jakarta.ws.rs.core.UriInfo uriInfo; @Context + @Autowired private jakarta.servlet.ServletContext myContext; @Context + @Autowired private jakarta.servlet.http.HttpServletRequest myServletRequest; @Context + @Autowired private jakarta.servlet.http.HttpServletResponse myServletResponse; protected IHttpServletRequest myServletRequestWrapper; From a858215ce7f0883bcd8d4699cb2b3c97938e6345 Mon Sep 17 00:00:00 2001 From: iroqueta Date: Tue, 25 Jul 2023 18:20:14 -0300 Subject: [PATCH 02/15] implements more REST interfaces in spring boot Issue: 103655 --- .../serverless/test/test_services_rest.java | 5 ++++- .../webpanels/GXObjectUploadServices.java | 20 +++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/gxawsserverless/src/test/java/com/gx/serverless/test/test_services_rest.java b/gxawsserverless/src/test/java/com/gx/serverless/test/test_services_rest.java index c4f40dcbe..daab02fcc 100644 --- a/gxawsserverless/src/test/java/com/gx/serverless/test/test_services_rest.java +++ b/gxawsserverless/src/test/java/com/gx/serverless/test/test_services_rest.java @@ -148,8 +148,11 @@ public javax.ws.rs.core.Response Upload( ) throws Exception super.init( "POST" ); try { - builder = new com.genexus.webpanels.GXObjectUploadServices().doInternalRestExecute(restHttpContext); + com.genexus.webpanels.GXObjectUploadServices gxObjectUpload = new com.genexus.webpanels.GXObjectUploadServices(); + String jsonResponse = gxObjectUpload.doInternalRestExecute(restHttpContext); cleanup(); + builder = com.genexus.ws.rs.core.Response.statusWrapped(201).entityWrapped(jsonResponse); + builder.header("GeneXus-Object-Id", gxObjectUpload.getKeyId()); return (javax.ws.rs.core.Response) builder.build() ; } catch ( Exception e ) diff --git a/java/src/main/java/com/genexus/webpanels/GXObjectUploadServices.java b/java/src/main/java/com/genexus/webpanels/GXObjectUploadServices.java index 09dca8cd0..0f1c42adb 100644 --- a/java/src/main/java/com/genexus/webpanels/GXObjectUploadServices.java +++ b/java/src/main/java/com/genexus/webpanels/GXObjectUploadServices.java @@ -6,7 +6,6 @@ import json.org.json.JSONArray; import json.org.json.JSONObject; -import com.genexus.ws.rs.core.*; import org.apache.commons.io.FilenameUtils; import java.io.InputStream; @@ -15,13 +14,21 @@ public class GXObjectUploadServices extends GXWebObjectStub { boolean isRestCall = false; - IResponseBuilder builder = null; - public IResponseBuilder doInternalRestExecute(HttpContext context) throws Exception + String keyId; + String jsonResponse = null; + + public String doInternalRestExecute(HttpContext context) throws Exception { isRestCall = true; doExecute(context); - return builder; + return jsonResponse; } + + public String getKeyId() + { + return keyId; + } + public void doInternalExecute(HttpContext context) throws Exception { doExecute(context); @@ -33,7 +40,6 @@ protected void doExecute(HttpContext context) throws Exception String ext = ""; WebApplicationStartup.init(com.genexus.Application.gxCfg, context); context.setStream(); - String keyId; try { String fileDirPath = Preferences.getDefaultPreferences().getPRIVATE_PATH(); @@ -102,9 +108,7 @@ protected void doExecute(HttpContext context) throws Exception context.getResponse().flushBuffer(); } else { - String jsonResponse = jObj.toString(); - builder = Response.statusWrapped(201).entityWrapped(jsonResponse); - builder.header("GeneXus-Object-Id", keyId); + jsonResponse = jObj.toString(); } if (!savedFileName.isEmpty()) { HttpUtils.CacheUploadFile(keyId, savedFileName, fileName, ext); From 59fb6bd001cefe8a56b4b4a5ed2fa8de284d23a7 Mon Sep 17 00:00:00 2001 From: iroqueta Date: Mon, 7 Aug 2023 13:47:01 -0300 Subject: [PATCH 03/15] Implements more REST interfaces in spring boot, error handling, GAM, execute command line, execute reorgs, model property to select Framework Now JDK 17 is needed to build standar classes Issue: 103655 --- .github/workflows/Build.yml | 2 +- common/pom.xml | 6 ++ .../java/com/genexus/ApplicationContext.java | 13 ++- .../main/java/com/genexus/xml/XMLReader.java | 20 +++- gxspringboot/pom.xml | 39 ++++++++ .../springboot/GAMServletsDefinition.java | 93 +++++++++++++++++++ .../springboot/GxSpringBootRestService.java | 22 +++++ pom.xml | 1 + 8 files changed, 193 insertions(+), 3 deletions(-) create mode 100644 gxspringboot/pom.xml create mode 100644 gxspringboot/src/main/java/com/genexus/springboot/GAMServletsDefinition.java create mode 100644 gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java diff --git a/.github/workflows/Build.yml b/.github/workflows/Build.yml index 228124cb0..e4d609055 100644 --- a/.github/workflows/Build.yml +++ b/.github/workflows/Build.yml @@ -38,7 +38,7 @@ jobs: - name: Setup Java JDK uses: actions/setup-java@v1.4.3 with: - java-version: 1.9 + java-version: 17 gpg-private-key: ${{ secrets.MAVEN_GPG_BUILDER_PRIVATE_KEY }} gpg-passphrase: MAVEN_GPG_PASSPHRASE diff --git a/common/pom.xml b/common/pom.xml index 2cc470bcb..a7912c539 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -19,6 +19,12 @@ xercesImpl 2.12.2 + + org.springframework + spring-core + 6.0.11 + provided + commons-codec commons-codec diff --git a/common/src/main/java/com/genexus/ApplicationContext.java b/common/src/main/java/com/genexus/ApplicationContext.java index 5248852b8..db0b35db2 100644 --- a/common/src/main/java/com/genexus/ApplicationContext.java +++ b/common/src/main/java/com/genexus/ApplicationContext.java @@ -14,7 +14,8 @@ public class ApplicationContext private boolean isGXUtility = false; private boolean isMsgsToUI = true ; private boolean isServletEngine = false; - private boolean isEJBEngine = false; + private boolean isSpringBootApp = false; + private boolean isEJBEngine = false; private boolean isDeveloperMenu = false; private static Object syncObject = new Object(); @@ -112,6 +113,16 @@ public boolean isServletEngine() return isServletEngine; } + public void setSpringBootApp(boolean isSpringBootApp) + { + this.isSpringBootApp = isSpringBootApp; + } + + public boolean isSpringBootApp() + { + return isSpringBootApp; + } + public void setEJBEngine(boolean isEJBEngine) { this.isEJBEngine = isEJBEngine; diff --git a/common/src/main/java/com/genexus/xml/XMLReader.java b/common/src/main/java/com/genexus/xml/XMLReader.java index b8511d9fe..85fab74e2 100644 --- a/common/src/main/java/com/genexus/xml/XMLReader.java +++ b/common/src/main/java/com/genexus/xml/XMLReader.java @@ -5,6 +5,7 @@ import java.io.*; import java.util.*; +import com.genexus.ApplicationContext; import org.apache.xerces.xni.QName; import org.apache.xerces.xni.XMLAttributes; import org.apache.xerces.xni.XMLDocumentHandler; @@ -30,6 +31,7 @@ import com.genexus.ResourceReader; import com.genexus.internet.IHttpRequest; import com.genexus.CommonUtil; +import org.springframework.core.io.ClassPathResource; public class XMLReader implements XMLDocumentHandler, XMLErrorHandler, XMLDTDHandler { @@ -770,7 +772,23 @@ public void open(String url) reset(); try { - inputSource = new XMLInputSource(null, url, null, new FileInputStream(new File(url)), null); + File xmlFile = new File(url); + if (ApplicationContext.getInstance().isSpringBootApp()) + { + ClassPathResource resource = new ClassPathResource(url); + if (resource.exists()) + xmlFile = resource.getFile(); + else + { + if (url.startsWith(ApplicationContext.getInstance().getServletEngineDefaultPath())) + { + resource = new ClassPathResource(url.replace(ApplicationContext.getInstance().getServletEngineDefaultPath(), "")); + if (resource.exists()) + xmlFile = resource.getFile(); + } + } + } + inputSource = new XMLInputSource(null, url, null, new FileInputStream(xmlFile), null); if (documentEncoding.length() > 0) inputSource.setEncoding(CommonUtil.normalizeEncodingName(documentEncoding)); parserConfiguration.setInputSource(inputSource); diff --git a/gxspringboot/pom.xml b/gxspringboot/pom.xml new file mode 100644 index 000000000..10c756fd6 --- /dev/null +++ b/gxspringboot/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + + com.genexus + parent + ${revision}${changelist} + + + gxspringboot + GeneXus Spring Boot + + + + ${project.groupId} + gxclassR + ${project.version} + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + org.springframework.boot + spring-boot-starter-web + 3.1.2 + provided + + + + + gxspringboot + + diff --git a/gxspringboot/src/main/java/com/genexus/springboot/GAMServletsDefinition.java b/gxspringboot/src/main/java/com/genexus/springboot/GAMServletsDefinition.java new file mode 100644 index 000000000..a79627db9 --- /dev/null +++ b/gxspringboot/src/main/java/com/genexus/springboot/GAMServletsDefinition.java @@ -0,0 +1,93 @@ +package com.genexus.springboot; +import java.lang.reflect.Constructor; +import jakarta.servlet.Servlet; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; + +public class GAMServletsDefinition { + @Bean + public ServletRegistrationBean gXOAuthAccessToken() { + return registerServletBean("com.genexus.webpanels.GXOAuthAccessToken", "/oauth/access_token"); + } + + @Bean + public ServletRegistrationBean gXOAuthLogout() { + return registerServletBean("com.genexus.webpanels.GXOAuthLogout", "/oauth/logout"); + } + + @Bean + public ServletRegistrationBean gXOAuthUserInfo() { + return registerServletBean("com.genexus.webpanels.GXOAuthUserInfo", "/oauth/userinfo"); + } + + @Bean + public ServletRegistrationBean gamOAuthSignIn() { + return registerServletBean("genexus.security.api.agamextauthinput", "/oauth/gam/signin"); + } + + @Bean + public ServletRegistrationBean gamOAuthCallback() { + return registerServletBean("genexus.security.api.agamextauthinput", "/oauth/gam/callback"); + } + + @Bean + public ServletRegistrationBean gamOAuthAccessToken() { + return registerServletBean("genexus.security.api.agamoauth20getaccesstoken", "/oauth/gam/access_token"); + } + + @Bean + public ServletRegistrationBean gamAccessTokenV2() { + return registerServletBean("genexus.security.api.agamoauth20getaccesstoken_v20", "/oauth/gam/v2.0/access_token"); + } + + @Bean + public ServletRegistrationBean gamOAuthUserInfo() { + return registerServletBean("genexus.security.api.agamoauth20getuserinfo", "/oauth/gam/userinfo"); + } + + @Bean + public ServletRegistrationBean oAuthUserInfoV2() { + return registerServletBean("genexus.security.api.agamoauth20getuserinfo_v20", "/oauth/gam/v2.0/userinfo"); + } + + @Bean + public ServletRegistrationBean oAuthSSORestV2() { + return registerServletBean("genexus.security.api.agamssorestrequesttokenanduserinfo_v20", "/oauth/gam/v2.0/requesttokenanduserinfo"); + } + + @Bean + public ServletRegistrationBean gamOAuthSignOut() { + return registerServletBean("genexus.security.api.agamextauthinput", "/oauth/gam/signout"); + } + + @Bean + public ServletRegistrationBean gamOAuthRequestTokenService() { + return registerServletBean("genexus.security.api.agamstsauthappgetaccesstoken", "/oauth/RequestTokenService"); + } + + @Bean + public ServletRegistrationBean gamOAuthQueryAccessToken() { + return registerServletBean("genexus.security.api.agamstsauthappvalidaccesstoken", "/oauth/QueryAccessToken"); + } + + /*@Bean + public ServletRegistrationBean gamSaml20SignOut() { + return registerServletBean("artech.security.saml.servlet.LOGOUT", "/saml/gam/signout"); + } + + @Bean + public ServletRegistrationBean gamSaml20SignIn() { + return registerServletBean("artech.security.saml.servlet.SSO", "/saml/gam/signin"); + }*/ + + private ServletRegistrationBean registerServletBean(String className, String path) { + try { + Constructor constructor = Class.forName(className).getConstructor(); + ServletRegistrationBean bean = new ServletRegistrationBean((Servlet) constructor.newInstance(), path); + return bean; + } + catch(Exception e) { + return null; + } + } +} diff --git a/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java b/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java new file mode 100644 index 000000000..e6fd517c4 --- /dev/null +++ b/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java @@ -0,0 +1,22 @@ +package com.genexus.springboot; + +import com.genexus.GxRestService; +import com.genexus.WrapperUtils; +import org.apache.logging.log4j.Logger; +import org.springframework.http.*; +import org.springframework.web.bind.annotation.*; +import org.springframework.http.converter.HttpMessageNotReadableException; + +abstract public class GxSpringBootRestService extends GxRestService { + private static Logger log = org.apache.logging.log4j.LogManager.getLogger(GxSpringBootRestService.class); + + @ExceptionHandler(HttpMessageNotReadableException.class) + protected ResponseEntity handleException(HttpMessageNotReadableException ex) { + log.error("Error executing REST service", ex); + + SetError("400", "Bad Request"); + ResponseEntity.BodyBuilder builder = ResponseEntity.status(HttpStatus.BAD_REQUEST); + builder.contentType(MediaType.APPLICATION_JSON); + return builder.body(errorJson.toString()) ; + } +} diff --git a/pom.xml b/pom.xml index a2cfc7d04..1bc290b70 100644 --- a/pom.xml +++ b/pom.xml @@ -82,6 +82,7 @@ common gxweb + gxspringboot wrapperjavax wrapperjakarta wrappercommon From 0cd3f2bc1cf4b108f6cf50ec1912b001236c7fa5 Mon Sep 17 00:00:00 2001 From: iroqueta Date: Mon, 7 Aug 2023 15:49:54 -0300 Subject: [PATCH 04/15] Now JDK 17 is needed to build standar classes Issue: 103655 --- .github/workflows/cache-redis-tests.yml | 2 +- .github/workflows/cloud-storage-tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cache-redis-tests.yml b/.github/workflows/cache-redis-tests.yml index fe7eab519..ea10dae99 100644 --- a/.github/workflows/cache-redis-tests.yml +++ b/.github/workflows/cache-redis-tests.yml @@ -34,7 +34,7 @@ jobs: - name: Setup Java JDK uses: actions/setup-java@v1.4.3 with: - java-version: 1.9 + java-version: 17 - name: Setup Maven settings uses: whelk-io/maven-settings-xml-action@v14 diff --git a/.github/workflows/cloud-storage-tests.yml b/.github/workflows/cloud-storage-tests.yml index acce56a5e..77b25c8e3 100644 --- a/.github/workflows/cloud-storage-tests.yml +++ b/.github/workflows/cloud-storage-tests.yml @@ -34,7 +34,7 @@ jobs: - name: Setup Java JDK uses: actions/setup-java@v1.4.3 with: - java-version: 1.9 + java-version: 17 - name: Setup Maven settings uses: whelk-io/maven-settings-xml-action@v14 From 3f7959954da75326338443ff8c99e530de4de2cc Mon Sep 17 00:00:00 2001 From: iroqueta Date: Thu, 10 Aug 2023 17:45:15 -0300 Subject: [PATCH 05/15] Read theme data as resource when SpringBoot is enabled Read application.gam and connection.gam when Springboot ir run as jar. Issue: 103655 --- .../src/main/java/com/genexus/util/ThemeHelper.java | 8 +++++++- common/src/main/java/com/genexus/xml/XMLReader.java | 13 +++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/com/genexus/util/ThemeHelper.java b/common/src/main/java/com/genexus/util/ThemeHelper.java index fc765dd5b..bdd7c272f 100644 --- a/common/src/main/java/com/genexus/util/ThemeHelper.java +++ b/common/src/main/java/com/genexus/util/ThemeHelper.java @@ -1,6 +1,7 @@ package com.genexus.util; import java.io.File; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.Collections; @@ -11,6 +12,7 @@ import com.genexus.CommonUtil; import com.genexus.common.interfaces.SpecificImplementation; +import org.springframework.core.io.ClassPathResource; public class ThemeHelper { @@ -34,7 +36,11 @@ private static ThemeData getThemeData(String themeName) ThemeData themeData; try { - String json = SpecificImplementation.GXutil.readFileToString(themesJsonFile, CommonUtil.normalizeEncodingName("UTF-8")); + String json; + if (com.genexus.ApplicationContext.getInstance().isSpringBootApp()) + json = new ClassPathResource("themes/" + themeName + ".json").getContentAsString(StandardCharsets.UTF_8); + else + json = SpecificImplementation.GXutil.readFileToString(themesJsonFile, CommonUtil.normalizeEncodingName("UTF-8")); themeData = ThemeData.fromJson(json); } catch (Exception ex) diff --git a/common/src/main/java/com/genexus/xml/XMLReader.java b/common/src/main/java/com/genexus/xml/XMLReader.java index 8ec6e02be..28d6424fa 100644 --- a/common/src/main/java/com/genexus/xml/XMLReader.java +++ b/common/src/main/java/com/genexus/xml/XMLReader.java @@ -772,23 +772,28 @@ public void open(String url) reset(); try { - File xmlFile = new File(url); + InputStream fileInputStream = null; if (ApplicationContext.getInstance().isSpringBootApp()) { ClassPathResource resource = new ClassPathResource(url); if (resource.exists()) - xmlFile = resource.getFile(); + fileInputStream = resource.getInputStream(); else { if (url.startsWith(ApplicationContext.getInstance().getServletEngineDefaultPath())) { resource = new ClassPathResource(url.replace(ApplicationContext.getInstance().getServletEngineDefaultPath(), "")); if (resource.exists()) - xmlFile = resource.getFile(); + fileInputStream = resource.getInputStream(); } } } - inputSource = new XMLInputSource(null, url, null, new FileInputStream(xmlFile), null); + else + { + File xmlFile = new File(url); + fileInputStream = new FileInputStream(xmlFile); + } + inputSource = new XMLInputSource(null, url, null, fileInputStream, null); if (documentEncoding.length() > 0) inputSource.setEncoding(CommonUtil.normalizeEncodingName(documentEncoding)); parserConfiguration.setInputSource(inputSource); From fef460038a3f110ad8cd1419b3a5f6808784c840 Mon Sep 17 00:00:00 2001 From: iroqueta Date: Fri, 11 Aug 2023 16:46:19 -0300 Subject: [PATCH 06/15] Read .config file in Springboot Issue: 103655 --- .../main/java/com/genexus/ApplicationContext.java | 14 +++++++++++++- .../src/main/java/com/genexus/xml/XMLReader.java | 11 +---------- .../java/com/genexus/internet/HttpAjaxContext.java | 3 +-- .../src/main/java/com/genexus/util/GXServices.java | 9 ++++++--- .../java/com/genexus/webpanels/HttpContextWeb.java | 3 +++ 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/common/src/main/java/com/genexus/ApplicationContext.java b/common/src/main/java/com/genexus/ApplicationContext.java index db0b35db2..59717b83a 100644 --- a/common/src/main/java/com/genexus/ApplicationContext.java +++ b/common/src/main/java/com/genexus/ApplicationContext.java @@ -1,6 +1,10 @@ package com.genexus; +import org.springframework.core.io.ClassPathResource; + +import java.io.File; + public class ApplicationContext { private static ApplicationContext instance; @@ -123,6 +127,14 @@ public boolean isSpringBootApp() return isSpringBootApp; } + public boolean checkIfResourceExist(String path) + { + if (isSpringBootApp()) + return new ClassPathResource(path).exists(); + else + return new File(path).exists(); + } + public void setEJBEngine(boolean isEJBEngine) { this.isEJBEngine = isEJBEngine; @@ -137,7 +149,7 @@ public boolean isEJBEngine() private String servletEngineDefaultPath = ""; public void setServletEngineDefaultPath(String servletEngineDefaultPath) { - if (servletEngineDefaultPath != null) { + if (servletEngineDefaultPath != null && !isSpringBootApp()) { this.servletEngineDefaultPath = servletEngineDefaultPath.trim(); if(this.servletEngineDefaultPath.endsWith(java.io.File.separator)) { diff --git a/common/src/main/java/com/genexus/xml/XMLReader.java b/common/src/main/java/com/genexus/xml/XMLReader.java index 28d6424fa..68e5ff340 100644 --- a/common/src/main/java/com/genexus/xml/XMLReader.java +++ b/common/src/main/java/com/genexus/xml/XMLReader.java @@ -775,18 +775,9 @@ public void open(String url) InputStream fileInputStream = null; if (ApplicationContext.getInstance().isSpringBootApp()) { - ClassPathResource resource = new ClassPathResource(url); + ClassPathResource resource = new ClassPathResource(url.replace(".\\", "")); if (resource.exists()) fileInputStream = resource.getInputStream(); - else - { - if (url.startsWith(ApplicationContext.getInstance().getServletEngineDefaultPath())) - { - resource = new ClassPathResource(url.replace(ApplicationContext.getInstance().getServletEngineDefaultPath(), "")); - if (resource.exists()) - fileInputStream = resource.getInputStream(); - } - } } else { diff --git a/gxweb/src/main/java/com/genexus/internet/HttpAjaxContext.java b/gxweb/src/main/java/com/genexus/internet/HttpAjaxContext.java index cd7ee3442..232d84c81 100644 --- a/gxweb/src/main/java/com/genexus/internet/HttpAjaxContext.java +++ b/gxweb/src/main/java/com/genexus/internet/HttpAjaxContext.java @@ -727,8 +727,7 @@ private boolean checkFileExists(String fileName) boolean fileExists = false; try { - File file = new File(getDefaultPath() + staticContentBase + fileName); - fileExists = file.exists() && file.isFile(); + fileExists = ApplicationContext.getInstance().checkIfResourceExist(getDefaultPath() + staticContentBase + fileName); com.genexus.diagnostics.Log.info("Searching if file exists (" + fileName + "). Found: " + String.valueOf(fileExists)); } catch (Exception e) diff --git a/java/src/main/java/com/genexus/util/GXServices.java b/java/src/main/java/com/genexus/util/GXServices.java index 165dca5aa..73c82e156 100644 --- a/java/src/main/java/com/genexus/util/GXServices.java +++ b/java/src/main/java/com/genexus/util/GXServices.java @@ -74,7 +74,10 @@ public static void loadFromFile(String basePath, String fileName, GXServices ser } } - private String configBaseDirectory() { + public String configBaseDirectory() { + if (ApplicationContext.getInstance().isSpringBootApp()) + return ""; + String baseDir = ""; String envVariable = System.getenv("LAMBDA_TASK_ROOT"); if (envVariable != null && envVariable.length() > 0) @@ -102,10 +105,10 @@ private void readServices(String basePath) { if (basePath.equals("")) basePath = configBaseDirectory(); - if (new File(basePath + SERVICES_DEV_FILE).exists()){ + if (ApplicationContext.getInstance().checkIfResourceExist(basePath + SERVICES_DEV_FILE)){ loadFromFile(basePath, SERVICES_DEV_FILE, this); } - if (new File(basePath + SERVICES_FILE).exists()){ + if (ApplicationContext.getInstance().checkIfResourceExist(basePath + SERVICES_FILE)){ loadFromFile(basePath, SERVICES_FILE, this); } } diff --git a/java/src/main/java/com/genexus/webpanels/HttpContextWeb.java b/java/src/main/java/com/genexus/webpanels/HttpContextWeb.java index e1ab9c3c4..a877898d3 100644 --- a/java/src/main/java/com/genexus/webpanels/HttpContextWeb.java +++ b/java/src/main/java/com/genexus/webpanels/HttpContextWeb.java @@ -1255,6 +1255,9 @@ private boolean useCustomRedirect() { } public String getDefaultPath() { + if (ApplicationContext.getInstance().isSpringBootApp()) + return ""; + if (servletContext == null) return ""; From bf8b4dfffe78f67b408f713ece23c5caf676f6c1 Mon Sep 17 00:00:00 2001 From: iroqueta Date: Wed, 16 Aug 2023 12:57:12 -0300 Subject: [PATCH 07/15] Error code in response error message must be numeric in springboot Issue: 103655 --- .../springboot/GxSpringBootRestService.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java b/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java index e6fd517c4..dda88eb61 100644 --- a/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java +++ b/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java @@ -1,7 +1,8 @@ package com.genexus.springboot; import com.genexus.GxRestService; -import com.genexus.WrapperUtils; +import json.org.json.JSONException; +import json.org.json.JSONObject; import org.apache.logging.log4j.Logger; import org.springframework.http.*; import org.springframework.web.bind.annotation.*; @@ -13,8 +14,19 @@ abstract public class GxSpringBootRestService extends GxRestService { @ExceptionHandler(HttpMessageNotReadableException.class) protected ResponseEntity handleException(HttpMessageNotReadableException ex) { log.error("Error executing REST service", ex); + JSONObject errorJson = new JSONObject(); + try + { + JSONObject obj = new JSONObject(); + obj.put("code", 400); + obj.put("message", "Bad Request"); + errorJson.put("error", obj); + } + catch(JSONException e) + { + log.error("Invalid JSON", e); + } - SetError("400", "Bad Request"); ResponseEntity.BodyBuilder builder = ResponseEntity.status(HttpStatus.BAD_REQUEST); builder.contentType(MediaType.APPLICATION_JSON); return builder.body(errorJson.toString()) ; From 8ec4c093bc8debe6ab982f15adef173b6b8cbb0f Mon Sep 17 00:00:00 2001 From: iroqueta Date: Wed, 16 Aug 2023 22:17:06 -0300 Subject: [PATCH 08/15] Catch NullPointer exception when try to serialize wrong messages in request body, and return a json message with bad request Issue: 103655 --- .../java/com/genexus/springboot/GxSpringBootRestService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java b/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java index dda88eb61..be691fd31 100644 --- a/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java +++ b/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java @@ -11,8 +11,8 @@ abstract public class GxSpringBootRestService extends GxRestService { private static Logger log = org.apache.logging.log4j.LogManager.getLogger(GxSpringBootRestService.class); - @ExceptionHandler(HttpMessageNotReadableException.class) - protected ResponseEntity handleException(HttpMessageNotReadableException ex) { + @ExceptionHandler(value = {HttpMessageNotReadableException.class, NullPointerException.class}) + protected ResponseEntity handleException(Exception ex) { log.error("Error executing REST service", ex); JSONObject errorJson = new JSONObject(); try From 00250ea39f344cb55f1aa8bd9a7640538cd4a67f Mon Sep 17 00:00:00 2001 From: iroqueta Date: Fri, 18 Aug 2023 15:43:29 -0300 Subject: [PATCH 09/15] Implements case insensitive support in API Object URL in Spring Boot Issue: 103655 --- .../java/com/genexus/springboot/GXConfig.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 gxspringboot/src/main/java/com/genexus/springboot/GXConfig.java diff --git a/gxspringboot/src/main/java/com/genexus/springboot/GXConfig.java b/gxspringboot/src/main/java/com/genexus/springboot/GXConfig.java new file mode 100644 index 000000000..02fc89f74 --- /dev/null +++ b/gxspringboot/src/main/java/com/genexus/springboot/GXConfig.java @@ -0,0 +1,19 @@ +package com.genexus.springboot; + +import org.springframework.context.annotation.Configuration; +import org.springframework.util.AntPathMatcher; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +@EnableWebMvc +public class GXConfig implements WebMvcConfigurer { + + @Override + public void configurePathMatch(PathMatchConfigurer configurer) { + AntPathMatcher matcher = new AntPathMatcher(); + matcher.setCaseSensitive(false); + configurer.setPathMatcher(matcher); + } +} From e8992613ad24d23c84291a420c5d0251cc2bd342 Mon Sep 17 00:00:00 2001 From: iroqueta Date: Mon, 28 Aug 2023 18:53:28 -0300 Subject: [PATCH 10/15] Implements GXMultiCall support in Springboot Issue: 103655 --- .../com/genexus/springboot/GXMultiCall.java | 42 +++++++++ .../com/genexus/webpanels/GXMultiCall.java | 91 +++++++------------ 2 files changed, 74 insertions(+), 59 deletions(-) create mode 100644 gxspringboot/src/main/java/com/genexus/springboot/GXMultiCall.java diff --git a/gxspringboot/src/main/java/com/genexus/springboot/GXMultiCall.java b/gxspringboot/src/main/java/com/genexus/springboot/GXMultiCall.java new file mode 100644 index 000000000..1349c4ae7 --- /dev/null +++ b/gxspringboot/src/main/java/com/genexus/springboot/GXMultiCall.java @@ -0,0 +1,42 @@ +package com.genexus.springboot; + +import org.springframework.http.*; +import org.springframework.web.bind.annotation.*; + +@RestController("GXMultiCall") +@RequestMapping(value = {"/gxmulticall", "/rest/gxmulticall"}) +public class GXMultiCall extends GxSpringBootRestService { + private final static String METHOD_EXECUTE = "execute"; + + @PostMapping(value = "", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public Object gxMultiCall(@RequestBody String jsonStr) throws Exception { + super.init( "POST" ); + ResponseEntity.BodyBuilder builder = null; + + try { + com.genexus.webpanels.GXMultiCall.callProcRest(context, jsonStr); + } + catch(ClassNotFoundException cnf) { + builder = ResponseEntity.status(HttpStatus.NOT_FOUND); + cleanup(); + return builder.body(null) ; + } + + builder = ResponseEntity.ok(); + builder.contentType(MediaType.APPLICATION_JSON); + cleanup(); + return builder.body("") ; + } + + protected boolean IntegratedSecurityEnabled( ) { + return false; + } + + protected int IntegratedSecurityLevel( ) { + return 0; + } + + protected String EncryptURLParameters() { + return "NO"; + } +} diff --git a/java/src/main/java/com/genexus/webpanels/GXMultiCall.java b/java/src/main/java/com/genexus/webpanels/GXMultiCall.java index 6093a0c69..e7c1dc85b 100644 --- a/java/src/main/java/com/genexus/webpanels/GXMultiCall.java +++ b/java/src/main/java/com/genexus/webpanels/GXMultiCall.java @@ -1,6 +1,5 @@ package com.genexus.webpanels; -import java.io.InputStream; import java.lang.reflect.Method; import com.genexus.Application; @@ -28,19 +27,10 @@ public class GXMultiCall extends GxRestService public Object gxMultiCall(String jsonStr) throws Exception { super.init( "POST" ); - String procName = ((HttpContextWeb) context.getHttpContext()).GetNextPar().toLowerCase(); - ModelContext modelContext = ModelContext.getModelContext(Application.gxCfg); - String appPackage = modelContext.getNAME_SPACE(); - if (!appPackage.equals("")) - { - appPackage = appPackage + "."; - } - - String restProcName = procName + "_services_rest"; try { - Class myClassRest = Class.forName(appPackage + restProcName); + GXMultiCall.callProcRest(context, jsonStr); } catch(ClassNotFoundException cnf) { @@ -48,7 +38,28 @@ public Object gxMultiCall(String jsonStr) throws Exception cleanup(); return builder.build() ; } - + + builder = Response.okWrapped(); + builder.type("application/json"); + builder.entity(""); + cleanup(); + return builder.build() ; + } + + public static void callProcRest(ModelContext context, String jsonStr) throws Exception + { + String procName = ((HttpContextWeb) context.getHttpContext()).GetNextPar().toLowerCase(); + + ModelContext modelContext = ModelContext.getModelContext(Application.gxCfg); + String appPackage = modelContext.getNAME_SPACE(); + if (!appPackage.equals("")) + { + appPackage = appPackage + "."; + } + + String restProcName = procName + "_services_rest"; + + Class myClassRest = Class.forName(appPackage + restProcName); Class myClass = Class.forName(appPackage + procName); Method[] methods = myClass.getMethods(); @@ -66,7 +77,7 @@ public Object gxMultiCall(String jsonStr) throws Exception JSONArray jsonArr = new JSONArray(jsonStr); UserInformation ui = Application.getConnectionManager().createUserInformation(Namespace.getNamespace(modelContext.getNAME_SPACE())); int remoteHandle = ui.getHandle(); - + for(int i = 0; i < jsonArr.length(); i++) { JSONArray procParms = new JSONArray(jsonArr.getJSONArray(i).toString()); @@ -76,17 +87,11 @@ public Object gxMultiCall(String jsonStr) throws Exception { params[j] = GXutil.convertObjectTo(procParms.getString(j), parameters[j]); } - com.genexus.db.DynamicExecute.dynamicExecute(modelContext, remoteHandle, modelContext.packageClass, appPackage + procName, params); + com.genexus.db.DynamicExecute.dynamicExecute(modelContext, remoteHandle, modelContext.packageClass, appPackage + procName, params); } - - Application.cleanupConnection(remoteHandle); - builder = Response.okWrapped(); - builder.type("application/json"); - builder.entity(""); - cleanup(); - return builder.build() ; - } + Application.cleanupConnection(remoteHandle); + } protected boolean IntegratedSecurityEnabled( ) { @@ -97,41 +102,9 @@ protected int IntegratedSecurityLevel( ) { return 0; } - - protected String EncryptURLParameters() {return "NO";}; - - private String parsePostData(int len, InputStream in) - { - if(len <= 0) - return new String(); - if(in == null) - throw new IllegalArgumentException(); - byte postedBytes[] = new byte[len]; - try - { - int offset = 0; - do - { - int inputLen = in.read(postedBytes, offset, len - offset); - if(inputLen <= 0) - { - throw new IllegalArgumentException ("err.io.short_read : length " + len + " read : " + offset + " Content: \n" + new String(postedBytes)); - } - offset += inputLen; - } while(len - offset > 0); - } - catch(java.io.IOException e) - { - throw new IllegalArgumentException(e.getMessage()); - } - try - { - String postedBody = new String(postedBytes, 0, len, "8859_1"); - return postedBody; - } - catch(java.io.UnsupportedEncodingException e) - { - throw new IllegalArgumentException(e.getMessage()); - } - } + + protected String EncryptURLParameters() + { + return "NO"; + } } From fd2d5e19c8954e82da9f2220928dd7a151007e97 Mon Sep 17 00:00:00 2001 From: iroqueta Date: Tue, 29 Aug 2023 14:47:46 -0300 Subject: [PATCH 11/15] Catch general error to wirte a response with Internal Server Error in REST services using Spring Boot Image.Link() in Spring Boot cames without contextPath Issue: 103655 --- .../springboot/GxSpringBootRestService.java | 18 ++++++++++++++---- .../java/com/genexus/internet/HttpContext.java | 2 +- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java b/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java index be691fd31..ecb9a82b9 100644 --- a/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java +++ b/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java @@ -11,15 +11,25 @@ abstract public class GxSpringBootRestService extends GxRestService { private static Logger log = org.apache.logging.log4j.LogManager.getLogger(GxSpringBootRestService.class); - @ExceptionHandler(value = {HttpMessageNotReadableException.class, NullPointerException.class}) + @ExceptionHandler(Exception.class) protected ResponseEntity handleException(Exception ex) { log.error("Error executing REST service", ex); JSONObject errorJson = new JSONObject(); + int errCode = 500; + String errMessage = "Internal Server Error"; + HttpStatus statusCode = HttpStatus.INTERNAL_SERVER_ERROR; + + if (ex instanceof HttpMessageNotReadableException || ex instanceof NullPointerException) { + errCode = 400; + errMessage = "Bad Request"; + statusCode = HttpStatus.BAD_REQUEST; + } + try { JSONObject obj = new JSONObject(); - obj.put("code", 400); - obj.put("message", "Bad Request"); + obj.put("code", errCode); + obj.put("message", errMessage); errorJson.put("error", obj); } catch(JSONException e) @@ -27,7 +37,7 @@ protected ResponseEntity handleException(Exception ex) { log.error("Invalid JSON", e); } - ResponseEntity.BodyBuilder builder = ResponseEntity.status(HttpStatus.BAD_REQUEST); + ResponseEntity.BodyBuilder builder = ResponseEntity.status(statusCode); builder.contentType(MediaType.APPLICATION_JSON); return builder.body(errorJson.toString()) ; } diff --git a/java/src/main/java/com/genexus/internet/HttpContext.java b/java/src/main/java/com/genexus/internet/HttpContext.java index aab778855..4d2bf575a 100644 --- a/java/src/main/java/com/genexus/internet/HttpContext.java +++ b/java/src/main/java/com/genexus/internet/HttpContext.java @@ -755,7 +755,7 @@ public String oldConvertURL(String file) if (file.startsWith("/")) { - if (file.startsWith(getContextPath()) || file.startsWith(getDefaultPath())) + if (file.startsWith(getContextPath()) || (!getDefaultPath().isEmpty() && file.startsWith(getDefaultPath()))) return out; return getContextPath() + out; } From 14d8fb83e8137f525e0199aeffb1fd50e7ec576d Mon Sep 17 00:00:00 2001 From: iroqueta Date: Wed, 30 Aug 2023 18:09:01 -0300 Subject: [PATCH 12/15] Read xml metadata tables in SD Apllications was not working using Spring Boot. Issue: 103655 fef4600 --- .../main/java/com/genexus/BaseProvider.java | 76 +++++++++++++++---- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/common/src/main/java/com/genexus/BaseProvider.java b/common/src/main/java/com/genexus/BaseProvider.java index 5fa4efb50..d3730906b 100644 --- a/common/src/main/java/com/genexus/BaseProvider.java +++ b/common/src/main/java/com/genexus/BaseProvider.java @@ -1,12 +1,16 @@ package com.genexus; import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.List; import java.util.ListIterator; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; +import com.genexus.diagnostics.core.ILogger; +import com.genexus.diagnostics.core.LogManager; import com.genexus.xml.XMLReader; import org.apache.commons.lang.StringUtils; @@ -16,9 +20,13 @@ import com.genexus.common.interfaces.SpecificImplementation; import com.genexus.util.GXDirectory; import com.genexus.util.GXFileCollection; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; public abstract class BaseProvider implements IGXSmartCacheProvider { + private static final ILogger logger = LogManager.getLogger(BaseProvider.class); + ConcurrentHashMap> queryTables; protected Date startupDate; Object syncLock = new Object(); @@ -45,30 +53,70 @@ private void loadQueryTables() { String path = SpecificImplementation.Application.getModelContext().getHttpContext().getDefaultPath(); String configurationDirectoryPath = path + File.separatorChar + "Metadata" + File.separatorChar + "TableAccess"; - ConcurrentHashMap> qTables = new ConcurrentHashMap>(); - GXDirectory configurationDirectory = new GXDirectory(configurationDirectoryPath); - GXFileCollection files = configurationDirectory.getFiles(); + + ConcurrentHashMap> qTables = new ConcurrentHashMap(); + loadQueryTablesPlatform(configurationDirectoryPath, qTables); + startupDate = CommonUtil.now(false,false); + queryTables = qTables; + } + } + + public void loadQueryTablesPlatform(String configurationDirectoryPath, ConcurrentHashMap> qTables) { + if (ApplicationContext.getInstance().isSpringBootApp()) + loadQueryTablesSpringBoot(configurationDirectoryPath, qTables); + else + loadQueryTablesNone(configurationDirectoryPath, qTables); + + } + + public void loadQueryTablesNone(String configurationDirectoryPath, ConcurrentHashMap> qTables) { + GXDirectory configurationDirectory = new GXDirectory(configurationDirectoryPath); + GXFileCollection files = configurationDirectory.getFiles(); + XMLReader reader = new XMLReader(); + short ok; + for(int i=1; i <= files.getItemCount(); i++) { + Vector lst = new Vector(); + lst.add(FORCED_INVALIDATE); // Caso en que se invalido el cache manualmente + AbstractGXFile xmlFile = files.item(i); + reader.open(xmlFile.getAbsoluteName()); + ok = reader.readType(1, "Table"); + while (ok == 1) { + lst.add(normalizeKey(reader.getAttributeByName("name"))); + ok = reader.readType(1, "Table"); + } + reader.close(); + qTables.put(normalizeKey(xmlFile.getNameNoExt()), lst); + } + } + + public void loadQueryTablesSpringBoot(String configurationDirectoryPath, ConcurrentHashMap> qTables) { + try { + Resource[] resources = new PathMatchingResourcePatternResolver().getResources(configurationDirectoryPath + "/*.xml"); XMLReader reader = new XMLReader(); + reader.setDocEncoding("UTF8"); short ok; - for(int i=1; i <= files.getItemCount(); i++) - { + String xmlContent; + for (int i = 0; i < resources.length; i++) { Vector lst = new Vector(); - lst.add(FORCED_INVALIDATE); // Caso en que se invalido el cache manualmente - AbstractGXFile xmlFile = files.item(i); - reader.open(xmlFile.getAbsoluteName()); + lst.add(FORCED_INVALIDATE); + xmlContent = resources[i].getContentAsString(StandardCharsets.UTF_8); + if (!xmlContent.startsWith("<")) + xmlContent = xmlContent.substring(1); //Avoid BOM + reader.openFromString(xmlContent); ok = reader.readType(1, "Table"); - while (ok == 1) - { - lst.add(normalizeKey((String) reader.getAttributeByName("name"))); + while (ok == 1) { + lst.add(normalizeKey(reader.getAttributeByName("name"))); ok = reader.readType(1, "Table"); } reader.close(); - qTables.put(normalizeKey((String)xmlFile.getNameNoExt()), lst); + qTables.put(normalizeKey(resources[i].getFilename().substring(0, resources[i].getFilename().lastIndexOf("."))), lst); } - startupDate = CommonUtil.now(false,false); - queryTables = qTables; + } + catch (IOException e) { + logger.error("Error reading Table Access metadata", e); } } + public ConcurrentHashMap> queryTables() { if (queryTables == null) { From 519df175c029e6a03f7ca36a716e0297c9d972ad Mon Sep 17 00:00:00 2001 From: iroqueta Date: Wed, 30 Aug 2023 18:25:41 -0300 Subject: [PATCH 13/15] Read xml metadata tables in SD Apllications was not working using Spring Boot. Issue: 103655 --- .../main/java/com/genexus/BaseProvider.java | 76 +++++++++++++++---- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/common/src/main/java/com/genexus/BaseProvider.java b/common/src/main/java/com/genexus/BaseProvider.java index 5fa4efb50..d3730906b 100644 --- a/common/src/main/java/com/genexus/BaseProvider.java +++ b/common/src/main/java/com/genexus/BaseProvider.java @@ -1,12 +1,16 @@ package com.genexus; import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.List; import java.util.ListIterator; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; +import com.genexus.diagnostics.core.ILogger; +import com.genexus.diagnostics.core.LogManager; import com.genexus.xml.XMLReader; import org.apache.commons.lang.StringUtils; @@ -16,9 +20,13 @@ import com.genexus.common.interfaces.SpecificImplementation; import com.genexus.util.GXDirectory; import com.genexus.util.GXFileCollection; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; public abstract class BaseProvider implements IGXSmartCacheProvider { + private static final ILogger logger = LogManager.getLogger(BaseProvider.class); + ConcurrentHashMap> queryTables; protected Date startupDate; Object syncLock = new Object(); @@ -45,30 +53,70 @@ private void loadQueryTables() { String path = SpecificImplementation.Application.getModelContext().getHttpContext().getDefaultPath(); String configurationDirectoryPath = path + File.separatorChar + "Metadata" + File.separatorChar + "TableAccess"; - ConcurrentHashMap> qTables = new ConcurrentHashMap>(); - GXDirectory configurationDirectory = new GXDirectory(configurationDirectoryPath); - GXFileCollection files = configurationDirectory.getFiles(); + + ConcurrentHashMap> qTables = new ConcurrentHashMap(); + loadQueryTablesPlatform(configurationDirectoryPath, qTables); + startupDate = CommonUtil.now(false,false); + queryTables = qTables; + } + } + + public void loadQueryTablesPlatform(String configurationDirectoryPath, ConcurrentHashMap> qTables) { + if (ApplicationContext.getInstance().isSpringBootApp()) + loadQueryTablesSpringBoot(configurationDirectoryPath, qTables); + else + loadQueryTablesNone(configurationDirectoryPath, qTables); + + } + + public void loadQueryTablesNone(String configurationDirectoryPath, ConcurrentHashMap> qTables) { + GXDirectory configurationDirectory = new GXDirectory(configurationDirectoryPath); + GXFileCollection files = configurationDirectory.getFiles(); + XMLReader reader = new XMLReader(); + short ok; + for(int i=1; i <= files.getItemCount(); i++) { + Vector lst = new Vector(); + lst.add(FORCED_INVALIDATE); // Caso en que se invalido el cache manualmente + AbstractGXFile xmlFile = files.item(i); + reader.open(xmlFile.getAbsoluteName()); + ok = reader.readType(1, "Table"); + while (ok == 1) { + lst.add(normalizeKey(reader.getAttributeByName("name"))); + ok = reader.readType(1, "Table"); + } + reader.close(); + qTables.put(normalizeKey(xmlFile.getNameNoExt()), lst); + } + } + + public void loadQueryTablesSpringBoot(String configurationDirectoryPath, ConcurrentHashMap> qTables) { + try { + Resource[] resources = new PathMatchingResourcePatternResolver().getResources(configurationDirectoryPath + "/*.xml"); XMLReader reader = new XMLReader(); + reader.setDocEncoding("UTF8"); short ok; - for(int i=1; i <= files.getItemCount(); i++) - { + String xmlContent; + for (int i = 0; i < resources.length; i++) { Vector lst = new Vector(); - lst.add(FORCED_INVALIDATE); // Caso en que se invalido el cache manualmente - AbstractGXFile xmlFile = files.item(i); - reader.open(xmlFile.getAbsoluteName()); + lst.add(FORCED_INVALIDATE); + xmlContent = resources[i].getContentAsString(StandardCharsets.UTF_8); + if (!xmlContent.startsWith("<")) + xmlContent = xmlContent.substring(1); //Avoid BOM + reader.openFromString(xmlContent); ok = reader.readType(1, "Table"); - while (ok == 1) - { - lst.add(normalizeKey((String) reader.getAttributeByName("name"))); + while (ok == 1) { + lst.add(normalizeKey(reader.getAttributeByName("name"))); ok = reader.readType(1, "Table"); } reader.close(); - qTables.put(normalizeKey((String)xmlFile.getNameNoExt()), lst); + qTables.put(normalizeKey(resources[i].getFilename().substring(0, resources[i].getFilename().lastIndexOf("."))), lst); } - startupDate = CommonUtil.now(false,false); - queryTables = qTables; + } + catch (IOException e) { + logger.error("Error reading Table Access metadata", e); } } + public ConcurrentHashMap> queryTables() { if (queryTables == null) { From 57095f5fcd59387f1fbf974bf143f0046e67460a Mon Sep 17 00:00:00 2001 From: iroqueta Date: Wed, 30 Aug 2023 18:28:28 -0300 Subject: [PATCH 14/15] Revert "Read xml metadata tables in SD Apllications was not working using Spring Boot." This reverts commit 14d8fb83e8137f525e0199aeffb1fd50e7ec576d. --- .../main/java/com/genexus/BaseProvider.java | 76 ++++--------------- 1 file changed, 14 insertions(+), 62 deletions(-) diff --git a/common/src/main/java/com/genexus/BaseProvider.java b/common/src/main/java/com/genexus/BaseProvider.java index d3730906b..5fa4efb50 100644 --- a/common/src/main/java/com/genexus/BaseProvider.java +++ b/common/src/main/java/com/genexus/BaseProvider.java @@ -1,16 +1,12 @@ package com.genexus; import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.List; import java.util.ListIterator; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; -import com.genexus.diagnostics.core.ILogger; -import com.genexus.diagnostics.core.LogManager; import com.genexus.xml.XMLReader; import org.apache.commons.lang.StringUtils; @@ -20,13 +16,9 @@ import com.genexus.common.interfaces.SpecificImplementation; import com.genexus.util.GXDirectory; import com.genexus.util.GXFileCollection; -import org.springframework.core.io.Resource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; public abstract class BaseProvider implements IGXSmartCacheProvider { - private static final ILogger logger = LogManager.getLogger(BaseProvider.class); - ConcurrentHashMap> queryTables; protected Date startupDate; Object syncLock = new Object(); @@ -53,70 +45,30 @@ private void loadQueryTables() { String path = SpecificImplementation.Application.getModelContext().getHttpContext().getDefaultPath(); String configurationDirectoryPath = path + File.separatorChar + "Metadata" + File.separatorChar + "TableAccess"; - - ConcurrentHashMap> qTables = new ConcurrentHashMap(); - loadQueryTablesPlatform(configurationDirectoryPath, qTables); - startupDate = CommonUtil.now(false,false); - queryTables = qTables; - } - } - - public void loadQueryTablesPlatform(String configurationDirectoryPath, ConcurrentHashMap> qTables) { - if (ApplicationContext.getInstance().isSpringBootApp()) - loadQueryTablesSpringBoot(configurationDirectoryPath, qTables); - else - loadQueryTablesNone(configurationDirectoryPath, qTables); - - } - - public void loadQueryTablesNone(String configurationDirectoryPath, ConcurrentHashMap> qTables) { - GXDirectory configurationDirectory = new GXDirectory(configurationDirectoryPath); - GXFileCollection files = configurationDirectory.getFiles(); - XMLReader reader = new XMLReader(); - short ok; - for(int i=1; i <= files.getItemCount(); i++) { - Vector lst = new Vector(); - lst.add(FORCED_INVALIDATE); // Caso en que se invalido el cache manualmente - AbstractGXFile xmlFile = files.item(i); - reader.open(xmlFile.getAbsoluteName()); - ok = reader.readType(1, "Table"); - while (ok == 1) { - lst.add(normalizeKey(reader.getAttributeByName("name"))); - ok = reader.readType(1, "Table"); - } - reader.close(); - qTables.put(normalizeKey(xmlFile.getNameNoExt()), lst); - } - } - - public void loadQueryTablesSpringBoot(String configurationDirectoryPath, ConcurrentHashMap> qTables) { - try { - Resource[] resources = new PathMatchingResourcePatternResolver().getResources(configurationDirectoryPath + "/*.xml"); + ConcurrentHashMap> qTables = new ConcurrentHashMap>(); + GXDirectory configurationDirectory = new GXDirectory(configurationDirectoryPath); + GXFileCollection files = configurationDirectory.getFiles(); XMLReader reader = new XMLReader(); - reader.setDocEncoding("UTF8"); short ok; - String xmlContent; - for (int i = 0; i < resources.length; i++) { + for(int i=1; i <= files.getItemCount(); i++) + { Vector lst = new Vector(); - lst.add(FORCED_INVALIDATE); - xmlContent = resources[i].getContentAsString(StandardCharsets.UTF_8); - if (!xmlContent.startsWith("<")) - xmlContent = xmlContent.substring(1); //Avoid BOM - reader.openFromString(xmlContent); + lst.add(FORCED_INVALIDATE); // Caso en que se invalido el cache manualmente + AbstractGXFile xmlFile = files.item(i); + reader.open(xmlFile.getAbsoluteName()); ok = reader.readType(1, "Table"); - while (ok == 1) { - lst.add(normalizeKey(reader.getAttributeByName("name"))); + while (ok == 1) + { + lst.add(normalizeKey((String) reader.getAttributeByName("name"))); ok = reader.readType(1, "Table"); } reader.close(); - qTables.put(normalizeKey(resources[i].getFilename().substring(0, resources[i].getFilename().lastIndexOf("."))), lst); + qTables.put(normalizeKey((String)xmlFile.getNameNoExt()), lst); } - } - catch (IOException e) { - logger.error("Error reading Table Access metadata", e); + startupDate = CommonUtil.now(false,false); + queryTables = qTables; } } - public ConcurrentHashMap> queryTables() { if (queryTables == null) { From 5da53e3d6dba266d53e5ae87f471d72bb34dde9b Mon Sep 17 00:00:00 2001 From: iroqueta Date: Wed, 30 Aug 2023 18:36:26 -0300 Subject: [PATCH 15/15] Read xml metadata tables in SD Apllications was not working using Spring Boot. Issue: 103655 --- .../main/java/com/genexus/BaseProvider.java | 76 +++++++++++++++---- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/common/src/main/java/com/genexus/BaseProvider.java b/common/src/main/java/com/genexus/BaseProvider.java index 5fa4efb50..d3730906b 100644 --- a/common/src/main/java/com/genexus/BaseProvider.java +++ b/common/src/main/java/com/genexus/BaseProvider.java @@ -1,12 +1,16 @@ package com.genexus; import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.List; import java.util.ListIterator; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; +import com.genexus.diagnostics.core.ILogger; +import com.genexus.diagnostics.core.LogManager; import com.genexus.xml.XMLReader; import org.apache.commons.lang.StringUtils; @@ -16,9 +20,13 @@ import com.genexus.common.interfaces.SpecificImplementation; import com.genexus.util.GXDirectory; import com.genexus.util.GXFileCollection; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; public abstract class BaseProvider implements IGXSmartCacheProvider { + private static final ILogger logger = LogManager.getLogger(BaseProvider.class); + ConcurrentHashMap> queryTables; protected Date startupDate; Object syncLock = new Object(); @@ -45,30 +53,70 @@ private void loadQueryTables() { String path = SpecificImplementation.Application.getModelContext().getHttpContext().getDefaultPath(); String configurationDirectoryPath = path + File.separatorChar + "Metadata" + File.separatorChar + "TableAccess"; - ConcurrentHashMap> qTables = new ConcurrentHashMap>(); - GXDirectory configurationDirectory = new GXDirectory(configurationDirectoryPath); - GXFileCollection files = configurationDirectory.getFiles(); + + ConcurrentHashMap> qTables = new ConcurrentHashMap(); + loadQueryTablesPlatform(configurationDirectoryPath, qTables); + startupDate = CommonUtil.now(false,false); + queryTables = qTables; + } + } + + public void loadQueryTablesPlatform(String configurationDirectoryPath, ConcurrentHashMap> qTables) { + if (ApplicationContext.getInstance().isSpringBootApp()) + loadQueryTablesSpringBoot(configurationDirectoryPath, qTables); + else + loadQueryTablesNone(configurationDirectoryPath, qTables); + + } + + public void loadQueryTablesNone(String configurationDirectoryPath, ConcurrentHashMap> qTables) { + GXDirectory configurationDirectory = new GXDirectory(configurationDirectoryPath); + GXFileCollection files = configurationDirectory.getFiles(); + XMLReader reader = new XMLReader(); + short ok; + for(int i=1; i <= files.getItemCount(); i++) { + Vector lst = new Vector(); + lst.add(FORCED_INVALIDATE); // Caso en que se invalido el cache manualmente + AbstractGXFile xmlFile = files.item(i); + reader.open(xmlFile.getAbsoluteName()); + ok = reader.readType(1, "Table"); + while (ok == 1) { + lst.add(normalizeKey(reader.getAttributeByName("name"))); + ok = reader.readType(1, "Table"); + } + reader.close(); + qTables.put(normalizeKey(xmlFile.getNameNoExt()), lst); + } + } + + public void loadQueryTablesSpringBoot(String configurationDirectoryPath, ConcurrentHashMap> qTables) { + try { + Resource[] resources = new PathMatchingResourcePatternResolver().getResources(configurationDirectoryPath + "/*.xml"); XMLReader reader = new XMLReader(); + reader.setDocEncoding("UTF8"); short ok; - for(int i=1; i <= files.getItemCount(); i++) - { + String xmlContent; + for (int i = 0; i < resources.length; i++) { Vector lst = new Vector(); - lst.add(FORCED_INVALIDATE); // Caso en que se invalido el cache manualmente - AbstractGXFile xmlFile = files.item(i); - reader.open(xmlFile.getAbsoluteName()); + lst.add(FORCED_INVALIDATE); + xmlContent = resources[i].getContentAsString(StandardCharsets.UTF_8); + if (!xmlContent.startsWith("<")) + xmlContent = xmlContent.substring(1); //Avoid BOM + reader.openFromString(xmlContent); ok = reader.readType(1, "Table"); - while (ok == 1) - { - lst.add(normalizeKey((String) reader.getAttributeByName("name"))); + while (ok == 1) { + lst.add(normalizeKey(reader.getAttributeByName("name"))); ok = reader.readType(1, "Table"); } reader.close(); - qTables.put(normalizeKey((String)xmlFile.getNameNoExt()), lst); + qTables.put(normalizeKey(resources[i].getFilename().substring(0, resources[i].getFilename().lastIndexOf("."))), lst); } - startupDate = CommonUtil.now(false,false); - queryTables = qTables; + } + catch (IOException e) { + logger.error("Error reading Table Access metadata", e); } } + public ConcurrentHashMap> queryTables() { if (queryTables == null) {