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

/content/server/jira/platform/module-type.md

https://bitbucket.org/mrzymski/jira-server-docs
Markdown | 213 lines | 175 code | 38 blank | 0 comment | 0 complexity | c028b4c7b4adb830ae2f155405655578 MD5 | raw file
  1. ---
  2. aliases:
  3. - /server/jira/platform/module-type-plugin-module-4227083.html
  4. - /server/jira/platform/module-type-plugin-module-4227083.md
  5. category: reference
  6. confluence_id: 4227083
  7. dac_edit_link: https://developer.atlassian.com/pages/editpage.action?cjm=wozere&pageId=4227083
  8. dac_view_link: https://developer.atlassian.com/pages/viewpage.action?cjm=wozere&pageId=4227083
  9. date: '2017-12-08'
  10. legacy_title: Module Type Plugin Module
  11. platform: server
  12. product: jira
  13. subcategory: modules
  14. title: Module type
  15. ---
  16. # Module type
  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>The Module Type plugin module is available only for OSGi-based plugins in JIRA 4.0 and later.</p></td>
  26. </tr>
  27. </tbody>
  28. </table>
  29. ## Purpose of this Module Type
  30. Module Type plugin modules allow you to dynamically add new plugin module types to the plugin framework, generally building on other plugin modules. For example, a plugin developer could create a `<dictionary>` plugin module that is used to feed a dictionary service used by still other plugins.
  31. ## Configuration
  32. The root element for the Module Type plugin module is `module-type`. 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 ModuleDescriptor class to instantiate when a new plugin module of this type is found.</p>
  49. <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>
  50. </tr>
  51. <tr class="even">
  52. <td><p>state</p>
  53. <p> </p></td>
  54. <td><p>Indicate whether the plugin module should be disabled by default (value='disabled') or enabled by default (value='enabled').</p>
  55. <p><strong>Default:</strong> enabled.</p></td>
  56. </tr>
  57. <tr class="odd">
  58. <td><p>i18n-name-key</p></td>
  59. <td>The localisation key for the human-readable name of the plugin module.</td>
  60. </tr>
  61. <tr class="even">
  62. <td><p>key</p></td>
  63. <td><p>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.</p>
  64. <p> </p>
  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> </p>
  69. <p>In the example, <code>appProps</code> is the key for this particular module declaration, for <code>component-import</code>, in this case.</p>
  70.  
  71. <p>I.e. the identifier of the module type. This value will be used as the XML element name to match.</p></td>
  72. </tr>
  73. <tr class="odd">
  74. <td><p>name</p></td>
  75. <td><p>The human-readable name of the plugin module.</p></td>
  76. </tr>
  77. <tr class="even">
  78. <td><p>system</p></td>
  79. <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>
  80. <p><strong>Default:</strong> false.</p></td>
  81. </tr>
  82. </tbody>
  83. </table>
  84. **\*key attribute is required.**
  85. #### Elements
  86. - **description** - The description of the plugin module. The 'key' attribute can be specified to declare a localisation key for the value instead of text in the element body.
  87. ## Example
  88. Here is an example `atlassian-plugin.xml` file containing a plugin module type:
  89. ``` xml
  90. <atlassian-plugin name="Hello World" key="example.plugin.helloworld" plugins-version="2">
  91. <plugin-info>
  92. <description>A dictionary module type test</description>
  93. <vendor name="Atlassian Software Systems" url="http://www.atlassian.com"/>
  94. <version>1.0</version>
  95. </plugin-info>
  96. <module-type key="dictionary" class="example.plugin.DictionaryModuleDescriptor" />
  97. </atlassian-plugin>
  98. ```
  99. Our dictionary module descriptor allows plugins to provide dictionaries that get definitions of technical terms and phrases in various languages. We have a `Dictionary` interface that looks like this:
  100. ``` java
  101. public interface Dictionary
  102. {
  103. String getDefinition(String text);
  104. }
  105. ```
  106. The Java code for `DictionaryModuleDescriptor` could look like this:
  107. ``` java
  108. public class DictionaryModuleDescriptor extends AbstractModuleDescriptor<Dictionary>
  109. {
  110. private String language;
  111. @Override
  112. public DictionaryModuleDescriptor(ModuleFactory moduleFactory)
  113. {
  114. super(moduleFactory);
  115. }
  116. @Override
  117. public void init(Plugin plugin, Element element) throws PluginParseException
  118. {
  119. super.init(plugin, element);
  120. language = element.attributeValue("lang");
  121. }
  122. public Dictionary getModule()
  123. {
  124. return moduleFactory.createModule(moduleClassName, this);
  125. }
  126. public String getLanguage()
  127. {
  128. return language;
  129. }
  130. }
  131. ```
  132. This will add the new module type 'dictionary' to the plugin framework, allowing other plugins to use the new module type. Here is a plugin that uses the new 'dictionary' module type:
  133. ``` xml
  134. <atlassian-plugin name="Hello World" key="example.plugin.helloworld" plugins-version="2">
  135. <plugin-info>
  136. <description>An english dictionary</description>
  137. <vendor name="Atlassian Software Systems" url="http://www.atlassian.com"/>
  138. <version>1.0</version>
  139. </plugin-info>
  140. <dictionary key="myEnglishDictionary" lang="english" class="example.plugin.english.MyDictionary" />
  141. </atlassian-plugin>
  142. ```
  143. Accessing modules of your dynamic module type can be done using `com.atlassian.plugin.PluginAccessor`.
  144. ``` java
  145. // To get all the enabled modules of this module descriptor
  146. List<DictionaryModuleDescriptor> dictionaryModuleDescriptors =
  147. pluginAccessor.getEnabledModuleDescriptorsByClass(DictionaryModuleDescriptor.class);
  148. // Now we'll use each one to get a map of languages to translations of the word "OSGi"
  149. Map<String, String> results = new HashMap<String, String>();
  150. for (DictionaryModuleDescriptor dictionaryModuleDescriptor : dictionaryModuleDescriptors)
  151. {
  152. results.put(dictionaryModuleDescriptor.getLanguage(),
  153. dictionaryModuleDescriptor.getModule().getDefinition("OSGi"));
  154. }
  155. ```
  156. Note that it is not advisable to cache the results of calls to `com.atlassian.plugin.PluginAccessor`'s methods, since the return values can change at any time as a result of plugins being installed, uninstalled, enabled, or disabled.
  157. ## Notes
  158. Some information to be aware of when developing or configuring a Module Type plugin module:
  159. - Not all dynamic module types will need to use the `class` attribute on the modules that implement them. For example, if the above dictionary example just used a resource file to translate terms, and not an interface that plugins had to implement, plugins using the dictionary module type might look like this:
  160. ``` xml
  161. <dictionary key="myEnglishDictionary" lang="english" resource="example/plugin/english/myDictionary.properties" />
  162. ```
  163. - The plugin that defines a new module type cannot use the module type in the Plugin Framework 2.1, but can in 2.2 or later.
  164. - If you want to have control over the construction of the ModuleDescriptor, you can skip the 'module-type' module and make public a component registered against the ModuleDescriptorFactory interface:
  165. ``` xml
  166. <component key="dictionaryFactory" class="example.plugin.DictionaryModuleDescriptorFactory" public="true">
  167. <interface>com.atlassian.plugin.ModuleDescriptorFactory</interface>
  168. </component>
  169. ```
  170. Ensure your `ModuleDescriptorFactory` implements `com.atlassian.plugin.osgi.external.ListableModuleDescriptorFactory`.
  171. - By specifying the `application` attribute in your module type element, you can ensure that a plugin only uses that module type when it is running in a specific application. For example, with the following snippet, the dictionary module type is only used when the plugin is loaded in JIRA:
  172. ``` java
  173. <dictionary key="myEnglishDictionary" lang="english" class="example.plugin.english.MyDictionary" application="jira" />
  174. ```
  175. The supported values for `application` are the **Product Keys** listed in the [Atlassian Plugin SDK documentation](https://developer.atlassian.com/display/DOCS/Working+with+the+SDK#WorkingwiththeSDK-AtlassianPluginSDK-SupportedAtlassianApplicationsandDefaultPorts).