[MAGNOLIA-6199] Comparison of two proxied objects doesn't work even if the underlying objects are exactly the same Created: 07/May/15  Updated: 13/Jan/17  Resolved: 13/Jan/17

Status: Closed
Project: Magnolia
Component/s: configuration, core
Affects Version/s: 5.4
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Philip Mundt Assignee: Unassigned
Resolution: Outdated Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Relates
relates to MULTISITE-28 By usage of smartphone variation, all... Closed
causality
is causing PAGES-17 Moving pages is broken Closed
Template:
Acceptance criteria:
Empty
Task DoD:
[ ]* Doc/release notes changes? Comment present?
[ ]* Downstream builds green?
[ ]* Solution information and context easily available?
[ ]* Tests
[ ]* FixVersion filled and not yet released
[ ]  Architecture Decision Record (ADR)
Bug DoR:
[ ]* Steps to reproduce, expected, and actual results filled
[ ]* Affected version filled
Date of First Response:
Story Points: 5

 Description   

This behavior was observed when analyzing PAGES-17.

With the new registry API of 5.4, we proxy* all definitions that implement NamedDefinition. This proxy currently "decorates" the underlying definition objects to manage their ID and NAME properties.

When two such proxied objects are compared, the calls to equals method are intercepted just like any other, and delegated to the underlying object. The arguments to the method are however not unwrapped, so the comparison never works.

To illustrate:
Given proxies p1 and p2, which respectively proxy o1 and o2 objects. o1==o2 and p1==p2 are both true. When calling p1.equals(p2), p1 intercepts the calls to equals and delegates it to o1, which essentially results in o1.equals(p2), which is obviously never true.

I'm pretty sure I saw some equals (and possible hashcode) specific handling in ProxyToys somewhere, either it's optional or it's what's actually causing the issues. I'll dig it out !

  • for the sake of clarity/brevity, all "proxy" here actually refers to our usage of ProxyToys in the context of the configuration APIs. We also use ProxyToys in magnolia-i18n, so we'll need to verify the behavior there as well.


 Comments   
Comment by Magnolia International [ 07/May/15 ]

Might have to dig a bit further, because the following test passes in AbstractRegistryTest:

    @Test
    public void definitionsAreComparable() {
        final String d1 = "module-a:pouet/zoom";
        // Sanity check:
        assertNotNull(registry.getProvider(d1));
        assertNotNull(registry.getProvider(d1).get());
        assertThat("for the sake of this test, we need a NamedDefinition", registry.getProvider(d1).get(), instanceOf(NamedDefinition.class));

        // Actual test:
        assertEquals("getting a provider for the same ID should yield two equals() instances", registry.getProvider(d1), registry.getProvider(d1));
        assertSame("getting a provider for the same ID should yield two identical instances", registry.getProvider(d1), registry.getProvider(d1));
        assertEquals("getting a definition for the same ID should yield two equals() instances", registry.getProvider(d1).get(), registry.getProvider(d1).get());
        assertSame("getting a definition for the same ID should yield two identical instances", registry.getProvider(d1).get(), registry.getProvider(d1).get());
    }
Comment by Magnolia International [ 07/May/15 ]

The test in fact would show the problem if DummyThing did not use Lombok's @Data annotation.
If we don't implement an equals() method, or if it's implemented using fields comparison (which are all null in class-based proxies), the test fails. The test passes with @Data because Lombok's equals() is implemented using getters (which are in turn intercepted and delegated correctly to the underlying bean)

Generated at Mon Feb 12 04:12:14 CET 2024 using Jira 9.4.2#940002-sha1:46d1a51de284217efdcb32434eab47a99af2938b.