Available: | Atlassian Plugin Framework 2.5 and later. |
The Web Panel Renderer plugin module allows plugins to define custom renderer engines for web panels (web panels are bits of HTML that will be inserted into a page.)
The root element for the Web Panel Renderer plugin module is web-panel-renderer
. It allows the following attributes and child elements for configuration:
Name* | Description |
---|---|
class | The class which implements com.atlassian.plugin.web.renderer.WebPanelRenderer. This class is responsible for turning a web panel's content into proper HTML. See the plugin framework guide to creating plugin module instances. |
state
| Indicate whether the plugin module should be disabled by default (value='disabled') or enabled by default (value='enabled'). Default: enabled. |
i18n-name-key | The localisation key for the human-readable name of the plugin module. |
key | The unique identifier of the plugin module. You refer to this key to use the resource from other contexts in your plugin, such as from the plugin Java code or JavaScript resources.
In the example, |
name | The human-readable name of the plugin module. Used only in the plugin's administrative user interface. |
system | Indicates whether this plugin module is a system plugin module (value='true') or not (value='false'). Only available for non-OSGi plugins. Default: false. |
*class and key attributes are required.
To create your own renderer you should create a class that implements com.atlassian.plugin.web.renderer.WebPanelRenderer.
As an example we will create a plugin for the Atlassian Reference Application (version 2.5.0 or higher). We will create a web panel template renderer for FreeMarker templates, which is a format that is not supported by the Atlassian Plugin Framework out of the box. We will then also add a web panel that uses a FreeMarker template.
Using the Atlassian Plugin SDK, create a new plugin for the Reference Application and make sure the generated pom.xml
file uses version 2.5.0 or higher:
1 2$ atlas-create-refapp-plugin
Add the FreeMarker library to the Maven dependencies:
pom.xml
1 2... <dependency> <groupId>freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.9</version> </dependency> ...
Create your renderer class:
1 2package refapptest.freemarker; import com.atlassian.plugin.Plugin; import com.atlassian.plugin.web.renderer.RendererException; import com.atlassian.plugin.web.renderer.WebPanelRenderer; import freemarker.cache.ClassTemplateLoader; import freemarker.template.Configuration; import freemarker.template.DefaultObjectWrapper; import freemarker.template.Template; import freemarker.template.TemplateException; import java.io.IOException; import java.io.Writer; import java.util.Map; public class FreeMarkerWebPanelRenderer implements WebPanelRenderer { private Template loadTemplate(String filename) throws IOException { final Configuration conf = new Configuration(); conf.setObjectWrapper(new DefaultObjectWrapper()); conf.setTemplateLoader(new ClassTemplateLoader(this.getClass(), "/")); return conf.getTemplate(filename); } public String getResourceType() { return "freemarker"; } public void render(String templateFile, Plugin plugin, Map<String, Object> stringObjectMap, Writer writer) throws RendererException, IOException { try { loadTemplate(templateFile).process(stringObjectMap, writer); } catch (TemplateException te) { throw new RendererException(String.format( "Unable to render freemarker template %s: %s", templateFile, te.getMessage()), te); } } public String renderFragment(String templateFile, Plugin plugin, Map<String, Object> stringObjectMap) throws RendererException { throw new AssertionError("Not yet implemented."); } }
Note how the WebPanelRenderer
interface declares two render methods: one that takes the name of a template file and one that takes the whole template as a String. In this example we have only implemented the former method. The latter is left as an exercise for you. The consequence of this is that we will not be able to embed our FreeMarker content in atlassian-plugin.xml
.
Add the new renderer to atlassian-plugin.xml
:
atlassian-plugin.xml
1 2... <web-panel-renderer key="freemarkerWebPanelRenderer" class="refapptest.freemarker.FreeMarkerWebPanelRenderer"/> ...
Add a web panel to the Reference Application's administration page that uses this new renderer:
atlassian-plugin.xml
1 2... <web-panel key="aFreeMarkerPanel" location="atl.admin.body"> <resource name="view" type="freemarker" location="templates/mytemplate.ftl"/> </web-panel> ...
Add your FreeMarker template:
src/main/resources/templates/mytemplate.ftl
1 2<#assign color = "DarkRed"> <div style="color: ${color};"> <p> This is a FreeMarker Web Panel! </p> <#assign people = [{"name":"Joe", "age":25}, {"name":"Fred", "age":18}]> <ul> <#list people as person> <li>${person.name} is ${person.age}</li> </#list> </ul> </div>
Start up the Reference Application using the command: $ atlas-mvn refapp:run
Go to: localhost:5990/refapp/admin
You may have noticed how the configuration for our FreeMarker's template loader uses a freemarker.cache.ClassTemplateLoader
instance which expects templates to be on the classpath. To do this, FreeMarker's ClassTemplateLoader
constructor takes a Class
instance and then calls Class.getResource()
when it needs to load a template.
In our example we use FreeMarkerWebPanelRenderer.class
, which means that our renderer is limited to rendering templates that live in its own plugin JAR file. This is sufficient for this tutorial which has the renderer, the web panel and the template all in the same plugin. However, it would not work when the renderer is shared with other plugins and needs to render a template that lives in another plugin JAR.
If you want to build a shared FreeMarker renderer this way, you would have to implement your own freemarker.cache.TemplateLoader
. Instead of taking a Class
instance, your template loader would take the ClassLoader
that is returned by plugin.getClassLoader()
.
To keep the example clear and simple, we have chosen to accept this limitation. However, note that it has been addressed properly in the full source code that is available below.
To access the full source code for this plugin, you can:
Rate this page: