Status: | This feature is DEPRECATED in favor of performing Dependency Injection via Spring Java configuration or Atlassian Spring Scanner. |
JIRA uses Picocontainer as its central object factory and dependency injection
framework. As such, Picocontainer is responsible for instantiating objects and resolving their constructor dependencies.
This greatly simplifies code, in that any Picocontainer-instantiated object (for example a Webwork action) can obtain an
instance of another (e.g. a Manager class) simply by requesting one in its constructor. PicoContainer will ensure that
each object required by the constructor is passed in (a.k.a. dependency injection). For example, the ViewIssue
action:
ViewIssue.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
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-managed classes need to be registered with Picocontainer. This happens automatically for Webwork actions, but other classes need to be registered manually. Jira does this in ContainerRegistrar's registerComponents() method:
ContainerRegistrar.java
1 2public 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); ... }
Components can either be INTERNAL, meaning that they will be available only to JIRA itself, or PROVIDED, in which case they will also be available to plugins2 plugins.
Components are generally only registered in the ContainerRegistrar
if they are required in JIRA internally.
Plugin writers who wish to write their own components that can be injected into their plugin's classes
should use the component plugin module.
Before Jira 9.0, if you wanted to register an alternative implementation of a pico-registered type, for example
CustomFieldManager
in the example above, you could do so by declaring a <component>
module within a Plugins 1 plugin,
with the child element <interface>com.atlassian.jira.issue.CustomFieldManager</interface>
. From Jira 9.0 onwards, you
can no longer override core Jira components in this way. Jira will simply log a warning about each attempted override,
but will still allow the plugin to load.
Deprecated: | Please note that this technique was removed in JIRA 8.0. |
Sometimes it may be necessary for a plugin developer to override a component that JIRA ships with to provide some
custom behaviour. You can do this by providing an extension pico container via a jira-application.properties
property.
In jira-application.properties
, register an extension container provider:
1 2jira.extension.container.provider = com.mycompany.jira.MyContainerProvider
In this class, you can register your own implementations of interfaces, which will be used in preference to the
defaults in ComponentManager
:
MyContainerProvider.java
1 2package com.mycompany.jira; import org.picocontainer.PicoContainer; import org.picocontainer.defaults.DefaultPicoContainer; import com.atlassian.jira.config.component.ProfilingComponentAdapterFactory; import com.atlassian.jira.web.action.issue.BugAssociatorPrefs; import com.atlassian.jira.security.PermissionManager; import com.atlassian.jira.permission.PermissionSchemeManager; import com.mycompany.jira.MyBugAssociatorPrefs; import com.mycompany.jira.MyPermissionManager; import com.mycompany.jira.MyPermissionSchemeManager; public class MyContainerProvider implements ContainerProvider { private DefaultPicoContainer container; public PicoContainer getContainer(PicoContainer parent) { if (container == null) buildContainer(parent); return container; } private void buildContainer(PicoContainer parent) { this.container = new DefaultPicoContainer(new ProfilingComponentAdapterFactory(), parent); container.registerComponentImplementation(BugAssociatorPrefs.class, MyBugAssociatorPrefs.class); container.registerComponentImplementation(PermissionManager.class, MyPermissionManager.class); container.registerComponentImplementation(PermissionSchemeManager.class, MyPermissionSchemeManager.class); } }
Here we have registered our own implementations of three classes, after delegating to the default (so ours will
take precedence). You can now keep MyContainerProvider
and your modified com.mycompany.jira.\*
classes in their
own jar, which can be dropped into any JIRA instance to customise it to your needs.
Rate this page: