Last updated Apr 19, 2024

Architecture overview

This page provides a very high level overview of Jira's dependencies and the role each one plays in Jira. This page makes references to external resources (websites, books) where one can find more information.

Technical introduction

Jira is a web application written in Java. It is deployed as a standard Java WAR file into a java Servlet Container such as Tomcat.

WebWork

As Jira is a web application, users interact with Jira using a web browser. Jira uses OpenSymphony's WebWork 1 to process web requests submitted by users. Please note that WebWork 1, not 2, is used. WebWork 1 is a MVC framework similar to Struts. Each request is handled by a WebWork action which usually uses other objects, such as utility and Manager classes to accomplish a task.

Jira uses JSP for the View layer. So most of HTML that is served to the user as the response to their web request is generated by a JSP. Therefore, to generate a response the WebWork action uses a JSP.

For more information on WebWork 1 please see its online documentation.

Jira WebWork actions and actions.xml

web application framework defines what happens when you visit a particular URL in a web application. For example, the URL for a simple static page with no dynamic content could end in ".html". A ".jspa" suffix indicates that the URL is referring to a page whose content was created using Java Server Pages (JSP). JSP files are templates that can contain both HTML and commands to create HTML. The commands refer to a Java object and the object's methods are called just as in an ordinary Java program. The mapping of the URL to a Java class in Jira is done using the Webwork 1.x web application framework. The original documentation for Webwork 1.x can be found at opensymphony.com/webwork_old/src/docs/manual and wiki.opensymphony.com/display/WW1/Home. However, this framework has been superseded by Webwork 2, which is used by Confluence, Bamboo and Crowd

The mappings between a URL and classes are declared in the actions.xml file (src/webapp/WEB-INF/classes/actions.xml). A typical element of the file looks like this:

1
2
<!-- Workflow Transitions -->
<action name="admin.workflow.ViewWorkflowTransition" alias="ViewWorkflowTransition" roles-required="admin">
    <view name="success">/secure/admin/views/workflow/viewworkflowtransition.jsp</view>

    <command name="moveWorkflowFunctionUp" alias="MoveWorkflowFunctionUp">
        <view name="error">/secure/admin/views/workflow/viewworkflowtransition.jsp</view>
        <view name="success">/secure/admin/views/workflow/viewworkflowtransition.jsp</view>
    </command>

    <command name="moveWorkflowFunctionDown" alias="MoveWorkflowFunctionDown">
        <view name="error">/secure/admin/views/workflow/viewworkflowtransition.jsp</view>
        <view name="success">/secure/admin/views/workflow/viewworkflowtransition.jsp</view>
    </command>
</action>

A few things to note:

  • Each action element has an alias attribute, which is the part of the URL that you see in a web browser. The name element is the name of the Java class that is used by the alias.
  • The name of the view element is the String returned from the action to decide which view to show after the action is invoked.
  • The name of the command element can be used in the URL as a !commandName suffix and implemented in the Action class as the doCommandName() method.
  • All actions that don't require the role specified in roles-required should manage their own security or be available to all users.

Command elements are optional, and are used when several interactions belong to the same Action. A command name is specified on the URL like this:

1
2
SomeAction!myCommand.jspa

The command is implemented in a method in the Action class with the corresponding name:

1
2
public String doMyCommand() {

    // implement the command logic here

    return "someview";
}

The doExecute method is run when no command is requested i.e. the bare /path/to/MyAction.jspa.

Security

When adding an action to the actions.xml You must ensure the appropriate roles-required value is specified. This will ensure only users in the authorised role can execute the action. For actions that can be handled by application level security, such as those actions that can be given to project administrators identified through the course of administering Jira, no role may be required, likewise setup actions and others that manage their own permissions. For some actions, the use role must be present. This ensures the user is logged in and identified.

The admin role is required for all administration actions so you must be sure when adding an action that your new action has roles-required="admin" or confident that it doesn't need it. The sysadmin role requires the user be a system administrator, and the use role requires that they just be logged in. (Other definitions can be found in Permissions.java in the source).

Actions don't care about the path of the URI, just the ActionName.jspa and optionally the !commandName suffix.

Webwork Plugins: Jira can have new actions defined using the Webwork. These actions can also override existing actions in Jira. However, jsp files cannot currently be bundled in the plugin jar file and have to be installed in a separate step when deploying such a plugin. There is a Webwork Sample plugin that contains example actions and classes that can be used to understand this topic more fully.

Seraph

Almost all authentication in Jira is performed through Seraph, Atlassian's open source web authentication framework. The goal of seraph is to provide a simple, extensible authentication system that we can use on any application server.

Seraph is implemented as a servlet filter. Its sole job is, given a web request, to associate that request with a particular user. It supports several methods of authentication, including HTTP Basic Authentication, form-based authentication (ie. redirect to an internal or external login form), and looking up credentials already stored in the user's session (e.g. a cookie set by a SSO system).

Seraph performs no user management itself. It merely checks the credentials of the incoming request, and delegates any user-management functions (looking up a user, checking a user's password is correct) to Jira's user-management - Embedded Crowd (discussed later in this document).

If you were looking to integrate Jira with a Single Sign-On (SSO) solution, you would do so by writing a custom Seraph authenticator (and in fact, many customers have done so). Please note that by default Jira is not shipped with any SSO integration, customers have to write a custom Authenticator themselves.  You may also want to check out Crowd and integrating Jira with Crowd.

Another very important function that Seraph performs in Jira is to only allow users with Global Admin permission to access WebWork actions that allow the user to perform administration tasks. These WebWork actions are accessed by URLs starting with "/admin". For more information on Jira's permissions, see Jira's documentation.

For more information on how seraph works internally please see this page.

Embedded Crowd

Crowd is Atlassian's Identity Management and Single Sign On (SSO) tool.
Both Jira and Confluence now embed a subset of Crowd's core modules for powerful and consistent user management.

Embedded Crowd provides the following functionality:

  1. Stores users and groups in Jira's database
  2. Stores group membership (which users are part of which groups) in Jira's DB
  3. Authenticates users (checks if the users password matches)
  4. Provides API that allows to manage (create, delete) users, groups and group memberships (add and remove users from groups).
  5. Allows Jira to connect to external systems to retrieve user/group data (eg Microsoft AD, LDAP or a standalone Crowd server)
  6. Keeps a copy of any external data in the local DB for faster retrieval, and synchronises in the background.

As mentioned previously, Seraph delegates to Embedded Crowd to authenticate the user (i.e. check whether the correct password has been entered when a user tries to login).

For information on the DB tables used by Embedded Crowd see "Users and Groups" in the Jira Database Schema page.

Jira supports the use of Jira:PropertySet to store user preferences
In Jira the preferences include things like:

  • whether the user would like to receive HTML or Text e-mail
  • number of issues to display in Jira's Issue Navigator
  • whether to receive notifications for user's own updates to issues
  • Locale (Language) of the user

In addition, Embedded Crowd also has its own concept of "User Attributes".
The two concepts, although related, do provide different advantages and disadvantages, so plugin developers should consider their individual requirements in order to choose the more suitable way.

User properties in PropertySets

  • PropertySet values are typed.
    There are 11 different types allowed including numbers, dates, arrays of bytes, parsed XML DOM's, nested Properties, and arbitrary serialized Objects.
  • These can be arbitrarily large, as they can be stored as CLOBs or BLOBs in the database.
    These large amounts of data are not suitable for searching against.
  • PropertySets only allow a single value to be stored against a given key.

Embedded Crowd user attributes

  • Crowd Attributes store only text data.
  • In order to facilitate searchability, Crowd limits the values to 255 characters or less.
    (Note that MySQL has a limitation that means you can't index columns with > 255 characters )
  • Crowd allows multiple values to be stored against a single key.
    These values must all be unique with a case-insensitive test.
    (This follows the standard LDAP behaviour).

PropertySet

OpenSymphony's PropertySet is a framework that can store a set of properties (key/value pairs) against a particular "entity" with a unique id. An "entity" can be anything one wishes. For example, Jira's UserPropertyManager uses PropertySet to store user's preferences. Therefore, in this case, the "entity" is a User.

Each property has a key (which is always a java.lang.String) and a value, which can be:

  1. java.lang.String
  2. java.lang.Long
  3. java.util.Date
  4. java.lang.Double

Each property is always associated with one entity. As far as PropertySet is concerned an "entity" has an entity name, and a numeric id. As long as the same entity name/id combination is used to store the value and retrieve the value, everything will work.

In Jira PropertySet uses the following database tables:

  1. propertyentry - records the entity name and id for a property, its key, and the data type of the property's value. Each record in this table also has a unique id.
  2. propertystring - records String values
  3. propertydecimal - records Double values
  4. propertydate - records Date values
  5. propertynumber - records Long values

Each of the records in property<type> tables also has an id column. The id is the same as the id of the propertyentry record for this property. As the property's key and value are split across 2 tables, to retrieve a property value, a join needs to be done, between propertyentry table and one of the property<type> tables. Which property<type> table to join with is determined by the value of the propertytype column in the propertyentry record.

Here is an example of a full name stored for a user:
(to do)

PropertySet is used in Jira:

  1. By the UserPropertyManager to store users preferences.
  2. To store Application Properties, which are configurable settings that a user can change to customise their installation of Jira. 
  3. To store chosen preferences of gadgets on user's dashboards.

For more information on PropertySet please see its documentation. Also see Jira Database Schema.

Jira applications

The Jira family of applications currently consists of Jira Software, Jira Service Management, and Jira Core. A Jira application is built on the Jira platform, and extends and modifies the base functionality provided by the Jira platform. For example, the Jira Software application provides software development features that are not part of the Jira platform, such as agile boards, linked development tool information (e.g. commits, builds, etc), and software project templates.

An Application is a blob of plugins that operate together on top of the platform to provide functionality. The plugins can be divided into three types:

  1. Primary plugin: The plugin that defines the product. Disabling this plugin will will disable the product. There is only one primary plugin per Application. The primary plugin may also provide Application functionality.
  2. Application plugin: A plugin providing fundamental features for the Application. All product plugins must be enabled and working for the product to be considered working. The product plugin is owned by the product (that is, the application plugin will not work without the primary plugin of the Application).
  3. Utility plugin: A plugin that provides utilities to the primary and/or Application plugins. A utility plugins is not owned by the Application (i.e. the utility plugin will work without the primary plugin of the Application) and may be used by multiple Applications or other non-application plugins.

An Application may be installed, upgraded, disabled, removed, licensed, and have its configuration cleared dynamically.

If you are building for one of the Jira applications, rather than on the Jira platform itself, you will also need to be aware of the following:

  • Licensing: Each Jira application can be licensed individually. You can install one or more applications in Jira via the Manage applications page. The base Jira application, Jira Core, provides basic project tracking capabilities for business teams. All Jira applications include access to Jira Core, or you can license Jira Core only for users that need basic access to Jira.
  • User management: Jira administrators can grant access to licensed applications to specific groups (e.g. jira-software-users), via the Application access page in Jira. Users can then be added to these groups to grant them access to the Jira applications. Granting access to a user for an application, consumes a seat in the license for that Jira application. For example, a Jira administrator could grant a user access to Jira Software, which would consume one of the seats in the Jira Software license for that instance.
  • Project types: Installing and licensing an application in Jira provides additional project types that are specific to that application. For example, installing Jira Software allows users to create a 'Scrum software development' project type, which has boards, its own workflow, and its own issue types.
  • APIs: The Jira platform has a set of REST APIs and Java APIs. In addition, each Jira application has its own REST APIs and Java APIs that allow programmatic access to functionality that is specific to the application. For example, the Jira Software REST API includes methods to create, modify, and delete sprints.
  • Plugin modules: Plugin modules are UI extension points which apps can use to insert content into various areas of the host application's interface. The plugin modules are part of the Jira platform and therefore are common to all Jira applications. However, be aware that you can use these modules to access application-specific parts of the user interface. For example, you can add a dropdown to an agile board in Jira Software by specifying a web panel module that has a location of 'board-links'.

Jira Utility and Manager Classes

A lot of business logic in Jira is implemented in hundreds of java classes. The classes can be simple utility classes or Manager Objects.

Manager Objects in Jira usually have one specific goal (or topic). For example com.atlassian.jira.project.version.VersionManager is used to work with project versions, i.e. create, update, delete and retrieve versions.

Manager objects use a lot of external dependencies, most of which are open source, but some are developed by Atlassian and are usually shared between Atlassian products.

Since Jira 3.7 Manager classes are generally also wrapped by a corresponding service class.  The idea is that any validation of business logic necessary is carried out by the service classes whereas manager classes are responsible for actually doing the action.  For instance see the ProjectService's validateCreate method and it's corresponding create method. The ProjectManager then only has a create method which will go off and create a project assuming any validation has already been carried out by the client.  This allows clients to simply call the service class in order to validate and create a project, but still gives the flexibility of circumventing validation if the ProjectManager is used directly.

Jira-specific Atlassian events

The Atlassian Event library is available to all plugins, allowing them to listen to events occurring within Jira. The events available in Jira are shown below. You may also want to read about the Jira plugin lifecycle or try the Writing Jira event listeners with the atlassian-event library tutorial.

Event TypeDescriptionSource
ApplicationPropertyChangeEventThrown when changes occur in the application properties.Jira
IssueEventThrown when changes occur in issues.Jira
UserEventThrown when changes occur in users.Jira
ClearCacheEventThrown when Jira should clear and reinitialise all of its caches.Jira
ClearHttpCacheEventEvent that a host application can throw to clear Shindig's cache.Gadgets
XMLRestoreFinishedEventThrown when an XML backup is finished being restored.Crowd

Version events:

Thrown when changes are made to project versions.

Note: All of these extend AbstractVersionEvent)

Jira

Project events:

Thrown when changes are made to a project.

Note: All of these extend AbstractProjectEvent).

Jira

Rate this page: