Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow JsonNodeELResolver to invoke get and path #3996

Conversation

rssap
Copy link
Contributor

@rssap rssap commented Dec 7, 2024

This PR proposes a change to the JsonNodeELResolver to allow invoking the get method on an ArrayNode.

In this commit, the logic of the BeanELResolver was enhanced to better deal with method overloading.

We encountered some inconsistencies in the Behavior of the BeanELResolver compared to an older flowable release (in our case 6.6.0)
The ArrayNode has two methods with the name "get":

  • get(int index)
  • get(String fieldName)

Before the mentioned commit, it was possible to use the BeanELResolver to invoke ArrayNode::get and pass a Long as parameter, which is no longer possible. Even though none of the two methods apply to a Long (without casting it to an int), I think that there is still a benefit in supporting it:

  • JUEL expressions in Flowable will treat the "0" in ${array.get(0)} as a Long. Therefore, the BeanELResolver will try to invoke "get" with a Long as parameter.
  • As it was possible in the past to use such expressions, it would be great to have backwards compatibility.

Based on @filiphr Feedback, I modified the JsonNodeELResolver rather than the BeanELResolver.

I have added a unit test to demonstrate the problem. The tests also pass on the state of flowable-6.6.0 (some release before the logic of the BeanELResolver was changed).

Without the modification to the JsonNodeELResolver, the test fails with the following exception: org.flowable.common.engine.impl.javax.el.MethodNotFoundException: Unable to find unambiguous method: class com.fasterxml.jackson.databind.node.ArrayNode.get(java.lang.Long)

Check List:

  • Unit tests: YES
  • Documentation: NO

@filiphr
Copy link
Contributor

filiphr commented Dec 9, 2024

Thanks for the analysis and PR @rssap. That line is a bit dangerous as JUEL can coerce anything into a String. We've had mistakes before where someone would call a method accepting a string with some object and the objects toString() would be called, which then leads to some strange and unexpected behaviour.

I would be more keen on adjusting the JsonNodeELResolver instead of adjusting this on the BeanELResolver.

We also try to avoid using mocks like in the test you have. A better test would be in ExpressionManagerTest or in JsonTest

@rssap
Copy link
Contributor Author

rssap commented Dec 9, 2024

I would be more keen on adjusting the JsonNodeELResolver instead of adjusting this on the BeanELResolver.

Sounds good. I have adjusted the JsonNodeELResolver now. To remain flexible and prevent code duplication, I reused the BeanELResolver::invoke internally. Let me know if you like/dislike that.

Small note: The expressions ${array.get(0)} and ${array[0]} return different objects, but I hope that is acceptable:

  • ${array.get(0)} returns a JsonNode (e.g. a TextNode)
  • ${array[0]} returns the actual (e.g. string) value. No more .textValue() needed.

@rssap rssap changed the title Allow BeanELResolver to invoke ArrayNode::get with a Long Allow JsonNodeELResolver to invoke methods Dec 10, 2024
@rssap
Copy link
Contributor Author

rssap commented Dec 11, 2024

@filiphr please have another look at my changes.

@rssap
Copy link
Contributor Author

rssap commented Jan 17, 2025

@filiphr do you have any change requests?

@filiphr
Copy link
Contributor

filiphr commented Jan 20, 2025

Hey @rssap, sorry for the late reply.

I don't like the fact that we are embedding the BeanELResolver here. I would rather only support this in the invoke if the method is path and get, there is a single parameter and it is a long and handle it without any reflection. All other methods and method variables can then be ignored in the JsonNodeELResolver#invoke and just let the next ELResolver handle it.

I can look into this when merging the PR

@filiphr
Copy link
Contributor

filiphr commented Jan 20, 2025

@rssap, I've done some polishing. Can you please review my changes. If you agree with them we can merge this

Copy link
Contributor Author

@rssap rssap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback and the commit. LGTM 👍.

@rssap rssap changed the title Allow JsonNodeELResolver to invoke methods Allow JsonNodeELResolver to invoke get and path Jan 20, 2025
@filiphr filiphr merged commit a7b7bcf into flowable:main Jan 20, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants