I have a custom annotation as follows.
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnApiVersionConditional.class)
public @interface ConditionalOnApiVersion {
    int[] value() default 5;
    String property();
}
OnApiVersionConditional is,
public class OnApiVersionConditional implements Condition {
  @Override
    public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) {
        final MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(ConditionalOnApiVersion.class.getName());
       attributes.get("value");
        final String inputVersion = context.getEnvironment().getProperty("userInputVersion");
    }
In my Bean annotation,
  @Bean
  @ConditionalOnApiVersion(value = {6, 7}, property = "userInputVersion")
There are beans with single version matching also, like
@Bean
@ConditionalOnApiVersion(value = 8, property = "userInputVersion")
I would like to validate the userInput version from the property file to the available Beans supported versions. Not sure, how can i get the value, iterate and compare with userInoutVersion. The value could be 8 or {6,7} as an int array. Not sure, how can i iterate the value to check if any of the value is matching with the input version.
final List apiVersions = attributes.get("value").stream().collect(Collectors.toList());
Question:
How to iterate attributes.get("value") and compare with userInputVersion?
attributes.get("value") returns a List of Object.
I tried the below code,
final List<Object> apiVersions = attributes.get("value").stream().collect(Collectors.toList());
boolean result = apiVersions.stream().anyMatch(version -> (int)version == Integer.parseInt(userInputVersion));
But getting the below error int eh 2nd line anyMatch,
java.lang.ClassCastException: [I cannot be cast to java.lang.Integer
Thanks
You have defined a good custom annotation which uses Spring's @Conditional and this process will only create beans if the property named 'property' is present in the array value.
The annotation defines these two variables as follows:
When you use the metadata to retrieve these values, Spring returns them as Objects. Casting these objects into the types you defined them as is a key step. There is no need for streams as iterating an int[] array is trivial.
I tested various forms of your annotation (value = 5, value = {6,7}, etc) and found the following code to work well (@Conditional beans were only created if the version was correct).
public class OnApiVersionConditional implements Condition {
@Override
public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) {
    final MultiValueMap<String, Object> attributes = metadata
            .getAllAnnotationAttributes(ConditionalOnApiVersion.class.getName());
    // 1.  Retrieve the property name from the annotation (i.e. userInputVersion)
    List<Object> propertyObject = attributes.get("property");
    // 2.  Cast it to a String
    String propertyName = (String)propertyObject.get(0);
    // 3.  Retrieve the value 
    List<Object> list = attributes.get("value");
    // 4.  Cast it to int[]
    int[] values = (int[])list.get(0);
    // 5.  Look up the actual version (based on the property name in the annotation)
    final String inputVersion = context.getEnvironment().getProperty(propertyName);
    // Assume it is an integer? 
    int version = Integer.valueOf(inputVersion).intValue();
    // 6.  Scan the supported version; look to match against actual version
    for (int i : values)
        if (i == version)
            return true;
    // The version is not supported
    return false;
}
}
This method could be improved by validating both property and value; returning false if either of these contains bad/empty values, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With