Magnolia 5.7 reached extended end of life on May 31, 2022. Support for this branch is limited, see End-of-life policy. Please note that to cover the extra maintenance effort, this EEoL period is a paid extension in the life of the branch. Customers who opt for the extended maintenance will need a new license key to run future versions of Magnolia 5.7. If you have any questions or to subscribe to the extended maintenance, please get in touch with your local contact at Magnolia.
On this page we look at typical Magnolia URLs and learn how the fragment part of a URL makes location tracking possible. With fragments you can pinpoint detailed locations in the system. Users can bookmark their favorite apps, pages and nodes.
Parts of a URL
A typical AdminCentral URL in the Magnolia back end looks like this:
Parts of a URL:
- Protocol:
http
orhttps
. - Domain: Domain name as mapped in the site definition.
- Port: Port number.
- Context path: In a Magnolia URL the context path represents a Web application such as
magnoliaAuthor
ormagnoliaPublic
. - Servlet mapping : Identifies the servlet that should respond to the request.
- Fragment : Keeps track of an app's internal state. Identifies the name of the app, the subapp, and optionally a path.
Servlet mapping
A servlet responds to a request. Servlets are mapped in the servlet filter chain. By convention, a Magnolia servlet mapping starts with the dot character, for example /.magnolia/admincentral
for AdminCentral resources or /.rest
for REST resources.
A REST URL is a good example of complex servlet mapping. The URL requests the page /travel/about
. The servlet mapping part contains detailed information about the requested resource.
Parts of a servlet mapping:
- Servlet: The first part of the mapping identifies the servlet, in this case
/.rest
. - Endpoint: Identifies the REST endpoint where the request is issued:
nodes
,properties
orcommands
. - Version: REST Web services are versioned. The version number is built into the service URL.
- Workspace: Identifies which workspace in the
magnolia
repository has the requested content. - Node path: Location of the content in the workspace.
Fragment
#
. In AdminCentral URLs, the fragment keeps track of an app's internal state. It identifies the name of the app, the subapp that is open, and optionally a path to the content that is operated on. In public URLs the fragment identifies an anchor.The parts that come after the hash are separated from each other with a colon :
. The following fragment identifies the Contacts app . The detail subapp is currently open. The user is looking at version 1.0 of the node /vvangogh
.
Parts of a fragment:
- App type: The type is
app
for normal apps andshell
for one of the three special Shell apps: App Launcher, Pulse and Favorites. For your own apps, this part will always beapp
. - App name: Name of the app as configured in the app descriptor. The internal names of the three shell apps are
applauncher
,pulse
andfavorite
. Normal apps are also named in a predictable way: Pages ispages
, Assets isassets
and so on. Magnolia uses the app name to identify the app across the system. - Subapp ID : ID of the subapp as configured in the subapp descriptor. Subapps are displayed to users as tabs. Every app has at least one subapp. In a content app subapps are called
browser
anddetail
. In custom apps you can name your subapps as you want. Magnolia recommends that you name your main subappmain
for consistency. Themain
subapp can be the only subapp if the app does not provide any other subapps. - Node path: Path to the node being operated on.
- View type:
edit
,view
(preview),treeview
,listview
,thumbnailview
orsearchview
. - Version: Version of the node.
Example fragments
Pulse shell app.
#shell:pulse
Pages app with the browser subapp open. The /travel/about
page is currently selected in the treeview.
#app:pages:browser;/travel/about:treeview
Pages app with an detail subapp open. The /travel/about
page is being edited.
#app:pages:detail;/travel/about:edit
Pages app with a detail subapp open. The /travel/about
page is being previewed. The view
parameter instructs the app to display the page in preview mode.
#app:pages:detail;/travel/about:view
Subapp ID and its parameters
The subapp ID part of the fragment holds the subapp’s name and optional parameters. Each subapp ID is unique within the app. This allows the system to recognize a tab that is already open and bring that tab into focus rather than open a duplicate. For example, when the Pages app opens a detail subapp it assigns the subapp a unique ID consisting of the subapp name (detail
) and the path to the page (/travel/about
). If the user already has the page open the app brings the tab into focus when it is requested.
#app:pages:detail;/travel/about
A node path is the most common example of a parameter. The path identifies the node being viewed or edited, for example /travel/about
. The subapp ID and the node path are separated with a semicolon. We cannot use the colon character here as it would break the token.
Custom parameters inside the fragment
Here is an example of custom parameters in the fragment. The Preview app is being used to preview personalized content.
Parameters:
previewPersona
assigns a persona who represents the target audience.previewDate
assigns a date.
Here's what the Preview app looks like in the browser.
Selectors
A selector is a part of a URI between the first selector delimiter ~
(tilde) and the last selector delimiter.
Selectors are similar to query parameters in that they allow you to pass information to a servlet. The difference is that a query parameter sends input to be processed whereas a selector describes how you want to receive the requested resource. In this respect selectors are like extensions. The extension .html
specifies that you want to receive the resource as an HTML document. The selector ~Culture~
specifies that you want a list of tours about culture. It is still the same resource (tours list page) but instead of all tours you want it filtered by the category Culture.
For more on request parameters vs. selectors see Selectors and Request Parameters: Getting it Straight (page snapshot at archive.org).
Magnolia uses the tilde character ~
as a selector delimiter. In other systems such as Apache Sling you may see the dot character .
used as a delimiter. We can't use the dot in Magnolia because the JCR specification allows dots in node names, and consequently in URIs, with the single limitation that a dot cannot be the first character. This means a page page.one
, a document magnolia.flyer.pdf
, an a JavaScript file jquery.tabtree
are all perfectly valid node names and must work in URIs.
The
Path
class sets ~
(tilde) as the delimiter in the SELECTOR_DELIMITER
constant (String).
Splitting selectors
The whole selector can be split into several selectors separated from each other by the same delimiter ~
(tilde):
- Whole selector:
~Culture~a=1~b=2~
- Selector 1:
~Culture~
- Selector 2:
~a=1~
- Selector 3:
~b=2~
Getting and setting selectors
A selector can also be in the form name=value
. For example in
/mypage~foo=bar~.html
where foo=bar
is a name-value selector.
Name-value selectors are exposed by MgnlContext.getAttribute(selectorName)
and have a "local" scope similar to HttpServletRequest scope. In the example, MgnlContext.getAttribute("foo")
will return the String bar
whereas MgnlContext.getAttribute("foo", Context.SESSION_SCOPE)
or MgnlContext.getAttribute("foo", Context.APPLICATION_SCOPE)
will return null.
AggregationState
this class exposes some methods to set and get selectors.
setSelector(String selector)
is currently used byinfo.magnolia.cms.filters.RepositoryMappingFilter
where the request URI is parsed and the selector part extracted.String getSelector()
returns the whole selector. I.e given the URIhttp://myserver/mypage~x~foo=bar~.html
this method will return the String x~foo=barString[] getSelectors()
returns the selector split into its discrete elements. I.e given the URIhttp://myserver/mypage~x~foo=bar~.html
this method will return an array of two elements containing the "x" and the "foo=bar" String(s)
SelectorUtil
SelectorUtil is a utility class that provides two methods which are basically shortcuts to the getters in AggregationState
:
String getSelector()
String getSelector(int index)
Caching of selector URIs
Magnolia caches URIs that have selectors by default. Selectors are not a performance constraint. However, when a request parameter is present the URI is excluded from the cache.
/mypage~category=Culture~.html
is cached/mypage.html?category=Culture
is not cached
Creating a browsing history with fragments
The URL fragment can pinpoint very fine-grained locations in the system such as a particular page or configuration node. This makes it possible to build a detailed browsing history. Navigating a browsing history via fragments is not a unique concept. We adopted it from the Google Web Toolkit (GWT):
For each page that is to be navigable in the history, the application should generate a unique history token. A token is simply a string that the application can parse to return to a particular state. This token will be saved in browser history as a URL fragment (in the location bar, after the "#"), and this fragment is passed back to the application when the user goes back or forward in history, or follows a link.
Moving back and forward in browser history
This is how modern Web applications should work: rather than prevent the user from clicking the Back and Forward buttons, let them do what feels intuitive. If clicking Back seems like the right thing to do to get to the previous state then the application should support that feeling. Using the URL fragment allows the user to use the browser’s own back and forward functionality.
Sharing favorites
One of the advantages of bookmarking locations in the Favorites app is that they are automatically ported. If you work on multiple computers and different browser, the bookmarks are still available. The favorites functionality is also a relief for system administrators who need to provision functionality to a large user base. An admin can create a set of pre-defined bookmarks that all users get out of the box.