The OpenEngSB contains various different persistence solutions which should be introduced and explained in this chapter
The OpenEngSB has a central persistence service, which can be used by any component within in the OpenEngSB to store data. The service is designed for flexibility and usability for the storage of relatively small amounts of data with no explicit performance requirements. If special persistence features need to be used it is recommended to use a specialized storage rather than the general storage mechanism.
The persistence service can store any Java Object, but was specifically designed for Java Beans. With the following additional conditions: First of all the bean to persist needs to be serializable. In addition the equals method needs to be overwritten. If a field on the lhs of the comparision is null every field on the rhs is accepted; otherwise the fields are compared dirctly.
The interface of the persistence service supports basic CRUD (create, update, retrieve, delete) mechanisms. Instances of the persistence service are created per bundle and have to make sure that data is stored persistently. If bundles need to share data the common persistence service cannot be used, as it does not support this feature. The persistence manager is responsible for the management of persistence service instances per bundle. On the first request from a bundle the persistence manager creates a persistence service. All later requests from a specific bundle should get the exact same instance of the persistence service.
Queries with the OpenEngSB persistence done via the persistence service. Behind this service an easy query-by-example logic is used to retrieve your results. Since the current persistence implementation of the OpenEngSB builds on serialisation it can happen that some additional actions are required to restore the object. In that case make use of the SpecialActionsAfterSerialisation interface. If your entities implement the interface the "doSpecialActions" method is called after restoring allowing you to do additional actions to the bean before it's returned to the caller.
The persistence solution of the OpenEngSB was designed to support different possible back-end database systems. So if a project has high performance or security requirements, which can not be fulfilled with the default database system used by the persistence service, it is possible to implement a different persistence back-end. To make this exchange easier a test for the expected behavior of the persistence service is provided.
Besides the centralized Java Bean store the OpenEngSB also have a more specialized solution to store configurations. Configurations are basically also Java Beans, but have to extend a ConfigItem. Well, since Configurations are also only Java Beans you may ask: Why not simply store them via the persistence service? The reason is quite simple. We do need to store configurations at various places. Options may be the file system, an object store or any other place. In addition configurations, when you e.g. store them to files, have to be quite specific about their types. Rule, for example, have to be stored as simple strings, flows as xml files and connectors as key-value-pairs. Being so specific the implementations of the backends also have to be specific. Besides, there are kind of regions. Examples are Rules, Flows, and various others. Basically in you code you simply want to ask for a configuration persister for rules and do not care if it is a file persister or something else. In addition rules could be persisted somewhere else than e.g. flows. Therefore those backends have to be configured separate for each type.
Ok, after the need is identified let's take a look at the how. Basically it's quite simple. You register various backend services in the OSGi registry, give them a specific ID, configure how a region is mapped to an idea and request a persister for a specific region or type and retrieve the correct implementation. From a user point of view this system is quite simple. Use the getConfigPersistenceService(String type) method from the OpenEngSBCoreServices class with the type, which is typically stored directly at the configurations, as for example for the RuleConfiguration and retrieve and persist RuleConfigurations. The mapping between the backend and the frontend is defined in the configuration file here. If you want to use another available and compatible backend for rule configurations add the backend id in the configuration file and the service for this region will switch automatically.
Although it is quite simple to configure, change and consume and provide configurations it is mostly not a good idea to simply change the properties, backend or frontend if you're not exactly sure about what you're doing. You can easily take the wrong backend service which will not be able to persist e.g. a RuleConfiguration and throws exceptions. If you swtich the backend during the run everything stored in the old backend would not be available in the new one. Within a client project mostly relay on using those services to read the properties and use the OpenEngSB to store them.
Still the system can easily be extended to your own use. Typically you have to do the following steps to provide a new configuration service. First of all start by providing an own Configuration which extends ConfigItem. Please only use the metadata and content fields and do not add additional variables. They wont get stored. Now add a configuration file into etc with org.openengsb.persistence.config-ANY_NAME_YOU_LIKE.cfg. In this file define the region and the backend id. The exact values and detailed explanation for those fields is available here. If you've not choosen one of the general available services for storage you now can implement your own backend service registered in the OSGi registry with the ID you've configured in the .cfg file before. The interface you have to implement and register as a service is the ConfigPersistenceBackendService.
The context configuration persistence follows the basic configuration persistence scheme. In this case the backend (ContextFilePersistenceService) creates files for each context (basically empty files with filename <contextId>.context), the context service (ContexServiceImpl) requests a config persistence service of type CONTEXT, is given the aforementioned one and uses it to persist its data.