These are guidelines related to the development of Confluence. The guidelines mainly apply to Atlassian employees, but reading them should provide insight for third-party plugin developers as well, so we decided to make them public.
This document represents the ideal arrangement of components in Confluence. This architecture should be the target of our refactoring, and should inform any new features we add to the system.
For the first three years of its development, little attention was paid to the high-level structure of the Confluence application. As such, it grew organically and developed interesting quirks on the way. This document tries to make sense of Confluence from a high level, to make the application easier to work with, easier to explain and easier to extend.
The goals are:
Imagine an operating system.
The Confluence Bootstrap Process is responsible for bringing up enough of Confluence that the rest of the system can be loaded. In Confluence's case, this involves:
confluence.cfg.xml
fileBased on this information, the bootstrap process can determine what to do next, and provide enough configuration for the core services that they know how to start up.
Bootstrap is implemented as a Spring context, in bootstrapContext.xml
. It is loaded as a parent context to any subsequent Spring context. It is available as a static singleton from BootstrapUtils
.
Confluence's in-browser setup requires a number of components that aren't used anywhere else. For example it needs a dummy plugin manager so that i18n works before we have a real plugin manager available. Ideally, setup should be a separate Spring context that is loaded when setup is required, and disposed of when setup is complete.
Currently this is not the case - setup components are loaded as part of the bootstrap context and remain indefinitely. To fix this will need some work on the atlassian-setup
component, which annoyingly conflates setup and bootstrap.
Once the system has been bootstrapped, and setup has (at least) reached the point where we know how to connect to the database, the main spring context is loaded as a child of the bootstrap context. The main Spring context, available as a static singleton from ContainerManager
, contains the remainder of Confluence's Spring configuration, loaded from a lot of different XML files in WEB-INF/classes
.
The list of XML files to load for the main Spring context is defined in the contextConfigLocation
parameter in web.xml
.
Loading these files in some specific order (as parent/child contexts) might make sense as a way of enforcing component boundaries, but I'm not convinced the benefit is worth the effort.
See also: Spring Usage Guidelines
These are generic services that you might consider useful to any application, like database access, caching, plugins, events, indexing/searching, and so on. A good way to think of the service layer is to imagine a theoretical library called "atlassian-base", consisting only of Confluence's bootstrap and service layers, which could be used as the basis for any new Atlassian web application.
Services can have dependencies on the bootstrap manager, and on each other, but there should never be a circular dependency between services, and there should never be a tightly coupled dependency between a service and application code.
Interdependencies between services should be minimised. When introducing a dependency between services, ask if this dependency is necessary or incidental.
Services are defined in XML config files in WEB-INF/classes/services
.
In the future, once the service system has been bedded down, we might introduce some kind of naming convention for private beans to make it harder to use them accidentally outside the context.
Below the service layer is the Confluence application itself, which is divided into subsystems. More on this when I know what to do with them myself.
Rate this page: