PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/content/server/framework/atlassian-sdk/web-panel-renderer-plugin-module.md

https://bitbucket.org/zchristmas/atlassian-sdk-docs
Markdown | 240 lines | 194 code | 46 blank | 0 comment | 0 complexity | 474fc6c8b313362070d6accbed875578 MD5 | raw file
Possible License(s): LGPL-2.0
  1. ---
  2. aliases:
  3. - /server/framework/atlassian-sdk/web-panel-renderer-plugin-module-852106.html
  4. - /server/framework/atlassian-sdk/web-panel-renderer-plugin-module-852106.md
  5. category: reference
  6. confluence_id: 852106
  7. dac_edit_link: https://developer.atlassian.com/pages/editpage.action?cjm=wozere&pageId=852106
  8. dac_view_link: https://developer.atlassian.com/pages/viewpage.action?cjm=wozere&pageId=852106
  9. date: '2017-12-08'
  10. legacy_title: Web Panel Renderer Plugin Module
  11. platform: server
  12. product: atlassian-sdk
  13. subcategory: modules
  14. title: Web Panel Renderer plugin module
  15. ---
  16. # Web Panel Renderer plugin module
  17. <table>
  18. <colgroup>
  19. <col style="width: 20%" />
  20. <col style="width: 80%" />
  21. </colgroup>
  22. <tbody>
  23. <tr class="odd">
  24. <td><p>Available:</p></td>
  25. <td><p><a href="https://developer.atlassian.com/pages/viewpage.action?pageId=852001">Atlassian Plugin Framework 2.5</a> and later.</p></td>
  26. </tr>
  27. </tbody>
  28. </table>
  29. ## Purpose of this Module Type
  30. The Web Panel Renderer plugin module allows plugins to define custom renderer engines for [web panels](https://developer.atlassian.com/display/DOCS/Web+Panel+Plugin+Module) (web panels are bits of HTML that will be inserted into a page.)
  31. ## Configuration
  32. The root element for the Web Panel Renderer plugin module is `web-panel-renderer`. It allows the following attributes and child elements for configuration:
  33. #### Attributes
  34. <table>
  35. <colgroup>
  36. <col style="width: 20%" />
  37. <col style="width: 80%" />
  38. </colgroup>
  39. <thead>
  40. <tr class="header">
  41. <th><p>Name*</p></th>
  42. <th><p>Description</p></th>
  43. </tr>
  44. </thead>
  45. <tbody>
  46. <tr class="odd">
  47. <td><p>class</p></td>
  48. <td><p>The class which implements <a href="https://studio.atlassian.com/source/browse/PLUG/trunk/atlassian-plugins-webfragment/src/main/java/com/atlassian/plugin/web/renderer/WebPanelRenderer.java?r=56664" class="external-link">com.atlassian.plugin.web.renderer.WebPanelRenderer</a>.</p>
  49. <p>This class is responsible for turning a web panel's content into proper HTML.</p>
  50. <p>See the plugin framework guide to <a href="https://developer.atlassian.com/display/DOCS/Creating+Plugin+Module+Instances">creating plugin module instances</a>.</p></td>
  51. </tr>
  52. <tr class="even">
  53. <td><p>state</p>
  54. <p> </p></td>
  55. <td><p>Indicate whether the plugin module should be disabled by default (value='disabled') or enabled by default (value='enabled').</p>
  56. <p><strong>Default:</strong> enabled.</p></td>
  57. </tr>
  58. <tr class="odd">
  59. <td><p>i18n-name-key</p></td>
  60. <td>The localisation key for the human-readable name of the plugin module.</td>
  61. </tr>
  62. <tr class="even">
  63. <td><p>key</p></td>
  64. <td>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.
  65. <pre><code>&lt;component-import
  66. key=&quot;appProps&quot;
  67. interface=&quot;com.atlassian.sal.api.ApplicationProperties&quot;/&gt;</code></pre>
  68. <p>In the example, <code>appProps</code> is the key for this particular module declaration, for <code>component-import</code>, in this case.</p></td>
  69. </tr>
  70. <tr class="odd">
  71. <td><p>name</p></td>
  72. <td><p>The human-readable name of the plugin module.</p>
  73. <p>Used only in the plugin's administrative user interface.</p></td>
  74. </tr>
  75. <tr class="even">
  76. <td><p>system</p></td>
  77. <td><p>Indicates whether this plugin module is a system plugin module (value='true') or not (value='false'). Only available for non-OSGi plugins.</p>
  78. <p><strong>Default:</strong> false.</p></td>
  79. </tr>
  80. </tbody>
  81. </table>
  82. **\*class and key attributes are required.**
  83. ## Writing a Custom Renderer
  84. To create your own renderer you should create a class that implements <a href="https://studio.atlassian.com/source/browse/PLUG/trunk/atlassian-plugins-webfragment/src/main/java/com/atlassian/plugin/web/renderer/WebPanelRenderer.java?r=56664" class="external-link">com.atlassian.plugin.web.renderer.WebPanelRenderer</a>.
  85. As an example we will create a plugin for the <a href="https://studio.atlassian.com/browse/REFAPP" class="external-link">Atlassian Reference Application</a> (version 2.5.0 or higher). We will create a web panel template renderer for <a href="http://freemarker.sourceforge.net" class="external-link">FreeMarker templates</a>, 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.
  86. 1. Using the [Atlassian Plugin SDK](https://developer.atlassian.com/display/DOCS/Working+with+the+SDK), create a new plugin for the Reference Application and make sure the generated `pom.xml` file uses version 2.5.0 or higher:
  87. ``` bash
  88. $ atlas-create-refapp-plugin
  89. ```
  90. 2. Add the FreeMarker library to the Maven dependencies:
  91. **pom.xml**
  92. ``` xml
  93. ...
  94. <dependency>
  95. <groupId>freemarker</groupId>
  96. <artifactId>freemarker</artifactId>
  97. <version>2.3.9</version>
  98. </dependency>
  99. ...
  100. ```
  101. 3. Create your renderer class:
  102. ``` java
  103. package refapptest.freemarker;
  104. import com.atlassian.plugin.Plugin;
  105. import com.atlassian.plugin.web.renderer.RendererException;
  106. import com.atlassian.plugin.web.renderer.WebPanelRenderer;
  107. import freemarker.cache.ClassTemplateLoader;
  108. import freemarker.template.Configuration;
  109. import freemarker.template.DefaultObjectWrapper;
  110. import freemarker.template.Template;
  111. import freemarker.template.TemplateException;
  112. import java.io.IOException;
  113. import java.io.Writer;
  114. import java.util.Map;
  115. public class FreeMarkerWebPanelRenderer implements WebPanelRenderer
  116. {
  117. private Template loadTemplate(String filename) throws IOException
  118. {
  119. final Configuration conf = new Configuration();
  120. conf.setObjectWrapper(new DefaultObjectWrapper());
  121. conf.setTemplateLoader(new ClassTemplateLoader(this.getClass(), "/"));
  122. return conf.getTemplate(filename);
  123. }
  124. public String getResourceType()
  125. {
  126. return "freemarker";
  127. }
  128. public void render(String templateFile, Plugin plugin, Map<String, Object> stringObjectMap, Writer writer)
  129. throws RendererException, IOException
  130. {
  131. try
  132. {
  133. loadTemplate(templateFile).process(stringObjectMap, writer);
  134. }
  135. catch (TemplateException te)
  136. {
  137. throw new RendererException(String.format(
  138. "Unable to render freemarker template %s: %s", templateFile, te.getMessage()), te);
  139. }
  140. }
  141. public String renderFragment(String templateFile, Plugin plugin, Map<String, Object> stringObjectMap)
  142. throws RendererException
  143. {
  144. throw new AssertionError("Not yet implemented.");
  145. }
  146. }
  147. ```
  148. 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`.
  149. 4. Add the new renderer to `atlassian-plugin.xml`:
  150. **atlassian-plugin.xml**
  151. ``` xml
  152. ...
  153. <web-panel-renderer key="freemarkerWebPanelRenderer" class="refapptest.freemarker.FreeMarkerWebPanelRenderer"/>
  154. ...
  155. ```
  156. 5. Add a web panel to the Reference Application's administration page that uses this new renderer:
  157. **atlassian-plugin.xml**
  158. ``` xml
  159. ...
  160. <web-panel key="aFreeMarkerPanel" location="atl.admin.body">
  161. <resource name="view" type="freemarker" location="templates/mytemplate.ftl"/>
  162. </web-panel>
  163. ...
  164. ```
  165. 6. Add your FreeMarker template:
  166. **src/main/resources/templates/mytemplate.ftl**
  167. ``` xml
  168. <#assign color = "DarkRed">
  169. <div style="color: ${color};">
  170. <p>
  171. This is a FreeMarker Web Panel!
  172. </p>
  173. <#assign people = [{"name":"Joe", "age":25}, {"name":"Fred", "age":18}]>
  174. <ul>
  175. <#list people as person>
  176. <li>${person.name} is ${person.age}</li>
  177. </#list>
  178. </ul>
  179. </div>
  180. ```
  181. 7. Start up the Reference Application using the command: `$ atlas-mvn refapp:run`
  182. 8. Go to: <a href="http://localhost:5990/refapp/admin" class="uri external-link">localhost:5990/refapp/admin</a>
  183. ## Known Limitations
  184. 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.
  185. 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.
  186. 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()`.
  187. 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.
  188. ## Source Code
  189. To access the full source code for this plugin, you can:
  190. - <a href="http://svn.atlassian.com/fisheye/browse/public/contrib/tutorials/web-panel-renderer/trunk" class="external-link">browse it online</a>.
  191. - <a href="https://svn.atlassian.com/svn/public/contrib/tutorials/web-panel-renderer/trunk" class="external-link">check it out from Subversion</a>.
  192. ##### RELATED TOPICS
  193. [Web Panel Plugin Module](https://developer.atlassian.com/display/PLUGINFRAMEWORK/Web+Panel+Plugin+Module)
  194. [Plugin Modules](/server/framework/atlassian-sdk/plugin-modules)