From 2f016edc488ce00d5cf80aa38e2b7f7d6fccf90d Mon Sep 17 00:00:00 2001 From: Abhijeet Date: Fri, 7 Mar 2025 00:13:17 +0530 Subject: [PATCH 1/3] chore: Segregate organization flags based on orgnization id --- .../FeatureFlaggedMethodInvokerAspect.java | 38 +++++++++++++++++-- .../server/helpers/ReactiveContextUtils.java | 21 ++++++++++ .../PluginTriggerSolutionCEImpl.java | 17 +++++---- .../services/ce/FeatureFlagServiceCE.java | 2 +- .../services/ce/FeatureFlagServiceCEImpl.java | 11 +++--- .../services/ce/SessionUserServiceCEImpl.java | 3 ++ .../ce/ActionExecutionSolutionCEImpl.java | 21 +++++----- .../ce/DatasourceTriggerSolutionCEImpl.java | 34 ++++++++++------- ...FeatureFlaggedMethodInvokerAspectTest.java | 13 +++++-- .../services/ce/FeatureFlagServiceCETest.java | 6 ++- 10 files changed, 120 insertions(+), 46 deletions(-) create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ReactiveContextUtils.java diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java index 40659e939ea7..f51ede89281d 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java @@ -15,11 +15,13 @@ import org.aspectj.lang.reflect.MethodSignature; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.beans.Introspector; import java.lang.reflect.Method; +import java.lang.reflect.Parameter; @RequiredArgsConstructor @Aspect @@ -64,9 +66,23 @@ private Object invokeMethod(ProceedingJoinPoint joinPoint, FeatureFlagged annota } else if (Flux.class.isAssignableFrom(returnType)) { return featureFlagMono.flatMapMany(isSupported -> (Flux) invokeMethod(isSupported, joinPoint, method)); } + + // For supporting non-reactive methods with feature flagging annotation we need to extract organizationId from + // method arguments and then check if the feature flag is enabled for that organization. This hampers the code + // readability so avoid non-reactive methods for @FeatureFlagged unless the method is getting called from server + // internal flows where the user context is not provided. + String organizationId = extractOrganizationId(joinPoint.getArgs(), method.getParameters()); + + if (!StringUtils.hasLength(organizationId)) { + String errorMessage = + "Add missing organizationId parameter and enforce non-null value for orgnization-specific feature flags retrieval in non-reactive methods"; + AppsmithException exception = getInvalidAnnotationUsageException(method, errorMessage); + log.error(exception.getMessage()); + throw exception; + } // For non-reactive methods with feature flagging annotation we will be using the in memory feature flag cache // which is getting updated whenever the organization feature flags are updated. - return invokeMethod(isFeatureFlagEnabled(flagName), joinPoint, method); + return invokeMethod(isFeatureFlagEnabled(flagName, organizationId), joinPoint, method); } private Object invokeMethod(Boolean isFeatureSupported, ProceedingJoinPoint joinPoint, Method method) { @@ -106,10 +122,26 @@ AppsmithException getInvalidAnnotationUsageException(Method method, String error error); } - boolean isFeatureFlagEnabled(FeatureFlagEnum flagName) { - CachedFeatures cachedFeatures = featureFlagService.getCachedOrganizationFeatureFlags(); + boolean isFeatureFlagEnabled(FeatureFlagEnum flagName, String organizationId) { + CachedFeatures cachedFeatures = featureFlagService.getCachedOrganizationFeatureFlags(organizationId); return cachedFeatures != null && !CollectionUtils.isNullOrEmpty(cachedFeatures.getFeatures()) && Boolean.TRUE.equals(cachedFeatures.getFeatures().get(flagName.name())); } + + private String extractOrganizationId(Object[] args, Parameter[] parameters) { + if (args == null || parameters == null || args.length != parameters.length) { + return null; + } + + // First try to find parameter named exactly "organizationId" or "orgId" + for (int i = 0; i < parameters.length; i++) { + String paramName = parameters[i].getName(); + if ((paramName.equals("organizationId") || paramName.equals("orgId")) && args[i] instanceof String) { + return (String) args[i]; + } + } + + return null; + } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ReactiveContextUtils.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ReactiveContextUtils.java new file mode 100644 index 000000000000..693076daffdc --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ReactiveContextUtils.java @@ -0,0 +1,21 @@ +package com.appsmith.server.helpers; + +import com.appsmith.server.domains.User; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.context.ReactiveSecurityContextHolder; +import org.springframework.security.core.context.SecurityContext; +import reactor.core.publisher.Mono; + +@Slf4j +public class ReactiveContextUtils { + + public static Mono getCurrentUser() { + return ReactiveSecurityContextHolder.getContext() + .map(SecurityContext::getAuthentication) + .map(auth -> (User) auth.getPrincipal()) + .switchIfEmpty(Mono.defer(() -> { + log.error("No user found in the security context"); + return Mono.empty(); + })); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionCEImpl.java index bfa29a1b8b75..8da537ced59c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionCEImpl.java @@ -78,11 +78,6 @@ public Mono trigger( Mono pluginExecutorMono = pluginMono.flatMap(plugin -> pluginExecutorHelper.getPluginExecutor(Mono.just(plugin))); - // TODO: Flags are needed here for google sheets integration to support shared drive behind a flag - // Once thoroughly tested, this flag can be removed - Map featureFlagMap = - featureFlagService.getCachedOrganizationFeatureFlags().getFeatures(); - /* * Since there is no datasource provided, we are passing the Datasource Context connection and datasourceConfiguration as null. * We will leave the execution to respective plugin executor. @@ -91,9 +86,15 @@ public Mono trigger( Plugin plugin = pair.getT1(); PluginExecutor pluginExecutor = pair.getT2(); setHeadersToTriggerRequest(plugin, httpHeaders, triggerRequestDTO); - return setOrganizationAndInstanceId(triggerRequestDTO) - .flatMap(updatedTriggerRequestDTO -> ((PluginExecutor) pluginExecutor) - .triggerWithFlags(null, null, updatedTriggerRequestDTO, featureFlagMap)); + return setOrganizationAndInstanceId(triggerRequestDTO).flatMap(updatedTriggerRequestDTO -> { + // TODO: Flags are needed here for google sheets integration to support shared drive behind a + // flag once thoroughly tested, this flag can be removed + Map featureFlags = featureFlagService + .getCachedOrganizationFeatureFlags(updatedTriggerRequestDTO.getOrganizationId()) + .getFeatures(); + return ((PluginExecutor) pluginExecutor) + .triggerWithFlags(null, null, updatedTriggerRequestDTO, featureFlags); + }); }); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java index cce3d3402deb..4b8ea2bb4cce 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java @@ -42,5 +42,5 @@ Mono getAllRemoteFeaturesForOrganizationAndUpdateFeatureFlagsWithP Mono checkAndExecuteMigrationsForOrganizationFeatureFlags(Organization organization); - CachedFeatures getCachedOrganizationFeatureFlags(); + CachedFeatures getCachedOrganizationFeatureFlags(String organizationId); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java index b8362f034293..fa6750b6debc 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java @@ -13,7 +13,6 @@ import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SessionUserService; import com.appsmith.server.services.UserIdentifierService; -import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.util.StringUtils; @@ -40,9 +39,7 @@ public class FeatureFlagServiceCEImpl implements FeatureFlagServiceCE { private final FeatureFlagMigrationHelper featureFlagMigrationHelper; private static final long FEATURE_FLAG_CACHE_TIME_MIN = 120; - // TODO @CloudBilling: Remove once all the helper methods consuming @FeatureFlagged are converted to reactive - @Getter - private CachedFeatures cachedOrganizationFeatureFlags; + private Map cachedOrganizationFeatureFlags = new HashMap<>(); /** * This function checks if the feature is enabled for the current user. In case the user object is not present, @@ -185,7 +182,7 @@ public Mono> getOrganizationFeatures(String organizationId) return cacheableFeatureFlagHelper .fetchCachedOrganizationFeatures(organizationId) .map(cachedFeatures -> { - cachedOrganizationFeatureFlags = cachedFeatures; + cachedOrganizationFeatureFlags.put(organizationId, cachedFeatures); return cachedFeatures.getFeatures(); }) .switchIfEmpty(Mono.just(new HashMap<>())); @@ -200,4 +197,8 @@ public Mono> getOrganizationFeatures(String organizationId) public Mono checkAndExecuteMigrationsForOrganizationFeatureFlags(Organization organization) { return organizationService.checkAndExecuteMigrationsForOrganizationFeatureFlags(organization); } + + public CachedFeatures getCachedOrganizationFeatureFlags(String organizationId) { + return this.cachedOrganizationFeatureFlags.getOrDefault(organizationId, new CachedFeatures()); + } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/SessionUserServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/SessionUserServiceCEImpl.java index e004fc94973e..d24bfae8a26b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/SessionUserServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/SessionUserServiceCEImpl.java @@ -34,6 +34,9 @@ public class SessionUserServiceCEImpl implements SessionUserServiceCE { public static final String SPRING_SESSION_PATTERN = "spring:session:sessions:*"; private static final String SESSION_ATTRIBUTE = "sessionAttr:"; + // TODO @CloudBilling: Remove this method and resort to {@link ReactiveContextUtils#getCurrentUser()} to avoid + // adding the SessionUserService dependency where only current user session is required + @Deprecated @Override public Mono getCurrentUser() { return ReactiveSecurityContextHolder.getContext() diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java index 16d63cd7188b..a712ab29ced0 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java @@ -38,6 +38,7 @@ import com.appsmith.server.helpers.DatasourceAnalyticsUtils; import com.appsmith.server.helpers.DateUtils; import com.appsmith.server.helpers.PluginExecutorHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.newactions.base.NewActionService; import com.appsmith.server.newpages.base.NewPageService; import com.appsmith.server.plugins.base.PluginService; @@ -254,7 +255,6 @@ private Mono getTrueEnvironmentId( private Mono populateExecuteActionDTO(ExecuteActionDTO executeActionDTO, NewAction newAction) { Mono instanceIdMono = configService.getInstanceId(); Mono defaultOrganizationIdMono = organizationService.getDefaultOrganizationId(); - Mono systemInfoPopulatedExecuteActionDTOMono = actionExecutionSolutionHelper.populateExecuteActionDTOWithSystemInfo(executeActionDTO); @@ -755,17 +755,20 @@ protected Mono verifyDatasourceAndMakeRequest( .tag("plugin", plugin.getPackageName()) .name(ACTION_EXECUTION_DATASOURCE_CONTEXT) .tap(Micrometer.observation(observationRegistry))) - .flatMap(tuple2 -> { - DatasourceStorage datasourceStorage1 = tuple2.getT1(); - DatasourceContext resourceContext = tuple2.getT2(); + .zipWith(ReactiveContextUtils.getCurrentUser()) + .flatMap(objects -> { + DatasourceStorage datasourceStorage1 = objects.getT1().getT1(); + DatasourceContext resourceContext = objects.getT1().getT2(); + String organizationId = objects.getT2().getOrganizationId(); // Now that we have the context (connection details), execute the action. Instant requestedAt = Instant.now(); - Map features = featureFlagService.getCachedOrganizationFeatureFlags() != null - ? featureFlagService - .getCachedOrganizationFeatureFlags() - .getFeatures() - : Collections.emptyMap(); + Map features = + featureFlagService.getCachedOrganizationFeatureFlags(organizationId) != null + ? featureFlagService + .getCachedOrganizationFeatureFlags(organizationId) + .getFeatures() + : Collections.emptyMap(); // TODO: Flags are needed here for google sheets integration to support shared drive behind a flag // Once thoroughly tested, this flag can be removed diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceTriggerSolutionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceTriggerSolutionCEImpl.java index b934b4d0841b..de24bd474291 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceTriggerSolutionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceTriggerSolutionCEImpl.java @@ -108,26 +108,32 @@ public Mono trigger( final PluginExecutor pluginExecutor = tuple.getT3(); final Datasource datasource = tuple.getT4(); - // TODO: Flags are needed here for google sheets integration to support shared drive behind a flag - // Once thoroughly tested, this flag can be removed - Map featureFlagMap = featureFlagService.getCachedOrganizationFeatureFlags() != null - ? featureFlagService - .getCachedOrganizationFeatureFlags() - .getFeatures() - : Collections.emptyMap(); - return datasourceContextService .getDatasourceContext(datasourceStorage, plugin) // Now that we have the context (connection details), execute the action. // datasource remains unevaluated for datasource of DBAuth Type Authentication, // However the context comes from evaluated datasource. .flatMap(resourceContext -> populateTriggerRequestDto(triggerRequestDTO, datasource) - .flatMap(updatedTriggerRequestDTO -> ((PluginExecutor) pluginExecutor) - .triggerWithFlags( - resourceContext.getConnection(), - datasourceStorage.getDatasourceConfiguration(), - updatedTriggerRequestDTO, - featureFlagMap))); + .flatMap(updatedTriggerRequestDTO -> { + String organizationId = updatedTriggerRequestDTO.getOrganizationId(); + // TODO: Flags are needed here for google sheets integration to support shared + // drive behind a flag + // Once thoroughly tested, this flag can be removed + Map featureFlagMap = + featureFlagService.getCachedOrganizationFeatureFlags(organizationId) + != null + ? featureFlagService + .getCachedOrganizationFeatureFlags(organizationId) + .getFeatures() + : Collections.emptyMap(); + + return ((PluginExecutor) pluginExecutor) + .triggerWithFlags( + resourceContext.getConnection(), + datasourceStorage.getDatasourceConfiguration(), + updatedTriggerRequestDTO, + featureFlagMap); + })); }); // If the plugin hasn't implemented the trigger function, go for the default implementation diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java index 49c8607bc577..6dd8b017d134 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java @@ -20,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @SpringBootTest @@ -42,7 +43,8 @@ void setUp() { CachedFeatures cachedFeatures = new CachedFeatures(); cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE.name(), Boolean.FALSE)); - Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags()).thenReturn(cachedFeatures); + Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags(any())) + .thenReturn(cachedFeatures); } @Test @@ -110,7 +112,8 @@ void ceEeDiffMethodReturnsFlux_ceImplTest() { void ceEeSyncMethod_eeImplTest() { CachedFeatures cachedFeatures = new CachedFeatures(); cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE.name(), Boolean.TRUE)); - Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags()).thenReturn(cachedFeatures); + Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags(any())) + .thenReturn(cachedFeatures); String result = testComponent.ceEeSyncMethod("arg_"); assertEquals("arg_ee_impl_method", result); } @@ -125,7 +128,8 @@ void ceEeSyncMethod_ceImplTest() { void ceEeThrowAppsmithException_eeImplTest() { CachedFeatures cachedFeatures = new CachedFeatures(); cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE.name(), Boolean.TRUE)); - Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags()).thenReturn(cachedFeatures); + Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags(any())) + .thenReturn(cachedFeatures); assertThrows( AppsmithException.class, () -> testComponent.ceEeThrowAppsmithException("arg_"), @@ -136,7 +140,8 @@ void ceEeThrowAppsmithException_eeImplTest() { void ceEeThrowNonAppsmithException_eeImplTest_throwExceptionFromAspect() { CachedFeatures cachedFeatures = new CachedFeatures(); cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE.name(), Boolean.TRUE)); - Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags()).thenReturn(cachedFeatures); + Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags(any())) + .thenReturn(cachedFeatures); assertThrows( AppsmithException.class, () -> testComponent.ceEeThrowNonAppsmithException("arg_"), diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java index d615089f7ad4..646bdb962f2b 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java @@ -7,6 +7,7 @@ import com.appsmith.server.featureflags.CachedFeatures; import com.appsmith.server.featureflags.CachedFlags; import com.appsmith.server.helpers.FeatureFlagMigrationHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.services.CacheableFeatureFlagHelper; import com.appsmith.server.services.FeatureFlagService; import com.appsmith.server.services.OrganizationService; @@ -288,8 +289,9 @@ public void getOrganizationFeatureFlags_withDefaultOrganization_fetchLatestFlags @WithUserDetails(value = "api_user") public void getCachedOrganizationFeatureFlags_withDefaultOrganization_organizationFeatureFlagsAreCached() { + String orgId = ReactiveContextUtils.getCurrentUser().block().getOrganizationId(); // Assert that the cached feature flags are empty before the remote fetch - CachedFeatures cachedFeaturesBeforeRemoteCall = featureFlagService.getCachedOrganizationFeatureFlags(); + CachedFeatures cachedFeaturesBeforeRemoteCall = featureFlagService.getCachedOrganizationFeatureFlags(orgId); assertThat(cachedFeaturesBeforeRemoteCall.getFeatures()).hasSize(1); assertTrue(cachedFeaturesBeforeRemoteCall.getFeatures().get(ORGANIZATION_TEST_FEATURE.name())); @@ -305,7 +307,7 @@ public void getCachedOrganizationFeatureFlags_withDefaultOrganization_organizati // Check if the cached feature flags are updated after the remote fetch CachedFeatures cachedFeaturesAfterRemoteCall = - featureFlagService.getCachedOrganizationFeatureFlags(); + featureFlagService.getCachedOrganizationFeatureFlags(orgId); assertFalse(cachedFeaturesAfterRemoteCall.getFeatures().get(ORGANIZATION_TEST_FEATURE.name())); }) .verifyComplete(); From 0898bdff064eb6723dde50db2f8669db7a457eb4 Mon Sep 17 00:00:00 2001 From: Abhijeet Date: Fri, 7 Mar 2025 11:31:28 +0530 Subject: [PATCH 2/3] chore: Formating changes --- .../FeatureFlaggedMethodInvokerAspectTest.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java index ee8337a93c39..0e7efe18a718 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java @@ -151,16 +151,17 @@ void ceEeSyncWithoutOrganizationMethod_eeImplTest() { CachedFeatures cachedFeatures = new CachedFeatures(); cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE.name(), Boolean.TRUE)); Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags("organizationId")) - .thenReturn(cachedFeatures); + .thenReturn(cachedFeatures); try { testComponent.ceEeSyncMethodWithoutOrganization("arg_"); } catch (AppsmithException e) { - assertEquals(AppsmithError.INVALID_METHOD_LEVEL_ANNOTATION_USAGE.getMessage( - FeatureFlagged.class.getSimpleName(), - "TestComponentImpl", - "ceEeSyncMethodWithoutOrganization", - "Add missing organizationId parameter and enforce non-null value for orgnization-specific feature flags retrieval in non-reactive methods" - ), e.getMessage()); + assertEquals( + AppsmithError.INVALID_METHOD_LEVEL_ANNOTATION_USAGE.getMessage( + FeatureFlagged.class.getSimpleName(), + "TestComponentImpl", + "ceEeSyncMethodWithoutOrganization", + "Add missing organizationId parameter and enforce non-null value for orgnization-specific feature flags retrieval in non-reactive methods"), + e.getMessage()); } } } From 3751a96df64aea8aa6ce5d909cede21d0df84ebc Mon Sep 17 00:00:00 2001 From: Abhijeet Date: Wed, 12 Mar 2025 18:11:15 +0530 Subject: [PATCH 3/3] chore: Cleanup --- .../com/appsmith/server/helpers/ReactiveContextUtils.java | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ReactiveContextUtils.java diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ReactiveContextUtils.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ReactiveContextUtils.java deleted file mode 100644 index 023294d9a7ed..000000000000 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ReactiveContextUtils.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.appsmith.server.helpers; - -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class ReactiveContextUtils { - -}