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

fix: make property change listener trigger on removeProperty #19196

Merged
merged 1 commit into from
May 2, 2024

Conversation

akhodyko
Copy link
Contributor

Removing element property by calling com.vaadin.flow.internal.nodefeature.AbstractPropertyMap#removeProperty does not trigger property change listener because of com.vaadin.flow.internal.nodefeature.ElementPropertyMap#remove method is skipped due to AbstractPropertyMap#removeProperty method calls super:

    public void removeProperty(String name) {
        super.remove(name);
    }

Fixes #3994

@CLAassistant
Copy link

CLAassistant commented Apr 17, 2024

CLA assistant check
All committers have signed the CLA.

@caalador caalador added the Contribution PRs coming from the community or external to the team label Apr 18, 2024
Copy link

github-actions bot commented Apr 18, 2024

Test Results

1 099 files  ±0  1 099 suites  ±0   1h 16m 50s ⏱️ - 4m 26s
7 006 tests +9  6 957 ✅ +9  49 💤 ±0  0 ❌ ±0 
7 365 runs  +5  7 304 ✅ +5  61 💤 ±0  0 ❌ ±0 

Results for commit cfb48e3. ± Comparison against base commit fa7d789.

♻️ This comment has been updated with latest results.

@akhodyko akhodyko marked this pull request as draft April 18, 2024 07:21
@akhodyko akhodyko force-pushed the trigger-on-prop-removing branch 2 times, most recently from c7cb2ff to 01f794d Compare April 18, 2024 10:08
mshabarov
mshabarov previously approved these changes Apr 19, 2024
@mshabarov
Copy link
Contributor

@akhodyko thanks for you contribution! Looks good to me! May I transfer this pull request to "ready for review" state?

@akhodyko akhodyko marked this pull request as ready for review April 21, 2024 19:38
@akhodyko
Copy link
Contributor Author

@akhodyko thanks for you contribution! Looks good to me! May I transfer this pull request to "ready for review" state?

yes, you can, but there are some trouble with com.vaadin.flow.data.binder.BinderTest.readBean_converterThrows_exceptionHandlerSet_bindingExceptionIsThrown test yet.

@mshabarov
Copy link
Contributor

@akhodyko thanks for you contribution! Looks good to me! May I transfer this pull request to "ready for review" state?

yes, you can, but there are some trouble with com.vaadin.flow.data.binder.BinderTest.readBean_converterThrows_exceptionHandlerSet_bindingExceptionIsThrown test yet.

That seems wrong, if the Binder doesn't throw while the exception happens in the converter. Weird side effect. We will take a look, thanks!

@akhodyko
Copy link
Contributor Author

@mshabarov

I think readBean_converterThrows_exceptionHandlerSet_bindingExceptionIsThrown test is not fully correct.

I will try to explain:

  1. Before this PR, setting null value to com.vaadin.flow.component.AbstractSinglePropertyField was not triggered property change listener on removing property here com.vaadin.flow.component.AbstractSinglePropertyField.TypeHandler#createWriter.
  2. Because of point 1, com.vaadin.flow.component.internal.AbstractFieldSupport#pendingValueFromPresentation was not updated to actual value taking into account default value of field. This caused the field value change event to fire.
  3. After that, value change event caused validation at com.vaadin.flow.data.binder.Binder#handleFieldValueChange followed with conversion field value to model.

According to that, because of we have in that test com.vaadin.flow.data.binder.testcomponents.TestTextField accepting null values with default empty string value, null value must be treated as empty string and should not trigger the change listener and toModel conversion.

Replacing bean Person to another with non null firstName field fixed the test.

@akhodyko akhodyko force-pushed the trigger-on-prop-removing branch 2 times, most recently from 2ef3919 to e826351 Compare April 22, 2024 15:01
Copy link
Contributor

@mshabarov mshabarov left a comment

Choose a reason for hiding this comment

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

As the property removal is now considered as non-client originated event, we have to change to Assert.assertFalse(event.get().isUserOriginated()); in ElementPropertyMapTest::removeProperty_fireEvent_listenerIsNotNotified

@mshabarov
Copy link
Contributor

According to that, because of we have in that test com.vaadin.flow.data.binder.testcomponents.TestTextField accepting null values with default empty string value, null value must be treated as empty string and should not trigger the change listener and toModel conversion.
Replacing bean Person to another with non null firstName field fixed the test.

This makes sense, okay.

@mshabarov mshabarov requested a review from caalador April 26, 2024 12:19
@mshabarov
Copy link
Contributor

Requested another review from @caalador , just in case, if I missed something important, the overall fix looks good to me and correct.

@akhodyko
Copy link
Contributor Author

As the property removal is now considered as non-client originated event, we have to change to Assert.assertFalse(event.get().isUserOriginated()); in ElementPropertyMapTest::removeProperty_fireEvent_listenerIsNotNotified

done

@akhodyko akhodyko requested a review from mshabarov April 26, 2024 14:20
Copy link
Contributor

@caalador caalador left a comment

Choose a reason for hiding this comment

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

Looks good to me.

@mshabarov
Copy link
Contributor

@akhodyko could you please run mvn formatter:format and push? Then we can merge this change.

@akhodyko
Copy link
Contributor Author

akhodyko commented May 2, 2024

@akhodyko could you please run mvn formatter:format and push? Then we can merge this change.

done

Copy link

sonarcloud bot commented May 2, 2024

Quality Gate Passed Quality Gate passed

Issues
0 New issues
0 Accepted issues

Measures
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarCloud

@mshabarov mshabarov merged commit 63e6dfd into vaadin:main May 2, 2024
28 checks passed
@vaadin-bot
Copy link
Collaborator

Hi @akhodyko and @mshabarov, when i performed cherry-pick to this commit to 24.3, i have encountered the following issue. Can you take a look and pick it manually?
Error Message:
Error: Command failed: git cherry-pick 63e6dfd
error: could not apply 63e6dfd... fix: make property change listener trigger on removeProperty (#19196)
hint: After resolving the conflicts, mark them with
hint: "git add/rm ", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".

mshabarov added a commit that referenced this pull request May 6, 2024
mshabarov added a commit that referenced this pull request May 6, 2024
…19196)" (#19310)

This reverts commit 63e6dfd.

The original fix for the property change event is correct per se, but, unfortunately, we faced an odd side effect in the RadioButtonGroup component that blocks our development process and would be a breaking change for RadioButtonGroup's users.

Here are some details:

The getValue() method of the RadioButtonGroup (and probably other similar components, like Select and CheckboxGroup) returned an item that was set in setValue() before, even if it was an invalid item, e.g. it's key/id wasn't in the list of items for this component.

With this change, the PropertyChangeEvent is triggered, that causes handlePropertyChange and hasValidValue method to be called. hasValidValue doesn't properly check if the item is in the list of items on the server and returns true, that causes a state change in setModelValue, that eventually resets the value to null. In other words, if one wants to set a new value, which isn't present in the item's list, the component set the value to null, which sounds like even a bigger bug.

The proper behaviour, in my opinion, should be to not accept invalid values and make hasValidValue implementation properly check if the item is present or not, but this turns into more complicated work that may even have a breaking changes in behaviour.
vaadin-bot pushed a commit that referenced this pull request May 6, 2024
…19196)" (#19310)

This reverts commit 63e6dfd.

The original fix for the property change event is correct per se, but, unfortunately, we faced an odd side effect in the RadioButtonGroup component that blocks our development process and would be a breaking change for RadioButtonGroup's users.

Here are some details:

The getValue() method of the RadioButtonGroup (and probably other similar components, like Select and CheckboxGroup) returned an item that was set in setValue() before, even if it was an invalid item, e.g. it's key/id wasn't in the list of items for this component.

With this change, the PropertyChangeEvent is triggered, that causes handlePropertyChange and hasValidValue method to be called. hasValidValue doesn't properly check if the item is in the list of items on the server and returns true, that causes a state change in setModelValue, that eventually resets the value to null. In other words, if one wants to set a new value, which isn't present in the item's list, the component set the value to null, which sounds like even a bigger bug.

The proper behaviour, in my opinion, should be to not accept invalid values and make hasValidValue implementation properly check if the item is present or not, but this turns into more complicated work that may even have a breaking changes in behaviour.
@mshabarov
Copy link
Contributor

This has been reverted due to a regression in Vaadin Flow components (to be more precise, in RadioButtonGroup) that blocks our releases, see #19310.

For the record, the failed test is this:

[setIdentifierProviderOnId_setItemWithNullId_shouldFailToSelectExistingItemById] java.lang.NullPointerException: Cannot invoke "com.vaadin.flow.component.radiobutton.CustomItem.getId()" because the return value of "com.vaadin.flow.component.radiobutton.RadioButtonGroup.getValue()" is null
	at com.vaadin.flow.component.radiobutton.RadioButtonGroupTest.setIdentifierProviderOnId_setItemWithNullId_shouldFailToSelectExistingItemById(RadioButtonGroupTest.java:441)

I.e. the component reset the value to null, if setValue is called with an item, that is not present in the items list.
We plan to reconsider the logic in RadioButtonGroup regards invalid items and re-apply this patch again.

vaadin-bot added a commit that referenced this pull request May 6, 2024
…19196)" (#19310) (#19311)

This reverts commit 63e6dfd.

The original fix for the property change event is correct per se, but, unfortunately, we faced an odd side effect in the RadioButtonGroup component that blocks our development process and would be a breaking change for RadioButtonGroup's users.

Here are some details:

The getValue() method of the RadioButtonGroup (and probably other similar components, like Select and CheckboxGroup) returned an item that was set in setValue() before, even if it was an invalid item, e.g. it's key/id wasn't in the list of items for this component.

With this change, the PropertyChangeEvent is triggered, that causes handlePropertyChange and hasValidValue method to be called. hasValidValue doesn't properly check if the item is in the list of items on the server and returns true, that causes a state change in setModelValue, that eventually resets the value to null. In other words, if one wants to set a new value, which isn't present in the item's list, the component set the value to null, which sounds like even a bigger bug.

The proper behaviour, in my opinion, should be to not accept invalid values and make hasValidValue implementation properly check if the item is present or not, but this turns into more complicated work that may even have a breaking changes in behaviour.

Co-authored-by: Mikhail Shabarov <61410877+mshabarov@users.noreply.github.com>
@vaadin-bot
Copy link
Collaborator

This ticket/PR has been released with Vaadin 24.4.0.beta2 and is also targeting the upcoming stable 24.4.0 version.

@vaadin-bot
Copy link
Collaborator

This ticket/PR has been released with Vaadin 24.5.0.alpha1 and is also targeting the upcoming stable 24.5.0 version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Element.removeProperty should fire PropertyChangeEvent if property was removed
5 participants