Confluence is built around Spring, an open-source component framework for Java.
If you are familiar with Spring, then you just need to know that Confluence plugin modules (and their implementing classes) are autowired by name. Thus, if you want to access a Confluence component from your plugin, just include the appropriate setter method in your implementing class or use constructor injection with javax or Spring annotations (for v2 plugins).
If you want to write Confluence plugins but you are not familiar with Spring, the rest of this page will give you information on how to make your plugin interact with Confluence.
When you are writing anything but the simplest Confluence plugin, you will need to interact with the Confluence application itself to retrieve, change or store information. This document describes how to do it.
At the core of Confluence, there is a group of "Manager" objects. For example, the pageManager
is in charge of Confluence pages, the spaceManager
is in charge of spaces, and the attachmentManager
is in charge of attachments, and so on.
Traditionally, in a component-based system, components are retrieved from some kind of central repository. For example, in an EJB-based system, you would retrieve the bean from the application server JNDI repository.
Confluence works the other way round. When a plugin module is instantiated, Confluence determines which components the module needs, and delivers them to it.
Confluence determines which components a module needs by reflecting on the module's methods. There are two different mechanisms that are used, based on whether you are using a v1 or v2 plugin.
With setter-based injection, any method with a signature that matches a standard JavaBeans-style setter of the same name as a Confluence component will have that component passed to it when the module is initialised.
So, if your plugin module needs to access the pageManager
, put the following setter method on your module's implementing class:
1 2public void setPageManager(PageManager pageManager) { this.pageManager = pageManager; }
When constructing your module, Spring calls the constructor with the greatest number of arguments that can be satisfied by Confluence or plugin components.
If your plugin uses "transformerless" technique, with Atlassian Spring Scanner, you can do one of the following:
To make class a component with access to the pageManager
, use @Named/@Component
, @Inject/@Autowired
and @ConfluenceImport
annotations. For example:
1 2@Named public class MyModule { @ConfluenceImport private final PageManager pageManager; @Inject public MyModule(PageManager pageManager) { this.pageManager = pageManager; } // ... }
To make the scanner "notice" a class without actually making that code a component itself, use @Scanned
:
1 2@Scanned public class MyModule { @ConfluenceImport private final PageManager pageManager; public MyModule(PageManager pageManager) { this.pageManager = pageManager; } // ... }
You need to make sure there are no circular dependencies among your modules. If there are, you plugin will fail to start up and you will see an error message in the Confluence log file with information about the dependency problem.
There are dozens of managers for different areas of functionality in Confluence. The following table lists some of the more commonly used ones.
Manager class | Responsibility | Sample methods |
---|---|---|
Pages, blogs | getPage(), getBlogPost(), getRecentlyAddedPages(), findNextBlogPost(), saveContentEntity() | |
Spaces | getSpace(), getPersonalSpace(), createSpace() | |
Users, groups, preferences | getUserByKey(), getUserByName(), createUser(), addMembership(), hasMembership(), getConfluenceUserPreferences(), getUserProfilePicture() | |
Comments | addCommentToObject(), getComment(), updateCommentContent() | |
Labels | addLabel(), removeLabel(), getContentForLabel() | |
Attachment storage and retrieval | getAttachments(), getAttachmentData(), saveAttachment() | |
Searching (2.8 and earlier) | getListQueryResults() | |
Searching (2.9 and later) | search(), convertToEntities(), searchEntities() | |
Saving and retrieving all content. Parent interface of PageManager, CommentManager, etc. | saveContentEntity(), getVersionHistorySummaries() | |
Global, space, plugin configuration | getGlobalSettings(), updateSpaceSettings(), getPluginSettings() | |
Getting localised text | getText(String), getText(String, Object[]), getText(String, List) | |
Checking permissions (do this before calling a manager) | hasPermission(), hasCreatePermission(), isConfluenceAdministrator(), getPermittedEntities() | |
Adding or modifying space permissions | savePermission(), getGlobalPermissions() | |
Register listeners or publish events (legacy) | publishEvent(), registerListener() | |
Register listeners or publish events | publish(), register(), unregister() | |
Rendering web-sections and web-items in Velocity | getDisplayableSections(), getDisplayableItems() |
Note that these are all interfaces. If you include the appropriate setter method in your class as described above, the actual implementation is injected in your class by Spring.
Do not directly use implementations or cast the injected class to a particular implementation. Implementation classes are subject to change across versions without warning. Where possible, interface methods will be marked as deprecated for two major versions before being removed.
Managers in Confluence are responsible for the data integrity of their domain, but they are not generally responsible for validation or security. Invalid calls typically result in a runtime exception. Historically, this wasn't a major problem, but, as time went by, there were more duplication of this functionality across actions, remote API methods and plugins. To address this, a service layer was introduced in Confluence.
The services will follow a command pattern, where the service is responsible for creating a command that can then be validated and executed. The following nascent services are available:
Service class | Responsibility | Sample commands |
---|---|---|
Comments | CreateCommentCommand, DeleteCommentCommand, EditCommentCommand | |
Pages, blog posts | MovePageCommand |
These simpler services don't follow the command pattern, and they don't perform any data modification. They are generally used to simplify other functionality.
Service class | Responsibility |
---|---|
Http Connectivity to External Services |
Rate this page: