Wiki source code of UI Extension Points

Last modified by Eleni Cojocariu on 2026/10/09 15:14

Show last authors
1 A UI extension point (UIXP) is a named place in a rendered page that an extension can add content to without owning the code that renders it, a mechanism the [[UIExtension Module>>doc:extensions:Extension.UIExtension Module]] provides to the whole platform. The Applications Panel, the tabs below a page and the user menu are built this way: each one is an id, and what it shows is whatever is registered against that id when the page is rendered.
2
3 == Nothing Declares a Point ==
4
5 A point exists because something asks for its contributions by id. From wiki syntax, which inserts them one after another:
6
7 {{code language="none"}}
8 {{uiextensions extensionPoint="org.xwiki.platform.panels.Applications"/}}
9 {{/code}}
10
11 From script, which can lay them out instead:
12
13 {{code language="velocity"}}
14 {{velocity}}
15 #foreach ($uix in $services.uix.getExtensions('org.xwiki.platform.panels.Applications'))
16 * $services.rendering.render($uix.execute(), 'xhtml/1.0')
17 #end
18 {{/velocity}}
19 {{/code}}
20
21 The id is a plain string that nothing validates, so a point nobody contributes to and a point whose id is misspelled both render the same nothing. The points a release offers therefore cannot be read off the code, which is why each one gets a documentation page: [[All Bundled UI Extension Points>>doc:documentation.xs.dev.ui-extension-points.bundled.WebHome]] lists the ones XWiki ships, [[UI Extension Points (Extensions)>>doc:documentation.extensions.dev.ui-extension-points.WebHome]] the ones an installed extension brings, and the older [[Available Extension Points>>xwiki:Documentation.DevGuide.ExtensionPoint.WebHome]] list still holds the points neither page covers yet.
22
23 == How a Contribution Reaches the Point ==
24
25 {{plantuml}}
26 @startuml
27 !theme bluegray
28 skinparam nodesep 30
29 skinparam ranksep 40
30
31 rectangle "The page being rendered\nasks for an extension point id" as P
32 rectangle "UIExtensionManager" as M
33 database "Context component manager:\nthe UIExtension components\nvisible to this user, in this wiki" as CM
34 card "Those whose extension\npoint id matches" as L
35 rectangle "execute() on each of them" as E
36 card "The blocks they returned,\nwhere the point was asked for" as OUT
37
38 P --> M : point id
39 M --> CM : look up
40 CM --> L
41 L --> E
42 E --> OUT
43 @enduml
44 {{/plantuml}}
45
46 The lookup goes through the context component manager, so a contribution registered for the current user or the current wiki is found only there, and the same point rendered on another wiki of the farm does not see it. A component implementing ##UIExtensionManager## and registered under the point's own id replaces that lookup for that one point, which is how a point that computes its contributions rather than collecting them is built.
47
48 == Two Ways to Contribute ==
49
50 A contribution is either an ##XWiki.UIExtensionClass## object on a wiki page, which needs no build and no restart, or a Java component implementing the ##UIExtension## role. XWiki turns the object into one of those components, so both arrive at the same place. The object holds:
51
52 |=Field|=What it holds
53 |##extensionPointId##|The id of the point this contribution answers.
54 |##name##|The id of the contribution itself, by which the ##select##, ##exclude## and ##sortByCustomOrder## filters address it.
55 |##content##|The wiki syntax executed when the point is rendered, with the rights of the page's author.
56 |##parameters##|The values the point reads, one ##key=value## per line.
57 |##scope##|Current User, Current Wiki or Global, which decides the component manager the contribution is registered in and therefore who sees it.
58
59 == Order Is the Caller's Decision ==
60
61 The manager returns the contributions in no guaranteed order, and the ##uiextensions## macro inserts them as it receives them. A point that needs an order asks for it, by passing the hint of a ##UIExtensionFilter## component and the argument that filter takes:
62
63 {{code language="velocity"}}
64 $services.uix.getExtensions('org.xwiki.platform.panels.Applications', {'sortByParameter': 'order'})
65 {{/code}}
66
67 The bundled filters are ##sortById##, ##sortByParameter##, ##sortByCustomOrder##, ##select## and ##exclude##. A point that sorts on a parameter says so in its own documentation, since that parameter is part of what it asks its contributions for.

Get Connected