This module type allows you to put arbitrary context items into the context of any Using the Atlassian Template Renderer. This is useful to ensure plugin developers don't have to repeatedly create the same context each time they need to render content.
This module type is similar to the Confluence velocity-context-item module type. However, it is more powerful in the following ways:
The root element for the Template Context Items plugin module is template-context-item
. It allows the following attributes for configuration:
Name* | Description |
---|---|
context-key | The key with which the context item is referenced from templates, e.g. $i18n in the example below. |
component-ref | A reference to a component in the plugin's application context. To reference OSGi services or host components, import the component using component-import. The component will be looked up on each use, so prototype spring beans will be newly instantiated each time. |
class | The class that should be instantiated and put into the context. This will be a singleton. Note: either this or component-ref, but not both, is required. |
global | True if the context item should be available to contexts for all plugins. Default: false. |
*context-key attribute is required.
1 2<template-context-item key="i18nResolveContextItem" component-ref="i18nResolver" context-key="i18n" global="true" name="I18nResolver Context Item"/>
When rendering templates for other plugins, you need to ensure your plugin gets the template renderer for the other plugins bundle. There are many ways to do this, and all involve getting a hold of the plugins BundleContext
. With the bundle context, you can lookup the TemplateRenderer
service, however, in most cases you won't want to do this directly, as you may encounter problems if the template renderer has not been enabled yet, or is restarted. It will usually be more appropriate to use a ServiceTracker
, and access the template renderer through that.
The following are the two best ways of getting a hold of the plugins BundleContext
, which will apply depending on your situation:
Plugin
objectThis will be the case if you have defined a dynamic module type, from which you can access the plugins Plugin
object. In this case, you can access the BundleContext
like so:
1 2BundleContext ctx = ((OsgiPlugin) plugin).getBundle().getBundleContext();
In this case, you should expose an OSGi ServiceFactory
for your service. These work in the same way to Springs FactoryBean
's. Here's an example:
1 2public class MyServiceServiceFactory implements ServiceFactory { public Object getService(Bundle bundle, ServiceRegistration registration) { return new MyService(bundle.getBundleContext()); } ... }
ServiceTracker
Once you have a BundleContext
, you need to create ServiceTracker
that tracks the TemplateRenderer
service in the plugins BundleContext
:
1 2private final ServiceTracker templateRendererServiceTracker; public MyService(BundleContext bundleContext) { templateRendererServiceTracker = new ServiceTracker(bundleContext, TemplateRenderer.class.getName(), null); templateRendererServiceTracker.open(); }
Now you can use the service using the getService()
. The important thing that you need to worry about is handling if the service isn't available. Sometimes it may be appropriate to do no action, at other times, you may want to throw an exception:
1 2TemplateRenderer renderer = (TemplateRenderer) templateRendererServiceTracker.getService(); if (renderer == null) { throw new RuntimeException("TemplateRenderer service not available"); } // Now use the renderer
Finally, it's important that you close the ServiceTracker
once you're finished using it. There are a number of reasons why this might happen:
Closing the service tracker should be done in your plugin module type descriptors disable method, or your ServiceFactory
's unget method. For example:
1 2public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) { ((MyService) service).closeTemplateRendererServiceTracker(); }
In MyService
you would then have a corresponding method that would call the close()
method on the service tracker.
Rate this page: