context: So I've been trying to work with SPEL and Mono instance as input that would be parsed to an instance of Mono but SPEL isn't able to do the conversion and handle a Mono instance
@UtilityClass
public class ReactiveSpelUtil {
private static ExpressionParser SPEL_PARSER = new SpelExpressionParser();
private static final EvaluationContext STANDARD_EVALUATION_CONTEXT = new StandardEvaluationContext();
@SuppressWarnings("ALL")
public static Mono<Boolean> evaluate(final Object rootObject, String expression) {
STANDARD_EVALUATION_CONTEXT.setVariable(rootObject.getClass().getSimpleName(),rootObject);
return SPEL_PARSER.parseExpression(expression)
.getValue(STANDARD_EVALUATION_CONTEXT, Mono.class);
}
// expression sample is #rootObject.age>20 , age is wrapped in Mono
}
The Problem: I usually get error like this EL1013E: Cannot compare instances of class reactor.core.publisher.MonoJust and class java.lang.Integer, and the problem is that I can't do the parsing inside the map of the mono instance itself age
because the expressions are built in a way that can be parsed only as per the above code, so is there any way to achieve working with Mono instances as part of (within) SPEL expression?
Comment From: rstoyanchev
SpEL wasn't designed with this in mind and I'm not sure how it would work out more generally with both Flux
and Mono
potentially in the expression, and/or in the output type. Can you provide a little more on the context in which ReactiveSpelUtil
is used so that the use case is more clear?
Comment From: saeed-abdelhalim
Hello, it will be more or less like the following
@UtilityClass
public class ReactiveSpelUtil {
private static ExpressionParser SPEL_PARSER = new SpelExpressionParser();
@SuppressWarnings("ALL")
public static Mono<Boolean> evaluate(final RootObject rootObject, String expression) {
EvaluationContext STANDARD_EVALUATION_CONTEXT = new StandardEvaluationContext(rootObject);
STANDARD_EVALUATION_CONTEXT.setVariable(rootObject.getClass().getSimpleName(), rootObject);
return SPEL_PARSER.parseExpression(expression)
.getValue(STANDARD_EVALUATION_CONTEXT, Mono.class);
}
public static void main(String[] args) {
RootObject rootObject = new RootObject(Mono.just(new Person(21f, "Saeed")));
evaluate(rootObject, "getPerson().getAge()>20 and getPerson().getName().equalsIgnoreCase(\"Saeed\")")
.subscribe(System.out::println);
}
@Getter
@AllArgsConstructor
static class Person {
private float age;
private String name;
}
@Getter
@AllArgsConstructor
static class RootObject {
private Mono<Person> person;
}
}
I know using getPerson().getAge()
in the expression doesn't make sense because getPerson()
is Mono, but that's how the expressions I want to parse is built, I tried to find a way to work with Mono like using something like this expression
"{T(reactor.core.publisher.Mono).from(getPerson()).block().getAge()>20}"
as I can't use .map(..)
while SPEL doesn't supports lambdas but this expression is blocking which what I need to avoid and for sure it returns Boolean
not Mono
Comment From: rstoyanchev
You can add a transformation that resolves the Person
before pass it to SpEL. Something like this:
public static Mono<Boolean> evaluate(final RootObject rootObject, String expression) {
return rootObject.getPerson().map(person -> {
EvaluationContext STANDARD_EVALUATION_CONTEXT = new StandardEvaluationContext(person);
STANDARD_EVALUATION_CONTEXT.setVariable(person.getClass().getSimpleName(), person);
return SPEL_PARSER.parseExpression(expression)
.getValue(STANDARD_EVALUATION_CONTEXT, boolean.class);
});
}
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: spring-projects-issues
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.