azure-sdk-for-java: [BUG] Hashmap to Map Cast Exception in TargetingFilter.java when using Application Configuration
Describe the bug
When checking if a feature flag is enabled the exception java.lang.ClassCastException is thrown.
Exception or Stack Trace
Caused by: java.lang.ClassCastException: java.util.HashMap$Values cannot be cast to java.util.Map
at com.azure.spring.cloud.feature.management.filters.TargetingFilter.evaluate(TargetingFilter.java:134) ~[spring-cloud-azure-feature-management-4.8.0.jar:4.8.0]
at com.azure.spring.cloud.feature.management.FeatureManager.isFeatureOn(FeatureManager.java:114) ~[spring-cloud-azure-feature-management-4.8.0.jar:4.8.0]
at com.azure.spring.cloud.feature.management.FeatureManager.lambda$checkFeature$2(FeatureManager.java:106) ~[spring-cloud-azure-feature-management-4.8.0.jar:4.8.0]
at java.util.stream.MatchOps$1MatchSink.accept(MatchOps.java:90) ~[?:1.8.0_332]
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) ~[?:1.8.0_332]
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) ~[?:1.8.0_332]
at java.util.HashMap$ValueSpliterator.tryAdvance(HashMap.java:1673) ~[?:1.8.0_332]
at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126) ~[?:1.8.0_332]
at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:499) ~[?:1.8.0_332]
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:486) ~[?:1.8.0_332]
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) ~[?:1.8.0_332]
at java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230) ~[?:1.8.0_332]
at java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196) ~[?:1.8.0_332]
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:1.8.0_332]
at java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:516) ~[?:1.8.0_332]
at com.azure.spring.cloud.feature.management.FeatureManager.checkFeature(FeatureManager.java:106) ~[spring-cloud-azure-feature-management-4.8.0.jar:4.8.0]
at com.azure.spring.cloud.feature.management.FeatureManager.isEnabledAsync(FeatureManager.java:63) ~[spring-cloud-azure-feature-management-4.8.0.jar:4.8.0]
at our java code
To Reproduce Setup an http request or a piece of code that attempts to check if a feature flag is enabled. Make sure the feature flag has a feature filter with the default percentage set to 0% and an allowed group that is set to 100%. Running this code will cause the cast exception to fire.
Code Snippet
Here is my Java code that initiates the call to check if a flag is enabled:
Boolean.TRUE.equals(featureManager.isEnabledAsync("someFeatureFlag").block())
This is the decompiled code that is throwing the exception from TargetingFilter.java:
Map<String, Map<String, Object>> exclusionMap = (Map<String, Map<String, Object>>) parameters
.get(EXCLUSION);
Map<String, Object> exclusionAsLists = new HashMap<>();
if (exclusionMap != null) {
exclusionAsLists.put(USERS, exclusionMap.getOrDefault(USERS, new HashMap<String, Object>()).values());
exclusionAsLists.put(GROUPS, exclusionMap.getOrDefault(GROUPS, new HashMap<String, Object>()).values());
}
The error is specifically thrown on this line when the default branch is taken:
exclusionAsLists.put(USERS, exclusionMap.getOrDefault(USERS, new HashMap<String, Object>()).values());
Expected behavior No cast exception is thrown, and that the feature flag check returns either a true or false.
Screenshots
Here is the state of the debugger right before the exception is thrown:
Setup (please complete the following information):
- OS: MacOS 13.4.1 (22F82)
- IDE: IntelliJ
- Library/Libraries: spring-cloud-azure-feature-management-4.8.0.jar
- Java version: 8
- App Server/Environment: Tomcat
- Frameworks: Spring Boot 2.7.12
If you suspect a dependency version mismatch (e.g. you see NoClassDefFoundError, NoSuchMethodError or similar), please check out Troubleshoot dependency version conflict article first. If it doesn’t provide solution for the problem, please provide:
- verbose dependency tree (
mvn dependency:tree -Dverbose) - exception message, full stack trace, and any available logs
Additional context I am using a remote configuration store. My local app is talking with a config store in the portal. It connects via a connection string.
Here are the related configured properties:
spring.cloud.azure.appconfiguration.enabled=true
spring.cloud.azure.appconfiguration.stores[0].feature-flags.enabled=true
spring.cloud.azure.appconfiguration.stores[0].connection-string=<Connection string redacted>
spring.cloud.azure.appconfiguration.stores[0].enabled=true
spring.cloud.azure.appconfiguration.stores[0].monitoring.enabled=true
spring.cloud.azure.appconfiguration.stores[0].monitoring.refresh-interval=30s
spring.cloud.azure.appconfiguration.stores[0].monitoring.triggers[0].key=sentinel
spring.cloud.azure.appconfiguration.stores[0].monitoring.feature-flag-refresh-interval=30s
spring.cloud.azure.appconfiguration.stores[0].feature-flags.selects[0].label-filter=,${spring.profiles.active}
The config store has one key/value called sentinel that allows for dynamic refresh and one feature flag with a feature filter. Here is a screenshot of the details. The value past Tenant: is a guid:
Information Checklist Kindly make sure that you have added all the following information above and checkoff the required fields otherwise we will treat the issuer as an incomplete report
- [-] Bug Description Added
- [-] Repro Steps Added
- [-] Setup information Added
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 28 (13 by maintainers)
Reverting to 4.7.0 should fix this for now if you are running into this issue. PR is up for a fix for this https://github.com/Azure/azure-sdk-for-java/pull/35920.