-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Make JsonPropertyAccessor returned type directly a JsonNode or value #3270
Make JsonPropertyAccessor returned type directly a JsonNode or value #3270
Conversation
Thank you for contribution @pilak ! We will take a look into your PR soon. Meanwhile, please, consider to run First of all we use tabs for indents. Secondly our imports order is like:
|
7060332
to
dea81e3
Compare
Hi Artem, I made changes related to checkstyle violations and I think it's ok now. Hope my solution will fit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I don't understand what is going on.
Json property accessor selector friendly
This is not enough to justify such a breaking change.
Can you give in the commit message as much explanation what you are doing and why as possible?
See recommendations here: https://chris.beams.io/posts/git-commit/
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright 2013-2019 the original author or authors. | |||
* Copyright 2014-2020 the original author or authors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why have you moved the first year and why haven't you changed all others to 2020
in the last year?
Anyway it looks like you didn't run gradlew clean check
because we have a Gradle task to update Copyright for all the changed classes...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unfortunately I have an error while running the task check
Caused by: com.puppycrawl.tools.checkstyle.api.CheckstyleException: Unable to find: src/checkstyle/checkstyle-suppressions.xml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you show, please, how do you call it?
Is it from command line like ./gradlew clean check
?
Or do you use an IDE integration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from the wrapper yes in command line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The compilation was not working on JDK 11, so I used JDK 8 instead
Sorry, I don't know exactly what to set for the commit title...
|
Well, the header of the commit message should not exceed 50 symbols. And here are some questions from me since I review this:
All those are hard changes for me and I can't merge whatever I don't understand. (Did you really read that Chris Beam's article?) Thanks |
In general you need to pull |
@artembilan why do we return I also found that actually, the Jackson ArrayNode should implement the List interface or else Collection (don't know why jackson didn't do it, but there must be a reason). But because of this not, we must Reading the code again I now understand that this Anyway, I will push an update of my changes soon, according to your different reviews, and eventually what could be decided from this post. Thanks for your patience |
dea81e3
to
a6ad719
Compare
@artembilan I pushed some changes and modified the commit message to explain better what I intent to solve with my changes in this PR. Hope this is not too much time consuming for you, and will worth it. |
a6ad719
to
4b9b9bd
Compare
Thank you, @pilak , for such an effort! Stay tuned! |
Ok @artembilan thanks for the feedback. |
Please, rebase your branch to the latest master. It is now |
4b9b9bd
to
e059536
Compare
Hi @artembilan,
I also have this error from Travis CI:
|
Thank you for the update! Pulling locally for thorough review... |
I'll turn off my RabbitMQ to see what is wrong in the tests. |
It looks like we indeed need a I worry that proxying is a heavy operation and we should avoid it as much as possible. Would you mind to play with much simpler model when we deal only with a Thanks for understanding! |
private ContainerNode<?> assertContainerNode(JsonNode json) throws AccessException { | ||
if (json instanceof ContainerNode) { | ||
return (ContainerNode<?>) json; | ||
private JsonNode assertContainerNode(JsonNode json) throws AccessException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't look like we need such an assertion at all.
if (index != null && container.has(index)) {
return typedValue(container.get(index));
}
So, we are good to deal with whatever JsonNode
we get.
Looks like the previous Jackson version was different, but now it is a bit easier to avoid extra checks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
...ntegration-core/src/main/java/org/springframework/integration/json/JsonPropertyAccessor.java
Show resolved
Hide resolved
...ntegration-core/src/main/java/org/springframework/integration/json/JsonPropertyAccessor.java
Show resolved
Hide resolved
*/ | ||
public static class ArrayNodeAsList extends AbstractList<WrappedJsonNode<?>> | ||
implements WrappedJsonNode<ArrayNode> { | ||
public static class ArrayNodeAsList extends AbstractList<Object> implements JsonNodeWrapper { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't make all these support classes as public to avoid confuse on the end-user side when they get access to them.
Please, rebase your branch to the latest Although consider to test only |
Unfortunately the method below called in AST doesn't check for |
As JsonNode is an asbtract meta class (in a Jackson way), this is not possible to extend it without having to implement every abstract methods in order to add |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the update, @pilak !
I don't think this can make it into the current 5.4 GA phase.
So, probably already to the next one 6.0
.
I'll review it a bit later, next week after release, but meanwhile consider these issue Travis shows to us:
/home/travis/build/spring-projects/spring-integration/spring-integration-core/src/main/java/org/springframework/integration/json/JsonPropertyAccessor.java:76: error: cannot find symbol
return Set.of(new ConvertiblePair(JsonNodeWrapper.class, JsonNode.class));
^
symbol: method of(ConvertiblePair)
location: interface Set
/home/travis/build/spring-projects/spring-integration/spring-integration-core/src/main/java/org/springframework/integration/json/JsonPropertyAccessor.java:123: warning: [cast] redundant cast to JsonNode
return assertContainerNode((JsonNode) wrapper.getRealNode());
^
1 error
1 warning
Plus see if you rebased to the latest master.
1309e53
to
4e7bfda
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not possible to extend it without having to implement every abstract methods in order to add Comparable contract.
OK. Can we deal with the
TreeNode
instead for thatComparable
contract? I'm not sure that we indeed should let to have all theJsonNode
functionality access.
Plus, we probably just could convert anArrayNode
into aList
:StreamSupport.stream(arrayNode.spliterator(), false) .collect(Collectors.toList());
Using this we won't be able to call expression.getValue(..., ArrayNode.class)
private ContainerNode<?> assertContainerNode(JsonNode json) throws AccessException { | ||
if (json instanceof ContainerNode) { | ||
return (ContainerNode<?>) json; | ||
private JsonNode assertContainerNode(JsonNode json) throws AccessException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
4e7bfda
to
0c6efab
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is very close now to the finish.
Would you mind to answer to those my couple questions?
Or make a respective change...
Thanks
converterRegistry.addConverter(new GenericConverter() { | ||
@Override | ||
public Set<ConvertiblePair> getConvertibleTypes() { | ||
return Collections.singleton(new ConvertiblePair(JsonNodeWrapper.class, JsonNode.class)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this converter?
If that, shouldn't we introduce it alongside with that ToStringFriendlyJsonNodeToStringConverter
?
On the other hand: do we still need that ToStringFriendlyJsonNodeToStringConverter
with this whole your change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, as the Wrapper already integrate the toString
method, it is no more necessary to have such a converter...
I removed the ToString converter, and add some more test with this in mind.
I take it the application context will load it automatically in case of a Spring application is starting...? If so, now the wrapper converter is not an anonymous class anymore.
0c6efab
to
ac1ff8d
Compare
Please, stop squashing commits. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, stop squashing commits.
I'm not sure now what change have you done since the last review.
Ok sorry I will try to restore the history, and make it build better
...ation-core/src/test/java/org/springframework/integration/json/JsonPropertyAccessorTests.java
Show resolved
Hide resolved
converterRegistry.addConverter(new GenericConverter() { | ||
@Override | ||
public Set<ConvertiblePair> getConvertibleTypes() { | ||
return Collections.singleton(new ConvertiblePair(JsonNodeWrapper.class, JsonNode.class)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, as the Wrapper already integrate the toString
method, it is no more necessary to have such a converter...
I removed the ToString converter, and add some more test with this in mind.
I take it the application context will load it automatically in case of a Spring application is starting...? If so, now the wrapper converter is not an anonymous class anymore.
c93c3f8
to
e3633b5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we are good to go with your PR here so far, but now it only can make it into the next 6.0
version since we have just done with 5.4
and such a change cannot make it into the point release since it is slightly breaking change.
Thanks for understanding!
.travis.yml
Outdated
- ./gradlew checkAsciidocLinks check --refresh-dependencies --no-daemon | ||
- kill %1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are those logs in the end of build on Travis is what we would expect from this change:
Done. Your build exited with 0.
/home/travis/.travis/functions: line 536: 5866 Terminated while sleep 540; do
echo "=====[ ${SECONDS} seconds still running ]=====";
done
?
Especially I worry about that non-resolved ${SECONDS}
placeholder...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
${SECONDS}
is a built-in shell variable that start counting as you start/open a command in a terminal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made this change because of the result of this build
https://travis-ci.org/github/spring-projects/spring-integration/builds/740138931
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this log is only the output of the kill %1
in this line you have an example of the working routine:
https://travis-ci.org/github/spring-projects/spring-integration/builds/740153889#L826
...ation-core/src/test/java/org/springframework/integration/json/JsonPropertyAccessorTests.java
Show resolved
Hide resolved
e3633b5
to
2a7621f
Compare
* add `Comparable` contract to the initial wrapper so that expressions containing selection/projection with JsonNode filtering are now possible * render directly the value of a ValueNode. SpEL parser can now evaluate correctly the object value when the expression deals with filtering on JsonNode values (<, >, ==...) * the 2 above changes make this possible: `property.^[name.getTarget().asText() == 'value1'].name` can now be written as simply as `property.^[name == 'value1'].name`. The expression is now fully compatible with other PropertyAccessor types * rename `ToStringFriendlyJsonNode` to `JsonNodeWrapper` as it reflects more the capability of the new wrapper * add a GenericConverter to be able to convert the `JsonNodeWrapper` class into a `JsonNode` (or its derivative classes) directly while calling `expression.getValue(..., JsonNode.class)` * add the possibility to access list items in a json-path like index => a negative number will begin from the end of the list <= * return null value when JsonNode cannot handle the property name (or index)
2a7621f
to
5efd452
Compare
Since we have decided to go with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we have decided to go with
5.5
version yet for the upcoming Spring Boot2.5
, then pulling this change locally for the final review and clean up... I think we can apply such a change into the minor release with an appropriate Migration Guide note (if any).
Hello @artembilan
Am I supposed to do something for now?
.travis.yml
Outdated
- ./gradlew checkAsciidocLinks check --refresh-dependencies --no-daemon | ||
- kill %1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
${SECONDS}
is a built-in shell variable that start counting as you start/open a command in a terminal
...ation-core/src/test/java/org/springframework/integration/json/JsonPropertyAccessorTests.java
Show resolved
Hide resolved
.travis.yml
Outdated
- ./gradlew checkAsciidocLinks check --refresh-dependencies --no-daemon | ||
- kill %1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made this change because of the result of this build
https://travis-ci.org/github/spring-projects/spring-integration/builds/740138931
.travis.yml
Outdated
- ./gradlew checkAsciidocLinks check --refresh-dependencies --no-daemon | ||
- kill %1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this log is only the output of the kill %1
in this line you have an example of the working routine:
https://travis-ci.org/github/spring-projects/spring-integration/builds/740153889#L826
Hi @pilak ! We've busy with releases this week. Probably you don't need to do anything more, unless you'd like to contribute some other stuff 😄 Anyway I'll update this later. |
Nice, thank you @artembilan for your advices |
Sure! Looking forward for decision on that PR from Spring Framework commiters! |
According to that thread on stackoverflow, I'm submitting a PR in order to improve the selector readability on JsonPropertyAccessor.
I made this changes because I noticed that using the same expression passing from different accessors such as MapAccessor, ReflectivePropertyAccessor is working but not with JsonNodePropertyAccessor.
Here's an example that shows the breaking or the success of using or not the new JsonNodePropertyAccessor along with the same SpEL expression:
https://github.com/pilak/examples/blob/master/TestJsonAccessing.java