We are working on a wiki farm containing various similar subwiki’s for various clients. The challenge I am really struggling with is, that I want to have different (java based) listeners registered for each subwiki. An example of such a listener is one that listens for save events to change the titel of the Wikipage. For this, I use model data stored in objects that might be different for each subwiki. In order to prevent having to reload these models every time the event is triggered, I want the model to be loaded once and re-use it. However, I have searched the last couple of days’s to find ways of defining / registering etc. listener components on a per-wiki basis but I can’t find what I am looking for.
Can someone help me understand how to build these listeners this way by (for example) directing me to an example?
Any help is highly appreciated :-)
Depending on your need, you might have at least 2 main solutions:
- Use a single listener installed on the entire farm (either
installed on the entire farm with the Extension Manager or just by
dumping the jar in the "lib" folder) and keep a cache of your model,
using the current wikiID as key. That way, when intercepting an
event, your listener would get the current wiki ID (either from the
context or from the affected document's reference) and use it to
lookup the in-memory model, thus no longer requiring to initialize
the model for each event. The cache can be anything from a simple
map to a more configurable and scalable solution such as using
XWiki's Cache Module.
- Use the Wiki Component Manager and actually register N instances
of your listener, one for each wiki. To do that, you could:
- Deploy and use the Extension Manager UI to install your component on each individual wikis (careful, not on the entire farm!). You
could simplify this by making your component a dependency of the
UI/flavor that you install on the subwiki, so that it will be
installed automatically on the subwiki when you install the UI of
that subwiki. This way, you component's code should only care about
the current wiki (that it's installed on) and would only care about
caching the model of the current wiki.
- Alternatively, a programmatic method would imply iterating over each existing wiki and, for each, setting the context wiki to the
currently iterated wiki, dynamically getting the "wiki"
ComponentManager (lookup "Namespaced Component Manager" in the "Component Module"'s documentation), creating a new instance of your listener and
registering it to that wiki component manager. This code would run
once, when the XWiki instance is started. However, you would then
have to keep these component instances synchronized and, whenever a
new wiki is created, you would have to register a new listener
instance for it as well. There is no declarative way ATM that would
simplify this process.
I don`t really recommend method 2.2 since, even if it might be possible, is unnecessarily complex.
Method 2.1 would be the simplest to write, but then needs a bit of work to deploy (i.e. your artefact needs to be available in a configured maven repo or in an XWiki Repository (also lookup the "XWiki Repository Application") so that the Extension Manager can install it).
Method 1 is both easy to implement and to deploy, so if that suits your usecase, I recommend it.
Edit: As noted in the comments, option 2 is not currently supported. See XCOMMONS-213 for more details.