Rate this page:
Available: | Confluence 2.2 and later |
Changed: | In Confluence 3.3 and later, plugins can define their own contexts using the KeyedBandanaContext interface. |
There are three main persistence APIs in Confluence.
Because Bandana is the primary persistence API used by plugin developers, it is covered in more detail than the other two APIs.
Bandana is an Atlassian framework for persistence of arbitrary Java objects. The concepts used in Bandana are very simple:
String
and the value can be any Object
. It should typically implement Serializable.
If the key or value types are defined within a plugin, the class should have a no-argument constructor to avoid class loading issues.Based on this design, the BandanaManager
has the following methods for storing and retrieving values from a context by key:
void setValue(BandanaContext context, String key, Object value)
– store a value against a key in the Bandana context.Object getValue(BandanaContext context, String key)
– get a key's value from the Bandana context. Returns null if no matching context and key exists.void removeValue(BandanaContext context, String key)
– remove a key and value from the Bandana context (available in Confluence 3.3 and later).Object getValue(BandanaContext context, String key, boolean lookUp)
– same as above, except if lookUp
is true and the context is a space context, this method will also check the global context if no matching key is found in the space context.Iterable<String> getKeys(BandanaContext context)
– provides an iterable to allow enumeration of all keys within a context (available in Confluence 3.3 and later).For plugins that use a context not provided by the application, we recommend that you use a context for your Bandana values
that includes the full package name of your plugin. For example, a theme plugin might use a context like org.acme.confluence.mytheme.importantPreference
.
By default, Bandana uses an XStream to convert objects into XML for storage.
However, it is possible to provide your own method of serialization. If your BandanaContext
implements the BandanaSerializerFactory interface (available in Confluence 3.3 and later),
it will be used to create an serializer to serialize and deserialize your objects.
Prior to Confluence 2.3, this XML was written to the filesystem in the Confluence home directory. The file config/confluence-global.bandana.xml
stores the global context, and there is a file config/
spaceKey
/confluence-space.bandana.xml
with the configuration for each space. In Confluence 2.3 and later, Bandana data is written to the BANDANA table in the database, with three columns for context, key and a serialized value.
BandanaManager
To get access to the BandanaManager
from your plugin code, normally you only need to include a private BandanaManager
field with an associated constructor parameter. Spring will construct your object and pass in the required component.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
@Scanned
public class MyMacro implements Macro {
@ConfluenceImport
private BandanaManager bandanaManager;
public MyMacro(BandanaManager bandanaManager) {
this.bandanaManager = bandanaManager;
}
// main method of macro
public String execute(...) {
// do stuff with bandanaManager
return "...";
}
}
Confluence uses the open-source persistence framework Hibernate.
Each object to be persisted has a *.hbm.xml
file that sits in the same directory as the associated class in the
Confluence web application. For example, Label.class
has an associated Label.hbm.xml
that describes how label objects
are persisted. The particular details vary from class to class, but typically include the following:
All this data is expressed in the standard Hibernate mapping format. In some cases, there is a single mapping file for all subclasses of a particular class. For example, ContentEntityObject.hbm.xml
includes mappings for pages, news, mail and space descriptions.
The Hibernate mapping files are listed in mappingResources
bean in applicationContext.xml
.
The list of Hibernate types (and mapping files) cannot be extended dynamically by plugins.
Although it might be possible to extend Confluence database through Hibernate, this is not recommended. There are a few downfalls with extending our Hibernate configuration:
Avoid using Confluence database to store custom data – use content properties or Bandana instead.
Content properties are key-value pairs associated with a ContentEntityObject
and stored in the database.
You can access content properties via the ContentPropertyManager like this:
1 2 3 4 5 6 7
Page page = pageManager.getPage("KEY", "Page title"); // retrieve the page however you like
// retrieving a String property - use your plugin key in the property key
String favouriteColor = contentPropertyManager.getStringProperty(page, "com.example.plugin.key.favourite-colour");
// storing a String property
contentPropertyManager.setStringProperty(page, "com.example.plugin.key.favourite-colour", "purple");
You should get the ContentPropertyManager
and PageManager
injected into your macro, servlet, etc. using the techniques outlined in Accessing Confluence Components from Plugin Modules page, (also demonstrated in the previous section).
Rate this page: