Надстройки Plugins2

Надстройка JIRA (также известная как плагин) делает именно то, что вы думаете, что она может сделать: она добавляет функциональность JIRA. Он может добавить одну особенность, например отчет, или он может обеспечить достаточное количество функций, чтобы создать продукт в своем собственном праве. Надстройка устанавливается отдельно для JIRA через Universal Plugin Manager. Если вы хотите сделать его доступным для других, вы можете перечислить его на Atlassian Marketplace.

Привет мир

Если вы уже знаете теорию и хотите перейти прямо в разработку, прочитайте наше руководство по началу работы для создания вашей первой надстройки JIRA Plugins2.

О надстройках плагинов2

Надстройка Plugins2 представляет собой один JAR содержащий код, дескриптор надстройки (XML) и обычно некоторые файлы шаблонов Velocity для визуализации HTML.

Дескриптор надстройки

Дескриптор надстройки является единственной обязательной частью надстройки. Его следует называть atlassian-plugin.xml и располагаться в корневом каталоге вашего JAR-файла. Вот пример дескриптора с выделенными элементами:


<!-- the key must be unique, think of it as the 'package' of the add-on -->
<atlassian-plugin key="com.atlassian.addon.sample" name="Sample Add-on" plugins-version="2">
    <!-- a short block describing the plugin itself -->
    <plugin-info>
        <description>This is a brief textual description of the add-on</description>
        <!-- the version of the add-on -->
        <version>1.1</version>
        <!-- details of the add-on vendor -->
        <vendor name="Atlassian Software Systems Pty Ltd" url="http://www.atlassian.com"/>
    </plugin-info>

    . . . 1 or more add-on modules . . .
</atlassian-plugin>

Ключи надстроек

Каждая надстройка имеет *ключ надстройки*, который является уникальным среди всех надстроек (например, «com.atlassian.addon.sample»). Обычно используется имя корневого пакета основного класса Java.

Каждый модуль (см. Модули JIRA ниже) в надстройке также имеет ключ модуля, который является уникальным в надстройке (например, «myreport»). Семантически это эквивалентно имени класса Java.

Клавиша  ключа надстройки + ключ модуля объединяется, чтобы сделать * полный ключ * модуля надстройки (например, «com.atlassian.addon.sample: myreport»). Обратите внимание, что двоеточие используется для разделения ключа надстройки от ключа модуля.

Модули JIRA

Надстройка JIRA состоит из одного или нескольких модулей (см. Ниже «Модули JIRA»). Они имеют разные типы (например, отчет), и каждый из них имеет отдельный XML-элемент, описывающий его. Модули надстроек, поддерживаемые сервером JIRA, описаны в разделе «Справка».

См. Веб-фрагменты.

Жизненный цикл надстроек JIRA

Как только вы начнете создавать свои собственные надстройки, вполне вероятно, что вам нужно будет вызвать код JIRA для выполнения определенных задач; например, получить список пользователей, внести изменения в рабочий процесс или добавить новые данные в задачи. В этом разделе описывается жизненный цикл надстройки JIRA и этапы, над которыми надстройка может подключаться для выполнения задач инициализации, закрытия задач и т. д.

Этапы в жизненном цикле надстроек

Существует несколько этапов жизненного цикла надстройки и жизненного цикла компонентов вашей надстройки (например,компонента модулей плагина компонентов), которые вы можете подключить к своей надстройке. На этих этапах вы можете выполнять различные задачи, такие как подключение зависимостей, инициализация кэшей или программная настройка JIRA. Однако важно отметить, что не всегда целесообразно выполнять некоторые задачи на определенных этапах, поскольку состояние JIRA и системы надстроек может быть не готово к определенным задачам.

Этапы описаны ниже в разделах «Инициализация компонентов» и «Уничтожение компонентов», в том числе заметки о том, что вы можете, не можете или не должны делать на каждом этапе.

Инициализация компонентов

Более продвинутые надстройки будут содержать один или несколько компонентов, как правило, для реализации служб, менеджеров, запасов или других вещей. Когда дополнительный модуль загружается в систему надстройки, его компоненты должны быть сначала инициализированы до того, как надстройка может быть успешно зарегистрирована. Это происходит, когда:

  • Система надстроек запускается:
    • JIRA запущена
    • Экспорт данных импортируется в JIRA
  • Устанавливается надстройка
  • Надстройка или конкретный надстройки модуль включены

Существует три возможных этапа инициализации компонентов. Первая - это конструкция. Обычно это когда зависимости для вашего компонента вводятся, если вы используете инъекцию на основе конструктора. Здесь также происходит любая базовая инициализация полей вашего компонента. Например, определение кешей.

Вторая и третья фазы очень схожи: выполнение методов, аннотированных с помощью @PostConstruct, с последующим выполнением метода afterPropertiesSet из интерфейса InitializingBean в этом порядке. Естественно, что третий этап выполняется только в том случае, если ваш компонент реализует интерфейс InitializingBean. Эти две фазы в основном эквивалентны, и конкретная фаза, которую вы хотите использовать, зависит от конфигурации Spring. На этих этапах все зависимости ваших компонентов уже были введены (независимо от того, используете ли вы на основе конструктора или на основе набора). Например, если ваш компонент является прослушивателем событий, вы можете зарегистрировать его с помощью EventPublisher (который вы заявили бы как зависимость) в методе @PostConstruct.*

Примечание: * @PostConstruct и InitializingBean - это концепции, предоставляемые фреймвоком Spring. Для получения дополнительной информации о них см. их документацию на @PostConstruct и InitializingBean.

Несмотря на то, что зависимости вашего компонента были введены, это не обязательно означает, что эти зависимости находятся в «готовом к использованию» состоянии. Например, ваш компонент может зависеть от компонента JIRA, который кэширует информацию о надстройках. Во время инициализации вашего компонента могут быть другие надстройки, которые еще не были инициализированы и, таким образом, включены в системе надстроек.

Поэтому доступ к этим методам JIRA-компонента приведет к тому, что он будет действовать без знания других, хотя и неинициализированных надстроек. Чтобы избежать этого сценария, лучше всего отложить доступ к зависимостям, которым требуется знание надстройки, до тех пор, пока все надстройки не будут инициализированы и не активированы. См. раздел о дополнительных системных событиях ниже.

Если по какой-либо причине инициализация завершилась неудачей, надстройка будет эффективно отключена. Инициализация может завершиться неудачей, если компонент занимает слишком много времени для завершения (тайм-аут по умолчанию составляет 30 секунд). Поэтому не рекомендуется пытаться выполнять любые потенциально длительные задачи при инициализации компонентов, например, подключаться к внешнему ресурсу или загружать / обрабатывать большие объемы данных. Если такие задачи требуются, но могут быть асинхронными, вместо этого вы можете создать запланированную задачу для выполнения их в более удобное время.

Попытка получить доступ к зависимостям компонента на этапе инициализации также может привести к взаимоблокировкам. Например, если существует циклическая зависимость между одним компонентом и другим, и один обращается к другому во время инициализации, то контейнер Spring будет входить в тупик, пытаясь дождаться инициализации обоих компонентов. По истечении времени ожидания (как указано выше), контейнер поймет, что оба компонента не могут быть инициализированы, а загрузка плагина не удастся.

Уничтожение компонентов

Наряду с инициализацией компонентов, разрушение компонентов является ключевой частью жизненного цикла компонентов надстройки. Уничтожение компонентов требуется для того, чтобы убедиться, что надстройка может очистить после себя. Например, освобождение ресурсов, отмена регистрации слушателей. Уничтожение компонентов происходит, когда:

  • Надстройка закрывается:
    • Экспорт данных импортируется в JIRA
    • JIRA закрывается
  • Надстройка деинсталируется
  • Более новая версия надстройки устанавливается поверх существующей
  • Надстройка или конкретный дополнительный модуль отключены

Существует две возможные фазы уничтожения компонентов: выполнение методов, аннотированных с помощью @PreDestroy, с последующим выполнением метода destroy из интерфейса DisposableBean в этом порядке. Естественно, вторая фаза выполняется только в том случае, если ваш компонент реализует интерфейс DisposableBean. Эти две фазы в основном эквивалентны, и конкретная фаза, которую вы хотите использовать, зависит от конфигурации Spring.

* Примечание: * @PreDestroy и DisposableBean - это концепции, предоставляемые фреймвоком Spring. Для получения дополнительной информации о них см. их документацию по адресу @PreDestroy и DisposableBean.

Важно, чтобы компоненты правильно разрушали себя, чтобы после этого JIRA находилась в чистом состоянии. Это особенно важно, когда компонент потенциально упоминается другим плагином или самой JIRA. Например, если компонент регистрируется как прослушиватель событий с EventPublisher, тогда крайне важно, чтобы он отменил себя во время разрушения. Если это не сделано, EventPublisher будет удерживать объект за время, когда классы плагина могут быть выгружены из загрузчика классов. Это может привести к утечкам памяти и другим нежелательным последствиям.

Подобно инициализации компонентов, также существует тайм-аут для уничтожения компонентов (по умолчанию 10 секунд). Если уничтожение не завершится за это время, система плагинов будет регистрировать ошибку и продолжать.

В случае остановки всей системы надстройки порядок, в котором уничтожаются надстройки, не гарантируется. Таким образом, если компонент вашей надстройки зависит от компонентов от других надстроек, и вам необходимо получить доступ к этим компонентам во время уничтожения, это может привести к ошибкам.

События

И система событий, и JIRA сама создают события на разных этапах жизненного цикла надстройки. Они называются  системными событиями надстроек и событиями JIRA соответственно.

Системные события надстроек

Системные события надстроек запускаются системой событий, используемой JIRA и Atlassian Plugins Framework, atlassian-events. Эти события запускаются на разных этапах жизненного цикла надстройки. Внутри JIRA прослушивает эти события, чтобы обеспечить надлежащую работу различных компонентов системы, например CustomFieldManager. Надстройки также могут прослушивать эти события для выполнения задач, когда что-то происходит с надстройкой или дополнительным модулем (к кому принадлежит этот плагин). Ниже описаны дополнительные системные события.

PluginEnabledEvent и PluginModuleEnabledEvent

Когда надстройка была успешно установлена в систему надстроек, то есть после того, как она была успешно инициализирована, система надстройки уведомляет всех слушателей о том, что модули каждого дополнительного модуля были включены, включив модуль PluginModuleEnabledEvent. После того, как все уведомления были сделаны для модулей надстройки, затем запускается PluginEnabledEvent. В частности, эти события запускаются, когда:

  • Система надстройки запускается:
    • JIRA запущена
    • Экспорт данных импортируется в JIRA
  • Устанавливается надстройка
  • Надстройка или конкретный надстройки модуль включены

После того, как эти события были запущены, с точки зрения JIRA (и систем надстройки) ваше дополнение включено. То есть, когда JIRA запрашивает модуль PluginAccessor для модулей, которые присутствуют и включены, ваши модули надстройки будут возвращены. На этом этапе вы можете быть уверены, что любые * внутренние * зависимости, которые могут использовать компоненты надстройки (то есть зависимости, предоставленные * вашей * надстройкой * к вашей надстройке), будут находиться в состоянии " готовое к использованию ".

Из-за недостатков этапа инициализации компонента слушатель в PluginEnabledEvent является самым ранним моментом, когда вы пытаетесь сделать какую-либо серьезную проводку в JIRA. Например, если вашему надстройку необходимо убедиться, что в JIRA созданы определенные пользовательские поля для правильной работы надстройки, надстройка должна попытаться создать их на этом этапе, а не раньше.

Если, однако, у ваша надстройка имеет задачи, которые могут выполняться асинхронно или даже лениво, то это должен быть ваш предпочтительный подход. Недостатком этих критических задач на фазе PluginEnabledEvent является то, что в некоторых сценариях ваше дополнение будет уведомлено о том, что оно включено, сигнализируя о начале этих задач, но в то же время JIRA разрешит запросы на ваше дополнение. Таким образом, если задачи занимают слишком много времени, и они неправильно блокируют JIRA от обработки запроса, то вы можете попасть в неизвестное состояние.

Скажем, например, что вашей надстройке необходимо загрузить много данных в память, и этот процесс может занять некоторое время. Если эта задача выполняется при запуске PluginEnabledEvent, возможно, что во время выполнения этой задачи пользователи обращаются к JIRA и запрашивают информацию из вашей надстройки. Это, к сожалению, известное ограничение надстройки JIRA. Как было сказано ранее, если вы можете отложить выполнение этой задачи асинхронно или лениво, когда первый запрос приходит, в котором это требуется, тогда это позволит избежать проблем. Альтернативный подход заключается в том, чтобы сделать надстройку недоступной для запросов до завершения задачи, но для этого требуется много защитного программирования.

Наконец, порядок этих событий, запущенных по отношению к другим этапам жизненного цикла, может изменяться в зависимости от сценария, в котором вы работаете. Обратитесь к разделу о различных сценариях (примеры сценариев), чтобы лучше понять это.

 

PluginDisabledEvent и PluginModuleDisabledEvent

Когда надстройка удаляется из системы надстроек, события PluginModuleDisabledEvent и PluginDisabledEvent могут запускаться, чтобы сигнализировать о том, что это происходит. Это произойдет, когда:

  • Система надстроек закрывается:
    • Экспорт данных импортируется в JIRA
    • JIRA закрывается
  • Надстройка удаляется
  • Более новая версия надстройки устанавливается поверх существующей
  • Надстройка или конкретный дополнительный модуль отключены

* Примечание: * При отключении или удалении надстройки, PluginDisabledEvent, соответствующий этому плагину, не предназначен для захвата самой надстройкой. Он предоставляется в основном для самой JIRA и других надстроек, которые могут зависеть от надстройки. Как правило, последовательность событий:

  1. Для каждого модуля надстройки - Запущен PluginModuleDisabledEvent
  2. Для компонента надстройки - @PreDestroy, DisposableBean # destroy ()
  3. Запущен PluginDisabledEvent

Как вы можете видеть, надстройка, которую вы отключите, больше не будет использоваться к моменту запуска PluginDisabledEvent. Однако она может использоваться когда  одна надстройка информирует, когда другая надстройка отключается. Это может потребоваться, если функциональность одной надстройки зависит от другой.

Поскольку этап уничтожения компонентов не подходит для всех задач, связанных с отключением состояния надстройки, лучшим временем для выполнения этих задач было бы при подключении к PluginModuleDisabledEvent. Это гарантирует, что все компоненты вашей надстройки будут по-прежнему доступны (не будут уничтожены). Событие также запускается синхронно - разрушение компонента не будет продолжаться до тех пор, пока слушатели события не закончат выполнение.

LifecycleAware#onStart()

Интерфейс LifecycleAware предлагается библиотекой уровня общего доступа (SAL), чтобы помочь разработчикам надстройки, которые хотят публиковать публичные компоненты в системе надстроек и JIRA. Он может быть реализован добавочными компонентами, помеченными как «public» в файле atlassian-plugin.xml, чтобы подключиться к жизненному циклу надстройки. Подобно модели прослушивателя событий, любые компоненты, реализующие метод onStart () интерфейса, будут иметь этот метод, вызываемый на определенном этапе жизненного цикла, в зависимости от сценария.

Метод onStart () гарантированно вызывается на компоненте * после *, что этот компонент прошел через инициализацию. Тем не менее, время, в которое он вызывается по отношению к другим этапам, зависит от сценария:

  • Когда JIRA запускается или когда экспорт данных импортируется в JIRA (то есть вся система надстройки запускается), onStart () будет вызываться последним. То есть, он будет вызываться после:
  1. PluginModuleEnabledEvent запущен
  2. PluginEnabledEvent запущен
  3. Данные JIRA обновляются JIRA
  4. JiraStartedEvent запущен
  5. Выполняются задачи обновления надстройки, распознанные SAL.
  • Когда добавление включено или когда плагин устанавливается, onStart () будет вызываться непосредственно после инициализации. То есть, он будет вызываться раньше:
  1. PluginModuleEnabledEvent запущен
  2. Выполняются задачи обновления надстроек, распознанные SAL (в сценарии «установка»)
  3. PluginEnabledEvent запущен

Ненадежность сроков этой фазы делает его плохим кандидатом для использования вне самых основных задач. Он * может * использоваться для планирования задач с помощью SAL PluginScheduler, но все же может быть лучше всего выполнить эти задачи в том же месте, где вы выполняете другие задачи инициализации надстройки. Эта проблема отслеживается в проекте JIRA JAC: JRA-26358.

Задачи обновления надстроек

Надстройки могут определять задачи обновления, которые могут быть выполнены, чтобы обновлять данные JIRA с помощью новой версии надстройки. Это достигается просто путем определения компонентов в atlassian-plugin.xml, которые являются общедоступными и реализуют интерфейс com.atlassian.sal.api.upgrade.PluginUpgradeTask из SAL.

Если ваша надстройка сложна и хранит много данных - возможно, с помощью плагина / библиотеки ActiveObjects (AO), тогда обновление задач, вероятно, станет необходимостью при выпуске более новых версий ваших надстроек. Поэтому полезно знать, когда  выполняются задачи обновления надстроек на жизненном цикле. Задачи обновления надстроек могут выполняться, когда:

  • Система надстроек запускается:
    • JIRA запущена
    • Экспорт данных импортируется в JIRA
  • Устанавливается надстройка
  • Надстройка включена

Компонент задачи обновления будет выполняться только в том случае, если он не был * успешно выполнен ранее (то есть завершает, не выбрасывая исключение Exception). SAL отслеживает успешные задачи обновления, используя значение getBuildNumber () в интерфейсе PluginUpgradeTask.

* Примечание: * В зависимости от сценария время выполнения задач обновления будет меняться относительно других этапов жизненного цикла. В частности, когда надстройка устанавливается в исполняемый экземпляр JIRA (например, через UPM), задачи обновления надстройки будут выполняться после того, как PluginModuleEnabledEvent будет запущен для всех модулей, но во время PluginEnabledEvent для надстройки (SAL's PluginUpgradeManager начинает выполнение задач обновления при получении PluginEnabledEvent). Это означает, что если запрос поступает в JIRA, для которого требуется модуль из надстройки, который в настоящее время установлен, этот запрос может быть обслуживаться во время выполнения задач обновления. Это отличается от сценария при запуске JIRA или при обновлении данных - в обоих случаях JIRA будет блокировать запросы до завершения дополнительных задач обновления.

Из-за этого недостатка в JIRA и системы надстройки мы рекомендуем использовать защитные блокировки для плагинов с потенциально долговременными задачами обновления, чтобы гарантировать, что надстройка не может быть доступна во время выполнения задач обновления. Это становится менее проблематичным, если ваше дополнение только когда-либо установлено в JIRA, когда ни один пользователь не имеет доступ к нему, или сначала отключив JIRA.

События JIRA

Сама JIRA запускает несколько событий в течение своего жизненного цикла. Большинство из них предназначены для внутренних целей и не имеют отношения к разработчикам надстроек. Однако их можно послушать, используя регулярный механизм, предоставляемый событиями Atlassian.

Одно замечание - событие JiraStartedEvent. Оно срабатывает, когда:

  • Система надстроек запускается:
    • JIRA запущена
    • Экспорт данных импортируется в JIRA

В обоих описанных выше сценария событие запускается как часть фазы запуска LifecycleManager SAL, где каждый объект LifecycleAware уведомляется о запуске приложения. Это означает, что теоретически JiraStartedEvent происходит одновременно с:

  • выполняются любые дополнительные задачи обновления и
  • LifecycleAware # onStart () выполняется на любых известных компонентах.

Поскольку событие не запускается, когда надстройка установлена или включена, эта фаза жизненного цикла по существу является менее способной версией фазы LifecycleAware # onStart () с той разницей, что она основана на событиях. По тем же причинам, что и на этапе LifecycleAware # onStart (), вероятно, наиболее безопасно избегать использования этой фазы, если только не существует конкретной причины, по которой вам нужно выполнять только при запуске JIRA или восстановлении данных.

Примеры сценариев

В этом разделе описываются несколько сценариев, которые связаны с  жизненным циклом надстройки. В каждом сценарии мы перечисляем последовательность этапов и событий, чтобы дать вам представление о том, когда каждый этап вступает в игру.

  • JIRA запускает:

  1. Для всех компонентов всех надстроек - Constructor, @PostConstruct, #afterPropertiesSet
  2. Для каждой надстройки:
  • Для каждого модуля надстройки запускается PluginModuleEnabledEvent
  • PluginEnabledEvent запущен
  1. JIRA обновляет данные
  2. Повторные индексы JIRA (возможно)
  3. Следующее происходит «одновременно» (в серийном, но не в определенном порядке):
  • JiraStartedEvent запущен
  • SAL PluginUpgradeTasks, выполняются при необходимости
  • Выполняется LifecycleAware # onStart ()
  1. Запущен планировщик JIRA
  2. JIRA отвечает на веб-запросы
  • Экспорт данных восстанавливается:

  1. Система надстройки отключена:
  2. Для каждой надстройки:
    • Для каждого о компонента надстройки- @PreDestroy, DisposableBean # destroy ()
    • Для каждого модуля надстройки- PluginModuleDisabledEvent запущен
  1. Для каждой надстройки - PluginDisabledEvent запущен
  1. Данные импортируются в базу данных
  2. . Система надстройки перезагружена:
    1. Для всех компонентов всех надстроек - Constructor, @PostConstruct, #afterPropertiesSet
    2. Для каждой надстройки :
  • Для каждого модуля надстройки PluginModuleEnabledEvent запущен
  • PluginEnabledEvent запущен
  1. JIRA обновляет данные (при необходимости)
  2. Повторные индексы JIRA (возможно)
  3. Следующее происходит «одновременно» (в серийном, но не в определенном порядке):
  4. JiraStartedEvent запущен
  5. SAL PluginUpgradeTasks, выполняются при необходимости
  6. Выполняется LifecycleAware # onStart ()
  7. Пользовательский интерфейс может быть доступен снова
  • Надстройка отключена с помощью UPM:

    1. Для каждого модуля надстройки - PluginModuleDisabledEvent
    2. Для компонента дополнения - @PreDestroy, DisposableBean # destroy ()
    3. Включен PluginDisabledEvent
  • Надстройка включена через UPM:

  1. Для каждого из компонентов надстройки - Constructor, @PostConstruct, #afterPropertiesSet, LifecycleAware # onStart
  2. Для каждого модуля надстройки - PluginModuleEnabledEvent запущен
  3. Следующее происходит «одновременно» (в серийном, но не в определенном порядке):
  • Выполняются задачи обновления (только если они не выполнялись ранее)
  • Включен PluginEnabledEvent
  • Надстройка удаляется через UPM:

  1. Для каждого модуля надстройки - PluginModuleDisabledEvent запущен
  2. Для компонента надстройки - @PreDestroy, DisposableBean # destroy ()
  3. Включен PluginDisabledEvent
  4. Классы надстроек удалены из класса Loader
  • Надстройка устанавливается через UPM:

  1. Для каждого из компонентов надстройки - Constructor, @PostConstruct, #afterPropertiesSet, LifecycleAware # onStart
  2. Для каждого модуля надстройки - PluginModuleEnabledEvent запущен
  3. Доступ к модулям надстройки  с интерфейсом UI можно получить сейчас
  4. Следующее происходит «одновременно» (в серийном, но не в определенном порядке):
    • Выполняются задачи обновления (только если они не выполнялись ранее)
    • Включен PluginEnabledEvent
  5. Пользовательский интерфейс доступен пользователю, который инициировал установку
  • JIRA закрывается:

  1. Система надстройки закрыта
  2. Для каждой надстройки :
    • Для каждого компонента надстройки  - @PreDestroy, DisposableBean # destroy ()
    • Для каждого модуля надстройки- PluginModuleDisabledEvent

Похожие темы

Вы также можете прочитать этот связанный учебник: Написание прослушивателей событий JIRA с помощью библиотеки atlassian-event

PicoContainer и инъекции зависимостей

Важно понять, как работает инъекция зависимостей, прежде чем пытаться вызывать функциональность JIRA из вашей надстройки. JIRA использует PicoContainer для управления созданием объектов во всей системе. PicoContainer отвечает за создание экземпляров объектов и разрешение их зависимостей конструктора. Это значительно упрощает код, поскольку любой объект, созданный с помощью PicoContainer (например, действие Webwork), может получить экземпляр другого (например, класса Manager), просто запросив его в своем конструкторе. PicoContainer гарантирует, что каждый объект, который требуется в конструкторе, передается в (aka injection injection). Например, действие ViewIssue:

ViewIssue.java


public class ViewIssue extends AbstractViewIssue
{
    ....
    public ViewIssue(RepositoryManager repositoryManager, PermissionManager permissionManager, TrackbackManager trackbackManager,
                     ThumbnailManager thumbnailManager, SubTaskManager subTaskManager, IssueLinkManager issueLinkManager,
                     IssueLinkTypeManager issueLinkTypeManager, VoteManager voteManager, WatcherManager watcherManager,
                     PluginManager pluginManager)
   {
        super(issueLinkManager, subTaskManager);
        this.trackbackManager = trackbackManager;
        this.thumbnailManager = thumbnailManager;
        this.issueLinkTypeManager = issueLinkTypeManager;
        this.pluginManager = pluginManager;
        this.pagerManager = new PagerManager(ActionContext.getSession()); 
        this.repositoryManager = repositoryManager;
        this.permissionManager = permissionManager;
        this.voteManager = voteManager;
        this.watcherManager = watcherManager;
    }
    ....
}

Неконтролируемые классы

Классы, не управляемые PicoContainer (например, условия / функции рабочего процесса, службы и слушатели или скриптовые сценарии JSP), все же могут статически ставить объекты, вызванные pico, статическими методами в ComponentManager. Например:


final ProjectManager projectManager = ComponentManager.getInstance().getProjectManager();
final IssueFactory = ComponentManager.getInstance().getIssueFactory();
//or
final ApplicationProperties applicationProperties = ComponentManager.getComponentInstanceOfType(ApplicationProperties.class);

Регистрация новых классов, управляемых PicoContainer

PicoContainer-управляемые классы должны быть зарегистрированы в PicoContainer. Это происходит автоматически для действий Webwork, но другие классы необходимо зарегистрировать вручную. Это делается в методе registerComponents () компонента ComponentRegistrar:

ComponentManager.java


public void registerComponents(final ComponentContainer register, final boolean startupOK)
{
    ...
        register.implementation(INTERNAL, EntityUtils.class);
        register.implementation(PROVIDED, AttachmentManager.class, DefaultAttachmentManager.class);
        register.implementation(PROVIDED, AttachmentService.class, DefaultAttachmentService.class);
        register.implementation(PROVIDED, ProjectService.class, DefaultProjectService.class);
        register.implementation(PROVIDED, FieldManager.class, DefaultFieldManager.class);
        register.implementation(PROVIDED, CustomFieldManager.class, DefaultCustomFieldManager.class);
        register.implementation(PROVIDED, CustomFieldService.class, DefaultCustomFieldService.class);
        register.implementation(PROVIDED, FieldScreenManager.class, DefaultFieldScreenManager.class);
        register.implementation(INTERNAL, DefaultFieldScreenStore.class);
        register.implementation(PROVIDED, MailThreadManager.class, MailThreadManagerImpl.class);
        register.implementation(PROVIDED, CvsRepositoryUtil.class, CvsRepositoryUtilImpl.class);
        register.implementation(INTERNAL, DefaultWebAttachmentManager.class);
        register.implementation(INTERNAL, I18nBean.class);// this is a candidate for removal (may not be used - SF 08/Oct/04)
        register.implementation(PROVIDED, I18nHelper.class, I18nBean.class);
        register.implementation(PROVIDED, I18nHelper.BeanFactory.class, I18nBean.CachingFactory.class);
        register.implementation(INTERNAL, JiraLocaleUtils.class);
        register.implementation(PROVIDED, LocaleManager.class, DefaultLocaleManager.class);
        register.implementation(INTERNAL, PingUrlFilterer.class);
    ...
}

Компоненты могут либо в INTERNAL, либо в том, что они будут доступны только для самой JIRA или PROVIDED, и в этом случае они также будут доступны для надстроек plugins2.

Компоненты обычно регистрируются только в ComponentRegistrar, если они требуются в JIRA внутренне. Разработчики надстроек, которые хотят писать свои собственные компоненты, которые могут быть введены в свои классы надстроек, должны использовать модуль плагина компонента.

Хранилище данных

Active Objects - это уровень ORM в наших продуктах, который обеспечивает легкий, быстрый и масштабируемый доступ к данным и их хранение. См. Документацию по Active Objects.

Примеры дополнений Plugins2

Некоторые части JIRA реализованы как надстройки. Они называются системными надстройками. Если вы хотите узнать больше о том, как создать надстройку, системные надстройки могут быть удобной ссылкой, поскольку они демонстрируют функциональность, которая может быть построена в JIRA.

Системные надстройки ссылаются на следующие файлы (расположенные в / WEB-INF / classes):

  • system-workflow-plugin.xml - встроенные условия рабочего процесса, валидаторы и функции.
  • system-customfieldtypes-plugin.xml - встроенные в пользовательские типы полей.
  • system-project-plugin.xml - встроенные вкладки панели проекта (например, дорожная карта, журнал изменений и популярные задачи).
  • system-reports-plugin.xml - встроенные системные отчеты (т. е. отслеживание времени и отчеты о рабочей нагрузке разработчиков).
  • system-portlets-plugin.xml - все встроенные системные портлеты.

а в другой системе - * - файлы plugin.xml в этом каталоге. Модули надстроек определены в JIRA в JiraModuleDescriptorFactory.java.

По материалам Atlassian JIRA  Server Developer Plugins2 add-ons