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/.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 diff --git a/common/pom.xml b/common/pom.xml index 97c49d47c..0e24c7544 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..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; @@ -14,7 +18,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 +117,24 @@ public boolean isServletEngine() return isServletEngine; } + public void setSpringBootApp(boolean isSpringBootApp) + { + this.isSpringBootApp = isSpringBootApp; + } + + 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; @@ -126,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/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) { 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 b9e03a903..78ecaec37 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 { @@ -773,7 +775,19 @@ public void open(String url) reset(); try { - inputSource = new XMLInputSource(null, url, null, new FileInputStream(new File(url)), null); + InputStream fileInputStream = null; + if (ApplicationContext.getInstance().isSpringBootApp()) + { + ClassPathResource resource = new ClassPathResource(url.replace(".\\", "")); + if (resource.exists()) + fileInputStream = resource.getInputStream(); + } + 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); 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/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/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); + } +} 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/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..ecb9a82b9 --- /dev/null +++ b/gxspringboot/src/main/java/com/genexus/springboot/GxSpringBootRestService.java @@ -0,0 +1,44 @@ +package com.genexus.springboot; + +import com.genexus.GxRestService; +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.*; +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(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", errCode); + obj.put("message", errMessage); + errorJson.put("error", obj); + } + catch(JSONException e) + { + log.error("Invalid JSON", e); + } + + ResponseEntity.BodyBuilder builder = ResponseEntity.status(statusCode); + builder.contentType(MediaType.APPLICATION_JSON); + return builder.body(errorJson.toString()) ; + } +} 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/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; } 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/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"; + } } 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); 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 ""; diff --git a/pom.xml b/pom.xml index c3e25eff0..f0c12c5f5 100644 --- a/pom.xml +++ b/pom.xml @@ -82,6 +82,7 @@ common gxweb + gxspringboot wrapperjavax wrapperjakarta wrappercommon 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;