You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@sling.apache.org by Carsten Ziegeler <cz...@apache.org> on 2010/01/13 16:16:37 UTC

[RT] Identity of resources and adaptables

Hi,

I've been thinking lately about identity of our objects, especially
resource objects and adaptables.

Without thinking about how this is implemented at the moment and without
thinking if/how this could be implemented, what would you expect for the
following: We simply get the same resource twice from the same resource
resolver:

ResourceResolver resolver;

Resource a = resolver.getResource("/a/b");
Resource b = resolver.getResource("/a/b");

What should be true? a == b, a.equals(b) ?

Next question: We get the same adaptable from a resource:

Node n1 = a.adaptTo(Node.class);
Node n2 = a.adaptTo(Node.class);

Again: n1 == n2? n1.equals(n2)?

While these questions seem to be trivial (more or less), it can get more
subtle. Think about a resource resolver being used for a single request
and getting the same resource during the request several times. Should
it be possible to return different resources because the repository has
changed during the request?
Or the other way round. Think about an admin resource resolver running
forever in the background.

Before I post my answers I would like to get some other input? :)

Regards
Carsten
-- 
Carsten Ziegeler
cziegeler@apache.org

Re: [RT] Identity of resources and adaptables

Posted by Bertrand Delacretaz <bd...@apache.org>.
Hi,

On Wed, Jan 13, 2010 at 4:16 PM, Carsten Ziegeler <cz...@apache.org> wrote:
> ...I've been thinking lately about identity of our objects, especially
> resource objects and adaptables....

Identity crisis? Ok, I'll bite ;-)

> Resource a = resolver.getResource("/a/b");
> Resource b = resolver.getResource("/a/b");
>

> What should be true? a == b a.equals(b) ?

Equals: yes
== : I don't care, leave it undefined

> Next question: We get the same adaptable from a resource:
>
> Node n1 = a.adaptTo(Node.class);
> Node n2 = a.adaptTo(Node.class);
>
> Again: n1 == n2? n1.equals(n2)?

== : I don't care, leave it undefined

Depends on what we're adapting to.

In case of a Node I'd expect equals to be true, but ideally that
should only happen if the node hasn't changed in between adaptTo
calls.

> ...Think about a resource resolver being used for a single request
> and getting the same resource during the request several times. Should
> it be possible to return different resources because the repository has
> changed during the request?...

I think so, the application should accept receiving different values
for the same resources during the processing of a request. Nodoby says
Sling is supposed to be transactional during processing of a request.

If one needs a resource to stay stable during a whole request, they
should cache it themselves in the request attributes for example.

So in short: equals should do the right thing, I don't care about ==,
and resources can change at any time. And when adapting resources to
Foo, it's Foo semantics that prevail.

And I'm sure people will find edge cases where the above is problematic ;-)

-Bertrand

Re: [RT] Identity of resources and adaptables

Posted by Vidar Ramdal <vi...@idium.no>.
On Wed, Jan 13, 2010 at 4:16 PM, Carsten Ziegeler <cz...@apache.org> wrote:
> I've been thinking lately about identity of our objects, especially
> resource objects and adaptables.
>
> Without thinking about how this is implemented at the moment and without
> thinking if/how this could be implemented, what would you expect for the
> following: We simply get the same resource twice from the same resource
> resolver:
>
> ResourceResolver resolver;
>
> Resource a = resolver.getResource("/a/b");
> Resource b = resolver.getResource("/a/b");
>
> What should be true? a == b, a.equals(b) ?

I would expect a.equals(b), but not necessarily a == b

> Next question: We get the same adaptable from a resource:
>
> Node n1 = a.adaptTo(Node.class);
> Node n2 = a.adaptTo(Node.class);
>
> Again: n1 == n2? n1.equals(n2)?

Without cheating and looking at the JCR spec :), I would expect:
n1.equals(n2) == n1.getPath().equals(n2.getPath()) &&
n1.getSession().equals(n2.getSession())
but not necessarily
n1 == n2

-- 
Vidar S. Ramdal <vi...@idium.no> - http://www.idium.no
Sommerrogata 13-15, N-0255 Oslo, Norway
+ 47 22 00 84 00 / +47 21 531941, ext 2070

Re: [RT] Identity of resources and adaptables

Posted by Justin Edelson <ju...@gmail.com>.

On Jan 15, 2010, at 7:15 AM, Alexander Klimetschek <ak...@day.com>  
wrote:

> On Thu, Jan 14, 2010 at 17:28, Justin Edelson  
> <ju...@gmail.com> wrote:
>> But the more I think about it, the more I'm on the fence about:
>> resolver.getResource("/a/b") == resolver.getResource("/a/b")
>>
>> My first instinct was basically what Mike wrote, this can be true,  
>> but isn't
>> required to be so. But the more I think about it, I think this  
>> should always
>> be true. I don't have a explanation why... still working on that  
>> part.
>
> Note that ensuring a == b can make implementations very difficult, as
> you need to cache all the Resource instances you returned to the API
> client. And what about handling this across multiple threads?

To be clear, I meant that == should work if the resolvers are ==.

>
> There is a good reason why the JCR spec decided to state "a.equals(b)"
> and internal state represented as equal, but not a == b.
>
> Regards,
> Alex
>
> -- 
> Alexander Klimetschek
> alexander.klimetschek@day.com

Re: [RT] Identity of resources and adaptables

Posted by Carsten Ziegeler <cz...@apache.org>.
Felix Meschberger wrote:
> Hi,
> 
> I think equals should hold. == should not be required (and even less
> depended upon).
> 
> Especially in long used ResourceResolver instances having to guarantee
> == will generate a memory hog sooner or later.
> 
> I agree that we might build in some caching to the ResourceResolver, for
> example using an LRUMap or using WeakReferences for the GC to be able to
> clean up in times of low memory conditions.
> 
> One thing, holds me back a bit: The Resource.getResourceMetadata is
> currently not completely defined. So one, could assume that
> 
>    resource.getResourceMetadata.put("xyz", "some data");
>    "some data".equals(resource.getResourceMetadata.get(xyz"));
> 
> If we wan to reuse Resource objects, this is dangerous .... There may be
> good reasons to have it, but it inherently makes the Resource non-thread
> safe for those background task resource resolvers.
> 
Yes, that's true - everything would be fine and easily doable if we just had
resource resolvers during request processing :)

And yes, you're right that returning the same resource might require to
make the resource implementations thread safe - which does not seem to
be worth the effort I guess.

Now while I do not care that much about the resource, I care more about
the adaptables :) Invoking adaptTo twice on the same resource produces
two different objects - with different state - for some adaptions this
doesn't matter while it might does for others. One thing is the
different state, the other is that the adaption might be a heavy process
which you want to avoid to be done several times.
But as we don't have a clean up mechanism I guess this is not that
easily doable - and maybe we can defer this to the developers: if the
adaption takes some time they should take care to call adaptTo only once
and reuse the object.

Carsten

-- 
Carsten Ziegeler
cziegeler@apache.org

Re: [RT] Identity of resources and adaptables

Posted by Felix Meschberger <fm...@gmail.com>.
Hi,

I think equals should hold. == should not be required (and even less
depended upon).

Especially in long used ResourceResolver instances having to guarantee
== will generate a memory hog sooner or later.

I agree that we might build in some caching to the ResourceResolver, for
example using an LRUMap or using WeakReferences for the GC to be able to
clean up in times of low memory conditions.

One thing, holds me back a bit: The Resource.getResourceMetadata is
currently not completely defined. So one, could assume that

   resource.getResourceMetadata.put("xyz", "some data");
   "some data".equals(resource.getResourceMetadata.get(xyz"));

If we wan to reuse Resource objects, this is dangerous .... There may be
good reasons to have it, but it inherently makes the Resource non-thread
safe for those background task resource resolvers.

Regards
Felix

On 15.01.2010 14:14, Carsten Ziegeler wrote:
> Ok, thanks for all answers so far :)
> 
> Bertrand Delacretaz wrote:
>> On Fri, Jan 15, 2010 at 1:15 PM, Alexander Klimetschek <ak...@day.com> wrote:
>>> ...Note that ensuring a == b can make implementations very difficult, as
>>> you need to cache all the Resource instances you returned to the API
>>> client. And what about handling this across multiple threads?...
>>
>> Right, I wouldn't go that far.
>>
>> Java programmers are (or should be) used to rely on equals as opposed to ==
>>
> Yes, that's right :) Ok, so here are my thoughts so far. I'm more with
> Justin and would expect that during a request response cycle the same
> resource object is returned for the same path from the same resource
> resolver. But I never would compare them with == :)
> 
> Implementing the caching here is easy (it would be a non synced cache
> which also improves performance in systems where a lot is happening
> during rendering).
> 
> Now obviously I've started this thread with something in mind. I've seen
> apps developed on top of Sling with a lot of happening during a request
> and with a lot of using the adapter pattern. So it happens during a
> single request that a getResource() is called for the same path and then
> this resource is adapted to some business object.
> 
> Of course as different calls to getResource end up with different
> resource objects, we end up with different business objects.
> Specifying everything like the jcr spec does is nice, but it keeps a
> high burden on the developer who implements resources and adaptables as
> you somehow have to take care that these different objects have the same
> state!
> 
> So from an implementation pov it would be easier to return the same
> resource object and then return the same adaptable. This could be done
> by Sling transparently. I think this would make things easier and speed
> up performance.
> 
> Now, unfortunately if we would only have a request response cycle this
> would be easily doable with simple caching etc.
> 
> But we have background stuff and caching resources in a resource
> resolver that runs forever doesn't seem to be a good idea. However this
> could be solved as well.
> 
> Carsten

Re: [RT] Identity of resources and adaptables

Posted by Carsten Ziegeler <cz...@apache.org>.
Ok, thanks for all answers so far :)

Bertrand Delacretaz wrote:
> On Fri, Jan 15, 2010 at 1:15 PM, Alexander Klimetschek <ak...@day.com> wrote:
>> ...Note that ensuring a == b can make implementations very difficult, as
>> you need to cache all the Resource instances you returned to the API
>> client. And what about handling this across multiple threads?...
> 
> Right, I wouldn't go that far.
> 
> Java programmers are (or should be) used to rely on equals as opposed to ==
> 
Yes, that's right :) Ok, so here are my thoughts so far. I'm more with
Justin and would expect that during a request response cycle the same
resource object is returned for the same path from the same resource
resolver. But I never would compare them with == :)

Implementing the caching here is easy (it would be a non synced cache
which also improves performance in systems where a lot is happening
during rendering).

Now obviously I've started this thread with something in mind. I've seen
apps developed on top of Sling with a lot of happening during a request
and with a lot of using the adapter pattern. So it happens during a
single request that a getResource() is called for the same path and then
this resource is adapted to some business object.

Of course as different calls to getResource end up with different
resource objects, we end up with different business objects.
Specifying everything like the jcr spec does is nice, but it keeps a
high burden on the developer who implements resources and adaptables as
you somehow have to take care that these different objects have the same
state!

So from an implementation pov it would be easier to return the same
resource object and then return the same adaptable. This could be done
by Sling transparently. I think this would make things easier and speed
up performance.

Now, unfortunately if we would only have a request response cycle this
would be easily doable with simple caching etc.

But we have background stuff and caching resources in a resource
resolver that runs forever doesn't seem to be a good idea. However this
could be solved as well.

Carsten
-- 
Carsten Ziegeler
cziegeler@apache.org

Re: [RT] Identity of resources and adaptables

Posted by Bertrand Delacretaz <bd...@apache.org>.
On Fri, Jan 15, 2010 at 1:15 PM, Alexander Klimetschek <ak...@day.com> wrote:
> ...Note that ensuring a == b can make implementations very difficult, as
> you need to cache all the Resource instances you returned to the API
> client. And what about handling this across multiple threads?...

Right, I wouldn't go that far.

Java programmers are (or should be) used to rely on equals as opposed to ==

-Bertrand

Re: [RT] Identity of resources and adaptables

Posted by Alexander Klimetschek <ak...@day.com>.
On Thu, Jan 14, 2010 at 17:28, Justin Edelson <ju...@gmail.com> wrote:
> But the more I think about it, the more I'm on the fence about:
> resolver.getResource("/a/b") == resolver.getResource("/a/b")
>
> My first instinct was basically what Mike wrote, this can be true, but isn't
> required to be so. But the more I think about it, I think this should always
> be true. I don't have a explanation why... still working on that part.

Note that ensuring a == b can make implementations very difficult, as
you need to cache all the Resource instances you returned to the API
client. And what about handling this across multiple threads?

There is a good reason why the JCR spec decided to state "a.equals(b)"
and internal state represented as equal, but not a == b.

Regards,
Alex

-- 
Alexander Klimetschek
alexander.klimetschek@day.com

Re: [RT] Identity of resources and adaptables

Posted by Justin Edelson <ju...@gmail.com>.
My initial reaction was basically what Mike wrote.

But the more I think about it, the more I'm on the fence about:
resolver.getResource("/a/b") == resolver.getResource("/a/b")

My first instinct was basically what Mike wrote, this can be true, but isn't
required to be so. But the more I think about it, I think this should always
be true. I don't have a explanation why... still working on that part.

It seems natural that r.adaptTo(Foo.class).equals(r.adaptTo(Foo.class)), but
this does seem like an implementation detail that Sling may or may not be
able to impose. JCR happens to require Node.equals() to do what is, IMHO,
the right thing, but requiring this on a different legacy API doesn't seem
feasible.

Justin


On Thu, Jan 14, 2010 at 9:41 AM, Carsten Ziegeler <cz...@apache.org>wrote:

> Mike Müller wrote:
> > Nobody seems to be willing to burn his finger on this topic,
> > nevertheless I try to jump in the hot pot...
>
> Hehe, thanks!
>
> > If the following is given and we talk about the same request
> >
> > Resource a = resolver.getResource("/a/b");
> > Resource b = resolver.getResource("/a/b");
> >
> > I would expect
> > a.equals(b) = true
> > but a == b does not have to be true (but could be)
> >
> > as of the JCR spec, even if in the same session between
> > retrieving a and b "/a/b" is changed, both a and b have to
> > reflect these changes.
> Good point!
>
> > In this case I think we're not allowed to make any assumptions
> > about the returned instance, so I would expect also
> >
> > n1.equals(n2) = true
> > n1 == n2 does not have to be true (but could be)
> >
> I see that I picked up a bad example here :) Now let's assume you
> want to adapt the resource to a PersistableValueMap
>
> PersistableValueMap p1 = resource.adaptTo(PersistableValueMap.class)
> PersistableValueMap p2 = resource.adaptTo(PersistableValueMap.class)
>
> p1 == p2? p1.equals(p2)?
>
> > In the case of the JCR as backend (which maybe hasn't to be the case
> > in the future if we introduce ResourceResolverFactoriy etc.) the
> > JCR spec says
> > "However, the state reflected by the object must at all times be
> > consistent with any other Item object (associated with the same
> > Session) representing the same actual item entity"
> > That means that even if the resource resolver returns an other
> > resource on the second call the first should return the same
> > (changed) properties, which means a.equals(b) should return true
> > even in this case.
> >
> > The question is here if we should specify this behavour for a
> > resource resolver in sling or not.
> Yepp, exactly :)
>
> Thanks for your answer, Mike! Anyone else?
>
> Regards
> Carsten
> --
> Carsten Ziegeler
> cziegeler@apache.org
>

Re: [RT] Identity of resources and adaptables

Posted by Carsten Ziegeler <cz...@apache.org>.
Mike Müller wrote:
> Nobody seems to be willing to burn his finger on this topic,
> nevertheless I try to jump in the hot pot...

Hehe, thanks!

> If the following is given and we talk about the same request
> 
> Resource a = resolver.getResource("/a/b");
> Resource b = resolver.getResource("/a/b");
> 
> I would expect
> a.equals(b) = true
> but a == b does not have to be true (but could be)
> 
> as of the JCR spec, even if in the same session between
> retrieving a and b "/a/b" is changed, both a and b have to
> reflect these changes.
Good point!

> In this case I think we're not allowed to make any assumptions
> about the returned instance, so I would expect also
> 
> n1.equals(n2) = true
> n1 == n2 does not have to be true (but could be)
> 
I see that I picked up a bad example here :) Now let's assume you
want to adapt the resource to a PersistableValueMap

PersistableValueMap p1 = resource.adaptTo(PersistableValueMap.class)
PersistableValueMap p2 = resource.adaptTo(PersistableValueMap.class)

p1 == p2? p1.equals(p2)?

> In the case of the JCR as backend (which maybe hasn't to be the case
> in the future if we introduce ResourceResolverFactoriy etc.) the
> JCR spec says
> "However, the state reflected by the object must at all times be
> consistent with any other Item object (associated with the same
> Session) representing the same actual item entity"
> That means that even if the resource resolver returns an other
> resource on the second call the first should return the same
> (changed) properties, which means a.equals(b) should return true
> even in this case.
> 
> The question is here if we should specify this behavour for a
> resource resolver in sling or not.
Yepp, exactly :)

Thanks for your answer, Mike! Anyone else?

Regards
Carsten
-- 
Carsten Ziegeler
cziegeler@apache.org

RE: [RT] Identity of resources and adaptables

Posted by Mike Müller <mi...@mysign.ch>.
Nobody seems to be willing to burn his finger on this topic,
nevertheless I try to jump in the hot pot...

> From: Carsten Ziegeler [mailto:cziegeler@apache.org]
> Hi,
>
> I've been thinking lately about identity of our objects, especially
> resource objects and adaptables.
>
> Without thinking about how this is implemented at the moment
> and without
> thinking if/how this could be implemented, what would you
> expect for the
> following: We simply get the same resource twice from the
> same resource
> resolver:
>
> ResourceResolver resolver;
>
> Resource a = resolver.getResource("/a/b");
> Resource b = resolver.getResource("/a/b");
>
> What should be true? a == b, a.equals(b) ?

If the following is given and we talk about the same request

Resource a = resolver.getResource("/a/b");
Resource b = resolver.getResource("/a/b");

I would expect
a.equals(b) = true
but a == b does not have to be true (but could be)

as of the JCR spec, even if in the same session between
retrieving a and b "/a/b" is changed, both a and b have to
reflect these changes.


> Next question: We get the same adaptable from a resource:
>
> Node n1 = a.adaptTo(Node.class);
> Node n2 = a.adaptTo(Node.class);
>
> Again: n1 == n2? n1.equals(n2)?

In this case I think we're not allowed to make any assumptions
about the returned instance, so I would expect also

n1.equals(n2) = true
n1 == n2 does not have to be true (but could be)


> While these questions seem to be trivial (more or less), it
> can get more
> subtle. Think about a resource resolver being used for a
> single request
> and getting the same resource during the request several times. Should
> it be possible to return different resources because the
> repository has
> changed during the request?

In the case of the JCR as backend (which maybe hasn't to be the case
in the future if we introduce ResourceResolverFactoriy etc.) the
JCR spec says
"However, the state reflected by the object must at all times be
consistent with any other Item object (associated with the same
Session) representing the same actual item entity"
That means that even if the resource resolver returns an other
resource on the second call the first should return the same
(changed) properties, which means a.equals(b) should return true
even in this case.

The question is here if we should specify this behavour for a
resource resolver in sling or not.

> Or the other way round. Think about an admin resource resolver running
> forever in the background.
>
> Before I post my answers I would like to get some other input? :)

best regards
mike