-
Notifications
You must be signed in to change notification settings - Fork 390
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
Prevent NPE in TStructDescriptor when an unexpected enum is encountered ... #364
Conversation
…ed by returning an empty map.
@rangadi and @julienledem please take a look. The specific context where I encountered this was parquet conversion, where the stack trace looked like this:
|
isEnum() would be false in this case. getEnumValueOf() is valid only after isEnum() is checked. |
That means we are in the rather odd situation where field.getType can return enum, but isEnum returns false, and getEnumValues() throws an NPE. |
On further reflection, I see why returning an empty collection is bad -- but just blowing up with an NPE is not super nice either. Maybe we should change all methods that dereference |
Updated the PR with a better null check, as described in the comment above. |
I don't think that is possible. If TType is ENUM, isEnum would always be true. Can you point me to the struct that triggered this? |
I am fine with the patch (return 'null' rather than NPE). This is essentially a work around for not having to check isEnum(). JavaDoc added is very useful.. have a couple of comments there. |
/** | ||
* | ||
* @return true if the field is a known enum. Note that this can return false | ||
* in two cases: if the field is not an enum at all, or if the field you are reading |
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.
Thanks for the JavaDoc.
case (1) : yes, is false when a field is not enum (according to Thrift definition on classpath).
case (2) : What does it mean? TStructDescriptor is a singleton descriptor for each Thrift struct, only based on definition on the classpath. It does not depend on the message on the wire at all. May be the app stored separately that field_x is an Enum (which changed while reading), that is a different issue.
For (2), I am not entirely sure how this is happening, to be honest. I'm encountering this NPE when trying to convert a thrift file to parquet, using an out of date thrift definition. I assume that it's something like reading from the binary data and looking at the type bits in the stream to id the field type, and encountering a mismatch with what our inspection of the generated code gives us. |
default Thrift deserializer would ignore the field since the type on the wire does not match type reported by runtime Thrift struct. Though this patch can go in, looks like we should fix Parquet converter that is reading the thrift message. I think it is better to remove the (2) in the javadoc. |
I found a case with typedef where this is not true. This is possibly also the reason for parquet conversion failure.
Output: (16== ENUM)
|
Works with #356. |
Ah that's what it was. Thanks guys. Does the change to return a null instead of throwing an NPE still make sense? Should I just change the javadocs to get rid of (2)? |
I think so. We can merge this patch with an update to javadoc (you also need to merge with latest master). |
public TEnum getEnumValueOf(String name) { | ||
return enumMap.get(name); | ||
return enumMap == null ? null : enumMap.get(name); |
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 not use Guava Optional here?
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Optional.html
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.
Without reading the docs for optional -- would that require the user of the library to depend on guava? The current main user outside of EB is parquet, and that lib has almost no external dependencies to simplify integration.
On Dec 29, 2013, at 11:20 AM, "P. Oscar Boykin" notifications@github.com wrote:
In core/src/main/java/com/twitter/elephantbird/thrift/TStructDescriptor.java:
public TEnum getEnumValueOf(String name) {
return enumMap.get(name);
why not use Guava Optional here?return enumMap == null ? null : enumMap.get(name);
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Optional.html
—
Reply to this email directly or view it on GitHub.
…o tstruct_enum_npe Conflicts: core/src/main/java/com/twitter/elephantbird/thrift/TStructDescriptor.java
Javadoc updated. |
Prevent NPE in TStructDescriptor when an unexpected enum is encountered
merged. |
thanks! Looks good to me |
...by returning an empty map.
When an out-of-date thrift definition is used, and a new enum field is encountered, currently the enum map can be null, which results in an NPE. It seems like it is better to return an empty map and let the caller deal with the fact that the map doesn't contain all the enums the caller will encounter (the caller is then free to increment error counters, etc).