Looking at the source of ResourceResolver in current Sling trunk:
for (MapEntry mapEntry : resourceMapper.getMapMaps()) {
String[] mappedPaths = mapEntry.replace(mappedPath);
if (mappedPaths != null) {
....
break;
}
}
confirms that the first matching mapping entry is used as you observe.
If you look at the MapEntry class used there, you'll see that it does
not work according to the heirarchy of how things are defined in
/etc/map but according to the complete URL pattern. The first matching
entry will be used.
When you originally posted about the problem, it was when you cross from
content multi 1 to multi 2 that the problem shows up. Definitely leads
me to see that what you're looking for is for the resolver/mapper to
understand the intention of the transformations in the map and the
relationship between the content. It really isn't that smart,
unfortunately. It does not understand that the content is correlated
as being on the same level, or the pattern that we see when we see a
numbered progression (set membership?).
When I do work on apps this is what I would call the "Application
Context" where sling is only working in a request context.
I think your solution with LinkRewriter or anything else where you write
the logic to correlate multi1 and multi2 are the best solutions. I also
still think that whatever alias/reference methods are available at the
sling level are worth looking into as is the suggestion that someone
else made to use relative paths. Then you would be expressing the
relationships directly (explicitly and implicitly respectively).
Hope this helps,
Jonathan 'J5' Cook
[email protected] wrote:
Hi Jonathan,
you are right about the mapping. In fact I do use /etc/map root level mappings
like a many-to-one mapping.
E.g. similar to:
/etc/map/
|--/http
|--|--/any_host
|--|--|--/group1_multi
|--|--|--|--.sling:internalRedirect=/multi
|--|--|--/group2_multi
|--|--|--|--.sling:internalRedirect=/multi
The resolving works quite as you would expect. A request
http://any_host/group2_multi gets correctly resolved to /multi node.
Response-rewriting also gets applied. Sling automatically uses the deepest root
level mapping rule available. Two rules apply here to /multi, but they are on
the same level. And in this case, Sling seems to choose just the first. So my
request to http://any_host/group2_multi gets resolved to /multi, but the
rewriting of links to /multi node on this page will be done to
http://any_host/group1_multi.
The optimal solution (for my use case) would be: If there are multiple deepest
root level mappings for a resource, choose the one which was used for resolving
the request, not just simply the first one.
BTW: I also use CQ5, not just plain Sling ;-) But the behaviour and problem is
quite the same.
Regards,
Matthias
Jonathan Cook <[email protected]> hat am 14. September 2009 um 18:14
geschrieben:
It looks like you are trying to reverse a many-to-one mapping.
Let's simplify this even further
Inbound Transformation:
a/1 -> x/1
b/1 -> x/1
Desired Outbound Transformation:
x/1 -> a/1
x/1 -> b/1
This clarifies the domain of the problem, which is the behavior of the
outbound transformation, which is implemented in ResourceResolver.map()
You may be confusing the problem when you refer to x/1 as being a/1 --
it's not. As soon as the inbound resolution takes place, it becomes
x/1. The operations of the code attached to x/1 happen on x/1.
Taking a step back to the desired outcome rather than the specific
behavior that you don't want, namely that a/1 behave as if it were x/1,
I would guess that the aliasing functionality is more appropriate as a
solution to your problem than the ResourceResolver/mapping system.
You need to actually have a node at a/1 (your /group1/multi1) and that
node needs to be a reference to x/1 (your /multi/multi1) for the
"mapping" to work as desired.
If you want to go back to looking at the ResourceResolver.map and trying
to see how it could do the many-to-one mapping, you must introduce
another variable so that you are in fact reversing a more complex
one-to-one mapping. For instance, taking into account the original path
or other members of the request object. That path (or other value) must
then either be explicitly sent with the map call (essentially what you
are doing with your custom LinkRewriter, I'd wager) or be derivable.
From what I understand about the algorithm used by the new
ResourceResolver, it will attempt to derive the path from the
originating request when a map is performed, but will not be able to
when the original inbound transformation is done via a regular
expression. It attempts to derive the path value that lets it turn the
many-to-one mapping into a one-to-one mapping that can be reversed.
Remove use of regex from your inbound mappings and you may find that you
already have functioning outbound mappings. In that case, if the output
you get is not what is desired, try calling the ResourceResolver.map
method explicitly. I don't work with raw SLING (only with Day CQ as of
yet) so I don't know whether there IS any automatic remapping of URLs
done in the vanilla SLING.
Regards,
Jonathan 'J5' Cook
P.S. I hate to advertise but I am a
Day/Javascript/Java/anything-you-throw-at-me
developer/architect/handyman looking for telecommute work or work in the
Northern Virginia / Washington DC area. If you can help or are
interested in discussing a position with me, please don't hesitate to
contact me via email or GTalk.
Markus Pallo wrote:
We have a similar use case and still not solved yet ....
During searching i found
https://issues.apache.org/jira/browse/SLING-598 and thought probably
it could be helpful to use some url like
http://host/group1/uuid-{uuid ofmulti_content1}
and to resolve path to parent manually if its a child of my "multi".
what do you think ?
Markus
I currently have a use case for Sling rewriting, but still found no
"out-of-the-box" solution in the Sling flexible resource resolution
for it.
My application has a requirement for a node which should be virtually
duplicated. The example node structure is like this:
/group1
/group2
/multi
|--/multi_content1
|--/multi_content2
"Multi" should be available for each group individually. The content
stays the same, but it acts differently in each group depending on
the JCR-path or URI. To avoid problems with double-namings in the
"real" group-content and in the "multi" group-content, I decided to
use a seperate node for each multi-group with suffix "_multi".
So the structure should look virtually like this:
/group1
/group1_multi
|--/multi_content1
|--/multi_content2
/group2
/group2_multi
|--/multi_content1
|--/multi_content2
/multi
|--/multi_content1
|--/multi_content2
The goal is to handle requests like this with the same content (but
different path / URI):
/group1_multi/multi_content_1 --> /multi/multi_content1
/group2_multi/multi_content_1 --> /multi/multi_content1