Skip to content

Don't Bail If Optional Property Is Nullified#441

Closed
karthicks wants to merge 1 commit intolightbend:masterfrom
karthicks:issue-440
Closed

Don't Bail If Optional Property Is Nullified#441
karthicks wants to merge 1 commit intolightbend:masterfrom
karthicks:issue-440

Conversation

@karthicks
Copy link
Copy Markdown

For details on the problem description, please refer to #440.

if (!isOptionalProperty(clazz, beanProp)) {
// bubble the {@link Missing} exception up
throw e;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this (sometimes?) be explicitly setting the field to null? I feel like if the config does not contain a setting, maybe we keep whatever the bean's constructor set, but if the config explicitly has null in it, we should probably explicitly set to null?

}
} else {
try {
Object unwrapped = getValue(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I wonder if it would be better to handle null in getValue (would need to pass in to getValue whether the prop is optional and then use config.getIsNull I think). An advantage would be to avoid exceptions in normal control flow, which is nice because they are legitimately pretty slow to throw, and that could matter to some programs.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

On second thought, would it be acceptable to treat null values as if they were missing, as the spec states? That way, we can avoid exceptions during the normal control flow.

assertNotNull(beanConfig)
assertNotNull(beanConfig.getValueObject)
assertNull(beanConfig.getValueObject.getOptionalValue)
assertNull(beanConfig.getValueObject.getNullableValue)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

maybe we could test the matrix of combinations of

  • bean constructor sets to null vs non-null
  • config explicitly sets to null or simply omits the setting

If only to be sure we don't accidentally change behavior of one of those matrix cells later.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Currently, we do kind of test the use case where a value is set to null versus a value that is simply missing or omitted. The ObjectsConfig#optionalValue field is being used to test the value being omitted, and the ObjectsConfig#nullableValue field for the value being set to null.

@havocp
Copy link
Copy Markdown
Contributor

havocp commented Nov 10, 2016

thanks for the PR!

@karthicks
Copy link
Copy Markdown
Author

@havocp , sorry about the belated response. I tweaked the change so that it doesn't rely on the exception-based approach initially proposed. Can you take a look to see if this is more acceptable? -Karthick

}

public void setNullableValue(String nullableValue) {
this.nullableValue = nullableValue;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think (could be wrong) that we aren't testing the behavior where the bean constructor sets a non-null value on the optional field, and then either we do not have it in the config, or it's set to null in the config. Intuitively I would think it should be overwritten with null only if explicitly set in the config?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Though i can see the argument for overwriting it with null always (always ignore the bean constructor) maybe ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I think you're right. If an optional field is defaulted (either through an initializer or the default constructor), and if that field is missing in the configuration, then that default value should take effect. That does seem more intuitive to me.

}
if (configValue == null && !isOptionalProperty(clazz, beanProp)) {
SimpleConfig.addMissing(problems, expectedType, path, config.origin());
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does this imply that the throw new ConfigException.Missing a few lines down is now unreachable? If so we might throw a BugOrBrokenException("Should have detected missing props earlier") down there instead of ConfigException.Missing.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Will do. That makes sense.

@karthicks
Copy link
Copy Markdown
Author

@havocp ,

In order to handle fields in the bean that are initialized with a default value, I took the approach you initially suggested, viz., handle null values properly in getValue. Rather than changing that method's signature, I added an optional property to AbstractConfigValue and raise a ConfigException.Null exception only if the value is not optional.

What do you think?

-Karthick

Copy link
Copy Markdown
Contributor

@havocp havocp 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 updating this, I apologize for taking a while to reply.


final private SimpleConfigOrigin origin;

private boolean optional;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this field won't work for a couple reasons; 1) ConfigValue is immutable, 2) if this was changed to make a copy of the config value, it would still not be conceptually part of the value, it's part of the implied "schema" instead.

will suggest another way to do this below

// Otherwise, raise a {@link BugOrBroken} exception
throw new ConfigException.BugOrBroken("Should have detected missing props earlier");
}
Object unwrapped = getValue(clazz, parameterType, parameterClass, config, configPropName);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To let this getValue return null, I'd suggest passing in a parameter to getValue optional=true|false, and then at the top of getValue do something like:

if (optional and config.getIsNull(configPropName))
  return null;

I think that will work ?

@lightbend-cla-validator
Copy link
Copy Markdown
Collaborator

Hi @yellowblood, @camullen,

Thank you for your contribution! We really value the time you've taken to put this together.

Before we proceed with reviewing this pull request, please sign the Lightbend Contributors License Agreement:

http://www.lightbend.com/contribute/cla

@karthicks karthicks force-pushed the issue-440 branch 3 times, most recently from d38fba7 to 2546803 Compare March 31, 2017 20:14
@karthicks
Copy link
Copy Markdown
Author

@havocp ,

Updated the pull request as per your suggestion, which relies on the config.getIsNull method.

-Karthick Sankarachary

// Otherwise, raise a {@link Missing} exception right here
throw new ConfigException.Missing(beanProp.getName());
// Otherwise, raise a {@link BugOrBroken} exception
throw new ConfigException.BugOrBroken("Should have detected missing props earlier");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should be reverted to the original exception, because the related change (which was proposed here) is not in the PR anymore.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Just saw this comment. Don't know why I didn't get an email notification earlier. In any case, I've reverted to the original exception. Sorry for the belated response.

@2m
Copy link
Copy Markdown
Contributor

2m commented Oct 6, 2017

I think this can be merged when the exception type is reverted.

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.

4 participants