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 ObjectParsers to specify required sets of fields #49661

Merged
merged 10 commits into from
Feb 11, 2020

Conversation

polyfractal
Copy link
Contributor

ConstructingObjectParser can be used to specify required fields, but it is still difficult to configure "sets" of fields where only one of the set is required ((foo OR bar) AND (bizz OR buzz)). It requires hand-rolled logic in each ConstructingObjectParser, or special validation methods that are called during/after object construction.

This commit adds a new method on ObjectParser which allows the parsers to register required sets. E.g. ["foo", "bar"] can be registered, which means "foo", "bar" or both must be configured by the user otherwise an exception is thrown.

This pattern crops up in many places in our parsers, but as a demonstration this PR adds validation for aggregation "field" and "script" fields. One or both must be configured on all aggregations, and omitting both should result in an exception. This was previously handled far downstream resulting in an aggregation exception, when it should be a parse exception.

This might be a controversial change given it's partial overlap with ConstructingObjectParser. Open to changes/suggestions, as well as better naming :)

Closes #48824

ConstructingObjectParser can be used to specify required fields,
but it is still difficult to configure "sets" of fields where only
one of the set is required (requiring hand-rolled logic in each
ConstructingObjectParser, or adding special validation methods
to objects that are called after building the object).

This commit adds a new method on ObjectParser which allows
the parsers to register required sets.  E.g. ["foo", "bar"] can be
registered, which means "foo", "bar" or both must be configured
by the user otherwise an exception is thrown.

This pattern crops up in many places in our parsers, but as a
demonstration this PR adds validation for aggregation "field" and
"script" fields.  One or both must be configured on all aggregations,
omitting both should result in an exception.  This was previously
handled far downstream resulting in an aggregation exception, when it
should be a parse exception.
@polyfractal polyfractal added the :Core/Infra/Core Core issues without another label label Nov 27, 2019
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-core-infra (:Core/Infra/Core)

Copy link
Member

@rjernst rjernst left a comment

Choose a reason for hiding this comment

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

Overall having better control over what combinations of fields are allowed or must be present, but I wonder if this is sufficient. The examples given in javadoc are pretty simplistic, and shown like a query, while we are talking about json objects. Would it be possible to give closer to a real world example?

String[] requriedFields = iter.next();
for (String field : requriedFields) {
if (field.equals(currentFieldName)) {
iter.remove();
Copy link
Member

Choose a reason for hiding this comment

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

Isn't this removing the value from the ObjectParser's instance, which is static?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oof, you're right. I was just looking at the class itself (which is not static) but everyone declares ObjectParser as static. I'll fiddle to get rid of the mutability

@polyfractal
Copy link
Contributor Author

Thanks!

The examples given in javadoc are pretty simplistic, and shown like a query, while we are talking about json objects. Would it be possible to give closer to a real world example?

The motivating example for me was from aggregations: script or field (or both) must be specified, but if both are omitted it should be a parse exception. That's also why the PR has agg-related test fixes and documentation tweaks, since the PR included this as a demonstration example.I'll adjust the javadocs to show some json examples instead of boolean logic.

Regarding the agg-specific parts of the PR, I can remove them if we want it to be just infrastructure, and followup with a second PR for the agg stuff.

@polyfractal
Copy link
Contributor Author

I backed out all the agg-related changes (making field/script required, the test tweaks and the documentation change) so this PR is now just related to the object parser.

Fixed access to the static object by making a copy of the list before parsing. This didn't feel especially clever, so open to alternatives :)

Also beefed up the javadocs a bit with json examples

Copy link
Member

@rjernst rjernst left a comment

Choose a reason for hiding this comment

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

A few more comments.

@polyfractal
Copy link
Contributor Author

polyfractal commented Dec 16, 2019

Review comments addressed! The extra javadoc markup made the json snippets significantly less readable though so not sure if they are still helpful or not...

I opted to ignore <p> since none of the other javadocs in this class use it either. I also used <code> instead of {@code} to avoid escaping all the braces

EDIT Looks like javadoc is unhappy, fixing...

EDIT 2 Hmm, so it seems that precommit wants a "summary" field on the table

> Task :libs:elasticsearch-x-content:compileJava FAILED
/home/polyfractal/projects/es/elasticsearch/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java:258: error: no summary or caption for table
     * </table>

But the build fails when a "summary" field is included

> Task :libs:elasticsearch-x-content:javadoc
13:37:07 /dev/shm/elastic+elasticsearch+pull-request-1/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java:249: error: attribute not supported in HTML5: summary
13:37:07      * <table summary="failure cases">

Copy link
Member

@rjernst rjernst left a comment

Choose a reason for hiding this comment

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

LGTM

@polyfractal
Copy link
Contributor Author

Had a chance to revisit this, think I resolved the javadoc compilation build issue. Unsure why the "summary" field broke everything, but replacing it with a <content> tag instead satisfies the build. (kudos to @mark-vieira for the tip).

This got stale, merged in master and fixed conflicts, will monitor to make sure there aren't any new test issues before merging.

@polyfractal
Copy link
Contributor Author

@elasticmachine update branch

@polyfractal polyfractal merged commit 208cbc2 into elastic:master Feb 11, 2020
polyfractal added a commit that referenced this pull request Feb 11, 2020
ConstructingObjectParser can be used to specify required fields,
but it is still difficult to configure "sets" of fields where only
one of the set is required (requiring hand-rolled logic in each
ConstructingObjectParser, or adding special validation methods
to objects that are called after building the object).

This commit adds a new method on ObjectParser which allows
the parsers to register required sets.  E.g. ["foo", "bar"] can be
registered, which means "foo", "bar" or both must be configured
by the user otherwise an exception is thrown.

This pattern crops up in many places in our parsers; a good example are
the aggregation "field" and "script" fields.  One or both must be
configured on all aggregations, omitting both should result in an exception.
This was previously handled far downstream resulting in an aggregation
exception, when it should be a parse exception.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Aggregations should throw parse exception if no field or script is specified
4 participants