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