This is an automated email from the ASF dual-hosted git repository.

mridulpathak pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 1520fca0e3 Remove ApiContextListener.getApplicationCntx() and its 
static ServletContext
1520fca0e3 is described below

commit 1520fca0e320bb42b3834b65bd8899035f78a09f
Author: Mridul Pathak <[email protected]>
AuthorDate: Tue Oct 27 19:57:24 2026 +0530

    Remove ApiContextListener.getApplicationCntx() and its static ServletContext
    
    OFBizOpenApiReader and OpenApiUtil reached the dispatcher and delegator 
through a deprecated, JVM-wide static ServletContext kept by 
ApiContextListener. OpenApiResource now takes the dispatcher from its injected 
ServletContext and passes the delegator and dispatcher names to the reader 
through the swagger userDefinedOptions (swagger hands the reader a JSON copy of 
its configuration, so objects cannot be passed). 
OpenApiUtil.getAttributeSchema, getInSchema and getOutSchema take a Deleg [...]
---
 .../ofbiz/ws/rs/listener/ApiContextListener.java   | 20 +----------------
 .../ofbiz/ws/rs/openapi/OFBizOpenApiReader.java    | 23 ++++++++++---------
 .../ofbiz/ws/rs/resources/OpenApiResource.java     |  6 ++++-
 .../org/apache/ofbiz/ws/rs/util/OpenApiUtil.java   | 23 +++++++++----------
 .../ws/rs/openapi/OFBizOpenApiReaderTest.java      | 26 +++++++++++-----------
 .../ofbiz/ws/rs/resources/OpenApiResourceTest.java | 17 +++++++++++++-
 6 files changed, 58 insertions(+), 57 deletions(-)

diff --git 
a/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/listener/ApiContextListener.java
 
b/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/listener/ApiContextListener.java
index d8f96f9308..dfb5ef943b 100644
--- 
a/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/listener/ApiContextListener.java
+++ 
b/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/listener/ApiContextListener.java
@@ -44,8 +44,6 @@ import jakarta.servlet.ServletContextListener;
 public class ApiContextListener implements ServletContextListener {
 
     public static final String MODULE = ApiContextListener.class.getName();
-    // TODO: remove after the refactoring of OFBizOpenApiReader
-    private static ServletContext servletContext = null;
 
     /**
      * {@inheritDoc}
@@ -57,7 +55,7 @@ public class ApiContextListener implements 
ServletContextListener {
      */
     @Override
     public void contextInitialized(ServletContextEvent sce) {
-        servletContext = sce.getServletContext();
+        ServletContext servletContext = sce.getServletContext();
         Delegator delegator = 
DelegatorFactory.getDelegator(servletContext.getInitParameter("entityDelegatorName"));
         LocalDispatcher dispatcher = 
ServiceContainer.getLocalDispatcher(servletContext.getInitParameter("localDispatcherName"),
 delegator);
         Debug.logInfo("Api Jersey Context initialized, delegator " + delegator 
+ ", dispatcher", MODULE);
@@ -81,20 +79,4 @@ public class ApiContextListener implements 
ServletContextListener {
         context.removeAttribute("security");
         context = null;
     }
-
-
-    /**
-     * Returns the servlet context stored at initialization time.
-     *
-     * @return the application {@link ServletContext}, or {@code null} if the
-     *         context has not yet been initialized
-     * @deprecated Temporary workaround to provide servlet context access to
-     *             {@code OFBizOpenApiReader}; will be removed once that class
-     *             is refactored
-     */
-    // TODO: remove after the refactoring of OFBizOpenApiReader
-    @Deprecated
-    public static ServletContext getApplicationCntx() {
-        return servletContext;
-    }
 }
diff --git 
a/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/openapi/OFBizOpenApiReader.java
 
b/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/openapi/OFBizOpenApiReader.java
index d050a4a474..7ee69bf77f 100644
--- 
a/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/openapi/OFBizOpenApiReader.java
+++ 
b/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/openapi/OFBizOpenApiReader.java
@@ -26,15 +26,16 @@ import java.util.Set;
 
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.entity.Delegator;
+import org.apache.ofbiz.entity.DelegatorFactory;
 import org.apache.ofbiz.service.DispatchContext;
 import org.apache.ofbiz.service.GenericServiceException;
 import org.apache.ofbiz.service.LocalDispatcher;
 import org.apache.ofbiz.service.ModelParam;
 import org.apache.ofbiz.service.ModelService;
-import org.apache.ofbiz.webapp.WebAppUtil;
+import org.apache.ofbiz.service.ServiceContainer;
 import org.apache.ofbiz.ws.rs.core.OFBizApiConfig;
 import org.apache.ofbiz.ws.rs.core.ResponseStatus;
-import org.apache.ofbiz.ws.rs.listener.ApiContextListener;
 import org.apache.ofbiz.ws.rs.model.ModelApi;
 import org.apache.ofbiz.ws.rs.model.ModelMapping;
 import org.apache.ofbiz.ws.rs.model.ModelOperation;
@@ -64,7 +65,6 @@ import io.swagger.v3.oas.models.responses.ApiResponse;
 import io.swagger.v3.oas.models.responses.ApiResponses;
 import io.swagger.v3.oas.models.security.SecurityRequirement;
 import io.swagger.v3.oas.models.tags.Tag;
-import jakarta.servlet.ServletContext;
 import jakarta.ws.rs.HttpMethod;
 import jakarta.ws.rs.core.HttpHeaders;
 import jakarta.ws.rs.core.Response;
@@ -90,11 +90,12 @@ public final class OFBizOpenApiReader extends Reader 
implements OpenApiReader {
     }
 
     @Override
-    @SuppressWarnings("deprecation")
     public OpenAPI read(Set<Class<?>> classes, Map<String, Object> resources) {
         openApi = super.read(classes, resources);
-        ServletContext servletContext = 
ApiContextListener.getApplicationCntx();
-        LocalDispatcher dispatcher = WebAppUtil.getDispatcher(servletContext);
+        // Swagger hands the reader a JSON copy of the configuration, so the 
web application passes names, not objects
+        Map<String, Object> userDefinedOptions = 
config.getUserDefinedOptions();
+        Delegator delegator = DelegatorFactory.getDelegator((String) 
userDefinedOptions.get("delegatorName"));
+        LocalDispatcher dispatcher = 
ServiceContainer.getLocalDispatcher((String) 
userDefinedOptions.get("dispatcherName"), delegator);
         context = dispatcher.getDispatchContext();
         initializeStdOpenApiComponents();
         addPredefinedSchemas();
@@ -175,7 +176,7 @@ public final class OFBizOpenApiReader extends Reader 
implements OpenApiReader {
                 pathParameter.setRequired(true);
                 pathParameter.setName(pathParam);
                 pathParameter.setDescription(mdParam != null ? 
mdParam.getShortDisplayDescription() : "");
-                
pathParameter.setSchema(OpenApiUtil.getAttributeSchema(service, mdParam));
+                
pathParameter.setSchema(OpenApiUtil.getAttributeSchema(context.getDelegator(), 
service, mdParam));
                 operation.addParametersItem(pathParameter);
             }
             String verb = op.getVerb().toUpperCase();
@@ -295,15 +296,15 @@ public final class OFBizOpenApiReader extends Reader 
implements OpenApiReader {
     }
 
     private void addServiceOutSchema(ModelService service) {
-        schemas.put("api.response." + service.getName() + ".success", 
OpenApiUtil.getOutSchema(service));
+        schemas.put("api.response." + service.getName() + ".success", 
OpenApiUtil.getOutSchema(context.getDelegator(), service));
     }
 
     private void addServiceInSchema(ModelService service, ModelOperation op) {
-        schemas.put("api.request." + service.getName(), 
OpenApiUtil.getInSchema(service, op));
+        schemas.put("api.request." + service.getName(), 
OpenApiUtil.getInSchema(context.getDelegator(), service, op));
     }
 
     private void addServiceInSchema(ModelService service) {
-        schemas.put("api.request." + service.getName(), 
OpenApiUtil.getInSchema(service, null));
+        schemas.put("api.request." + service.getName(), 
OpenApiUtil.getInSchema(context.getDelegator(), service, null));
     }
 
     private void addPredefinedSchemas() {
@@ -363,7 +364,7 @@ public final class OFBizOpenApiReader extends Reader 
implements OpenApiReader {
                 if (statusType.getStatusCode() > 399) {
                     schemas.put(schemaName, 
OpenApiUtil.getGenericErrorSchema(null));
                 } else {
-                    schemas.put(schemaName, OpenApiUtil.getOutSchema(service));
+                    schemas.put(schemaName, 
OpenApiUtil.getOutSchema(context.getDelegator(), service));
                 }
 
             }
diff --git 
a/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/resources/OpenApiResource.java
 
b/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/resources/OpenApiResource.java
index 6a3f418824..def7089ace 100644
--- 
a/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/resources/OpenApiResource.java
+++ 
b/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/resources/OpenApiResource.java
@@ -25,6 +25,8 @@ import java.util.stream.Stream;
 import org.apache.ofbiz.base.util.UtilMisc;
 import org.apache.ofbiz.base.util.UtilProperties;
 import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.service.LocalDispatcher;
+import org.apache.ofbiz.webapp.WebAppUtil;
 import org.apache.ofbiz.ws.rs.openapi.OFBizOpenApiReader;
 import org.apache.ofbiz.ws.rs.openapi.OFBizResourceScanner;
 
@@ -115,7 +117,9 @@ public final class OpenApiResource {
         basicAuthScheme.setScheme("basic");
         openApi.schemaRequirement(basicAuthScheme.getName(), basicAuthScheme);
 
-        Map<String, Object> userDefinedOptions = 
UtilMisc.toMap("apiGroupPath", apiGroupPath);
+        LocalDispatcher dispatcher = WebAppUtil.getDispatcher(context);
+        Map<String, Object> userDefinedOptions = 
UtilMisc.toMap("apiGroupPath", apiGroupPath,
+                "delegatorName", dispatcher.getDelegator().getDelegatorName(), 
"dispatcherName", dispatcher.getName());
 
         SwaggerConfiguration config = new SwaggerConfiguration()
                 .openAPI(openApi.info(buildOpenApiInfo()))
diff --git 
a/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/util/OpenApiUtil.java 
b/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/util/OpenApiUtil.java
index 9dd71ac0ed..d3175b535d 100644
--- 
a/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/util/OpenApiUtil.java
+++ 
b/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/util/OpenApiUtil.java
@@ -36,10 +36,8 @@ import org.apache.ofbiz.entity.model.ModelEntity;
 import org.apache.ofbiz.entity.model.ModelField;
 import org.apache.ofbiz.service.ModelParam;
 import org.apache.ofbiz.service.ModelService;
-import org.apache.ofbiz.webapp.WebAppUtil;
 import org.apache.ofbiz.ws.rs.common.AuthenticationScheme;
 import org.apache.ofbiz.ws.rs.core.ResponseStatus;
-import org.apache.ofbiz.ws.rs.listener.ApiContextListener;
 import org.apache.ofbiz.ws.rs.model.ModelOperation;
 
 import io.swagger.v3.oas.models.headers.Header;
@@ -345,10 +343,11 @@ public final class OpenApiUtil {
      * that are not optional are added to the required list. Parameters without
      * a known OpenAPI type mapping are silently skipped.</p>
      *
+     * @param delegator the {@link Delegator} used to look up entity 
definitions
      * @param service the {@link ModelService} for which to build the input 
schema
      * @return an OpenAPI {@link Schema} representing the service request body
      */
-    public static Schema<Object> getInSchema(ModelService service, 
ModelOperation op) {
+    public static Schema<Object> getInSchema(Delegator delegator, ModelService 
service, ModelOperation op) {
         Schema<Object> parentSchema = new Schema<Object>();
         parentSchema.setDescription("In Schema for service: " + 
service.getName() + " request");
         parentSchema.setType("object");
@@ -359,7 +358,7 @@ public final class OpenApiUtil {
                 if (!param.isOptional()) {
                     required.add(name);
                 }
-                Schema<?> attrSchema = getAttributeSchema(service, param);
+                Schema<?> attrSchema = getAttributeSchema(delegator, service, 
param);
                 if (attrSchema != null) {
                     parentSchema.addProperty(name, attrSchema);
                 }
@@ -377,13 +376,13 @@ public final class OpenApiUtil {
      * is found, or if a {@code Map} type parameter has no entity name or child
      * attributes defined.</p>
      *
+     * @param delegator the {@link Delegator} used to look up entity 
definitions
      * @param service the {@link ModelService} owning the parameter
      * @param param   the {@link ModelParam} to build a schema for
      * @return the OpenAPI {@link Schema} for the parameter, or {@code null} if
      *         the parameter cannot be mapped
      */
-    @SuppressWarnings("deprecation")
-    public static Schema<?> getAttributeSchema(ModelService service, 
ModelParam param) {
+    public static Schema<?> getAttributeSchema(Delegator delegator, 
ModelService service, ModelParam param) {
         Schema<?> schema = null;
         if (param == null) {
             Debug.logWarning("ModelParam is null - ignored.", MODULE);
@@ -403,13 +402,12 @@ public final class OpenApiUtil {
         }
 
         List<ModelParam> children = param.getChildren();
-        Delegator delegator = 
WebAppUtil.getDelegator(ApiContextListener.getApplicationCntx());
         if (schema instanceof ArraySchema) {
             ArraySchema arrSch = (ArraySchema) schema;
             if (LIST_TYPE_MAP.containsKey(param.getName())) {
                 
arrSch.setItems(getSchemaForModel(LIST_TYPE_MAP.get(param.getName())));
             } else {
-                arrSch.setItems(children.size() > 0 ? 
getAttributeSchema(service, children.get(0)) : new StringSchema());
+                arrSch.setItems(children.size() > 0 ? 
getAttributeSchema(delegator, service, children.get(0)) : new StringSchema());
             }
         } else if (schema instanceof MapSchema) {
             if (isTypeGenericEntityOrGenericValue(param.getType())) {
@@ -435,7 +433,7 @@ public final class OpenApiUtil {
                     if (!param.isOptional()) {
                         required.add(childParam.getName());
                     }
-                    schema.addProperty(childParam.getName(), 
getAttributeSchema(service, childParam));
+                    schema.addProperty(childParam.getName(), 
getAttributeSchema(delegator, service, childParam));
                 }
                 schema.setRequired(required);
             }
@@ -452,10 +450,11 @@ public final class OpenApiUtil {
      * {@code statusDescription}, and {@code successMessage} properties.
      * Service output parameters are nested under a {@code data} property.</p>
      *
+     * @param delegator the {@link Delegator} used to look up entity 
definitions
      * @param service the {@link ModelService} for which to build the output 
schema
      * @return an OpenAPI {@link Schema} representing the service response body
      */
-    public static Schema<Object> getOutSchema(ModelService service) {
+    public static Schema<Object> getOutSchema(Delegator delegator, 
ModelService service) {
         Schema<Object> parentSchema = new Schema<Object>();
         parentSchema.setDescription("Out Schema for service: " + 
service.getName() + " response");
         parentSchema.setType("object");
@@ -466,9 +465,9 @@ public final class OpenApiUtil {
         parentSchema.addProperty("data", dataSchema);
         service.getOutParamNamesMap().forEach((name, type) -> {
             if (!name.equals(RestApiUtil.RESPONSE_STATUS_KEY)) {
-                Schema<?> attrSchema = getAttributeSchema(service, 
service.getParam(name));
+                Schema<?> attrSchema = getAttributeSchema(delegator, service, 
service.getParam(name));
                 if (attrSchema != null) {
-                    dataSchema.addProperty(name, getAttributeSchema(service, 
service.getParam(name)));
+                    dataSchema.addProperty(name, getAttributeSchema(delegator, 
service, service.getParam(name)));
                 }
             }
         });
diff --git 
a/framework/rest-api/src/test/java/org/apache/ofbiz/ws/rs/openapi/OFBizOpenApiReaderTest.java
 
b/framework/rest-api/src/test/java/org/apache/ofbiz/ws/rs/openapi/OFBizOpenApiReaderTest.java
index 0f9f976a92..da06ce4221 100644
--- 
a/framework/rest-api/src/test/java/org/apache/ofbiz/ws/rs/openapi/OFBizOpenApiReaderTest.java
+++ 
b/framework/rest-api/src/test/java/org/apache/ofbiz/ws/rs/openapi/OFBizOpenApiReaderTest.java
@@ -28,8 +28,11 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.ofbiz.entity.Delegator;
+import org.apache.ofbiz.entity.DelegatorFactory;
 import org.apache.ofbiz.service.DispatchContext;
 import org.apache.ofbiz.service.LocalDispatcher;
+import org.apache.ofbiz.service.ServiceContainer;
 import org.apache.ofbiz.ws.rs.core.OFBizApiConfig;
 import org.apache.ofbiz.ws.rs.model.ModelApi;
 import org.apache.ofbiz.ws.rs.model.ModelOperation;
@@ -43,7 +46,6 @@ import io.swagger.v3.oas.integration.SwaggerConfiguration;
 import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.Operation;
 import io.swagger.v3.oas.models.PathItem;
-import jakarta.servlet.ServletContext;
 
 class OFBizOpenApiReaderTest {
 
@@ -116,27 +118,24 @@ class OFBizOpenApiReaderTest {
     }
 
     /**
-     * Sets up all mocks (dispatcher, servlet context, static access, API 
model)
+     * Sets up all mocks (delegator and dispatcher lookup, API model)
      * and runs reader.read(...), returning the resulting OpenAPI object.
      */
-    @SuppressWarnings("deprecation")
     private OpenAPI buildOpenApi() throws Exception {
+        Delegator delegator = mock(Delegator.class);
         LocalDispatcher dispatcher = mock(LocalDispatcher.class);
         DispatchContext dctx = mock(DispatchContext.class);
         when(dispatcher.getDispatchContext()).thenReturn(dctx);
+        when(dctx.getDelegator()).thenReturn(delegator);
 
-        try (MockedStatic<org.apache.ofbiz.ws.rs.listener.ApiContextListener> 
ctxMock =
-                        
Mockito.mockStatic(org.apache.ofbiz.ws.rs.listener.ApiContextListener.class);
-                MockedStatic<org.apache.ofbiz.webapp.WebAppUtil> webMock =
-                        
Mockito.mockStatic(org.apache.ofbiz.webapp.WebAppUtil.class);
+        try (MockedStatic<DelegatorFactory> delegatorMock = 
Mockito.mockStatic(DelegatorFactory.class);
+                MockedStatic<ServiceContainer> dispatcherMock = 
Mockito.mockStatic(ServiceContainer.class);
                 MockedStatic<OFBizApiConfig> apiMock = 
Mockito.mockStatic(OFBizApiConfig.class)) {
 
-            ServletContext servletContext = mock(ServletContext.class);
+            delegatorMock.when(() -> 
DelegatorFactory.getDelegator("testDelegator"))
+                    .thenReturn(delegator);
 
-            
ctxMock.when(org.apache.ofbiz.ws.rs.listener.ApiContextListener::getApplicationCntx)
-                    .thenReturn(servletContext);
-
-            webMock.when(() -> 
org.apache.ofbiz.webapp.WebAppUtil.getDispatcher(servletContext))
+            dispatcherMock.when(() -> 
ServiceContainer.getLocalDispatcher("testDispatcher", delegator))
                     .thenReturn(dispatcher);
 
             ModelOperation op = mock(ModelOperation.class);
@@ -169,7 +168,8 @@ class OFBizOpenApiReaderTest {
             when(dctx.getModelService("testService")).thenReturn(service);
 
             SwaggerConfiguration config = new SwaggerConfiguration();
-            config.setUserDefinedOptions(Map.of("apiGroupPath", "test"));
+            config.setUserDefinedOptions(Map.of("apiGroupPath", "test",
+                    "delegatorName", "testDelegator", "dispatcherName", 
"testDispatcher"));
             reader.setConfiguration(config);
 
             return reader.read(Set.of(), Map.of());
diff --git 
a/framework/rest-api/src/test/java/org/apache/ofbiz/ws/rs/resources/OpenApiResourceTest.java
 
b/framework/rest-api/src/test/java/org/apache/ofbiz/ws/rs/resources/OpenApiResourceTest.java
index 61b3dddd1b..8933849bbc 100644
--- 
a/framework/rest-api/src/test/java/org/apache/ofbiz/ws/rs/resources/OpenApiResourceTest.java
+++ 
b/framework/rest-api/src/test/java/org/apache/ofbiz/ws/rs/resources/OpenApiResourceTest.java
@@ -23,6 +23,8 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import org.apache.ofbiz.entity.Delegator;
+import org.apache.ofbiz.service.LocalDispatcher;
 import org.apache.ofbiz.ws.rs.openapi.OFBizOpenApiReader;
 import org.apache.ofbiz.ws.rs.openapi.OFBizResourceScanner;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -30,6 +32,7 @@ import org.junit.jupiter.params.provider.CsvSource;
 import org.mockito.MockedConstruction;
 import org.mockito.Mockito;
 
+import jakarta.servlet.ServletContext;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.ws.rs.core.HttpHeaders;
 import jakarta.ws.rs.core.Response;
@@ -53,12 +56,24 @@ class OpenApiResourceTest {
         when(request.getServerPort()).thenReturn(8080);
         when(request.getContextPath()).thenReturn("/ofbiz");
 
+        // Mock the servlet context that holds the web application dispatcher
+        Delegator delegator = mock(Delegator.class);
+        when(delegator.getDelegatorName()).thenReturn("default");
+        LocalDispatcher dispatcher = mock(LocalDispatcher.class);
+        when(dispatcher.getDelegator()).thenReturn(delegator);
+        when(dispatcher.getName()).thenReturn("rest-api");
+        ServletContext servletContext = mock(ServletContext.class);
+        when(servletContext.getAttribute("dispatcher")).thenReturn(dispatcher);
+
         OpenApiResource resource = new OpenApiResource();
 
-        // inject request via reflection (since field is @Context)
+        // inject request and servlet context via reflection (since fields are 
@Context)
         java.lang.reflect.Field f = 
OpenApiResource.class.getDeclaredField("request");
         f.setAccessible(true);
         f.set(resource, request);
+        java.lang.reflect.Field c = 
OpenApiResource.class.getDeclaredField("context");
+        c.setAccessible(true);
+        c.set(resource, servletContext);
 
         // Mock heavy Swagger builder
         try 
(MockedConstruction<org.apache.ofbiz.ws.rs.openapi.OFBizOpenApiReader> 
readerMock =

Reply via email to