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

Filter out sythetic fields from FieldQueryMapEncoder #840

Merged
merged 1 commit into from
Nov 13, 2018

Conversation

velo
Copy link
Member

@velo velo commented Nov 12, 2018

Fix for #839

return new ObjectParamMetadata(
Arrays.stream(type.getDeclaredFields())
.filter(field -> !field.isSynthetic())
.peek(field -> field.setAccessible(true))
Copy link
Contributor

Choose a reason for hiding this comment

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

Technically, this violates the non-interference contract, but I don't see any actual issues with it.

@kdavisk6 kdavisk6 added the ready to merge Will be merged if no other member ask for changes label Nov 12, 2018
List<Field> fields = new ArrayList<Field>();
for (Field field : type.getDeclaredFields()) {
if (!field.isAccessible()) {
field.setAccessible(true);
Copy link
Member Author

Choose a reason for hiding this comment

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

@rage-shadowman we already do it

Copy link
Contributor

@rage-shadowman rage-shadowman Nov 13, 2018

Choose a reason for hiding this comment

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

No, that's how it's supposed to be done. It's also a per-instance thing, so the next guy who gets the declared fields from the class will have them inaccessible. I was talking about the stream usage modifying an object inside the stream.

I believe the stream non-interference contracts are about leaving the original object alone, so peek is only intended for use in statistics gathering and logging (or other such non-interfering things), and you're supposed to use map (and create a new object for the map to return rather than modifying objects in-line which is a side-effect). However, in this particular usage, I don't see anything wrong with violating the contract since you are the sole creator, maintainer, and user of the stream and all its objects.

Copy link
Member Author

Choose a reason for hiding this comment

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

But setAccessible is void or am I missing something obvious?

Copy link
Contributor

@rage-shadowman rage-shadowman Nov 13, 2018

Choose a reason for hiding this comment

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

It may be void, but it still mutates the Field object internally, making it accessible. From the stream's point of view, that's a side-effect (it's the effect you intended, but to the stream, it's a side-effect that violates the non-interference contract by modifying the stream's objects). Also, since it is a void method, you can't do this in a stream without violating that contract (you'd have to use a for loop instead, thereby making it an effect, rather than a side-effect).

Like I said, I don't think it's an issue since this is all done in 1 thread, and it doesn't have any side-effects from the perspective of anyone outside of this method (if the side-effect modified any objects that you didn't just create yourself, I might feel differently). This is something you should keep in mind whenever you use streams.

Please excuse me if you already know this, but more generally, you need to be aware of all your side-effects in order to know how complex your code will be in a multi-threaded context (the more complex, the more likely you have threading bugs that you just haven't seen yet and won't easily be able to debug -- or even reproduce -- when you do see them). Making code that is incapable of side-effects (immutable objects and unmodifiiable collections everywhere, no arrays, no output parameters -- just return the output instead) is my preference, but that's not always possible (sometimes you really need to maintain mutable state, and sometimes that state consists of complex invariants), and even when it is possible (in my experience, it usually is), most libraries out there do not follow such a strict approach.

@velo velo merged commit e15e9f0 into OpenFeign:master Nov 13, 2018
@velo velo deleted the synthetic_fields branch November 13, 2018 02:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready to merge Will be merged if no other member ask for changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants