Search code examples
javacomponentslistenerxwiki

Register java based listeners in subwiki's for XWiki


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 :-)


Solution

  • Depending on your need, you might have at least 2 main solutions:

    1. 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.
    2. Use the Wiki Component Manager and actually register N instances of your listener, one for each wiki. To do that, you could:
      1. 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.
      2. 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.