What is PermaStore?
PermaStore is a core part of the Leap Framework, its main responsibility is to facilitate storage and access for runtime configuration data used by Features.
At first glance the attributes of PermaStore may not be apparent – you may ask “why not just use the database”? By the end of this article the answer to that question should be clear.
Configurations in PermaStore are defined as XML in a configuration file usually belonging to a specific Feature and located in the Feature’s ../config/
directory. Any data that is defined within the bounds of a Configuration Builder is bootstrapped into PermaStore when the Leap application starts.
Within the PermaStore configuration file (examples below) developers set the following attributes:
Name
– Unique name that identifies this store of dataisEnabled
– Flag that indicates whether this configuration should be loadedFeatureInfo
– Describes which Feature & Feature Group the configuration applies toDataType
– The type of data that is stored in the configuration. Usually this will eitherMap
orList
.ConfigurationBuilder
– Defines whether the PermaStore data will be Inline, Custom, or SQL. Based on the valueBuilder
defined within this tag will change.<InlineBuilder>
,<CustomBuilder>
, or<SQLBuilder>
InlineBuilder
– Most often this is used to define a List or Map with values directly in the configuration file. Frequently a JSON Object.CustomBuilder
– Allows the developer to use the Full Qualified Domain Name to reference an implementation of theIPermastoreCustomCacheObjectBuilder
interface. This class is responsible for returning the List or Map that will be used in the configuration.SQLBuilder
– Allows the developer to specify a SQL query that will query for data to be cached. Is this data from the Leap DB or can we pass a Connection/Class to other DB?
Additionally, the Leap Framework team is working to add event publishers and subscribers that are triggered when data in PermaStore is manipulated. Although it is not yet available, it is work in progress.
Parts of PermaStore
- CRUD API for managing data within PermaStore. Referencing the configuration by the Name field
- In-Memory data grid implemented as Hazelcast. Very fast access and allows for configurations to be highly resilient and available
- Persistence in the Leap DB (MySQL or HSQLDB). This allows changes via the CRUD API to be stored at runtime. This is beneficial in the case that the in-memory data grid is bounced, the data is re-initialized from the DB
- Configuration Files as XML that define the details a PermaStore configuration
When to use PermaStore?
PermaStore should only be used for a specific type of data that have specific circumstances. Most important, PermaStore is non-transactional and data in PermaStore must be non-volatile.
Volatile data does not suit PermaStore well because there is a cost to performance when interacting with PermaStore via CRUD. Because chances are persisted to a database as well as updated in cache PermaStore is not ideal for frequently changing data.
On the same note, because PermaStore is non-transactional the data that is persisted in the database is considered to be eventually consistent. Which is not usually appropriate for systems that require transactional operations and guaranteed data.
With these things in mind, it’s clear that PermaStore configurations are PERFECT for data that doesn’t change very often but may be accessed frequently by a Feature as part of its regular operation. This might include things like URLs to external services, Units of Measure, Ports to allocate for Socket connections, filepaths, etc…
Using PermaStore in a Feature
Up to this point we’ve defined what PermaStore is and how to configure it, now we will actually use the configuration.
Within any bean, the getPermaStoreConfiguration(RequestContext, ConfigName)
method can be called in order to retrieve the configuration and then access the data.
Once the data is retrieved from the PermaStore configuration, it can be used within the bean to accomplish the current task.
PermaStore Examples
IPermaStoreConfigurationService permaStoreConfigService = new PermaStoreConfigurationService(); permadata = permaStoreConfigService.getPermaStoreConfiguration(requestCtx, "dougs_data"); org.json.simple.JSONObject jsonObject = (org.json.simple.JSONObject) permadata.getConfigData();
<route id="permaStoreTestImpl"> <from uri="direct:testingPermaStore" /> <to uri="bean:leapConfigUtil?method=getPermastoreConfiguration(dougs_data)" /> <log message=" ${body}" /> </route>
PermaStore Configuration
<?xml version="1.0" encoding="UTF-8"?> <PermaStoreConfigurations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="permastoreconfig.xsd"> <PermaStoreConfiguration> <Name>lodnum</Name> <isEnabled>true</isEnabled> <featureInfo featureName="feature1" featureGroup="featuregroup1" /> <DataType>Map</DataType> <ConfigurationBuilder type="INLINE"> <InlineBuilder type="JSON-TO-Map"> {"variable" :"lodnum","locale_id":"US_ENGLISH"} </InlineBuilder> </ConfigurationBuilder> </PermaStoreConfiguration> </PermaStoreConfigurations>
<?xml version="1.0" encoding="UTF-8"?> <PermaStoreConfigurations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="permastoreconfig.xsd"> <PermaStoreConfiguration> <Name>AreaList</Name> <isEnabled>true</isEnabled> <featureInfo featureName="feature1" featureGroup="featuregroup1" /> <DataType>List</DataType> <ConfigurationBuilder type="CUSTOM"> <CustomBuilder> <builder>com.attunedlabs.permastore.config.PICAddressBuilder</builder> </CustomBuilder> </ConfigurationBuilder> </PermaStoreConfiguration> </PermaStoreConfigurations>
<?xml version="1.0" encoding="UTF-8"?> <PermaStoreConfigurations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="permastoreconfig.xsd"> <PermaStoreConfiguration> <Name>PicAreaList</Name> <featureInfo featureGroup="" featureName="" /> <DataType>List</DataType> <ConfigurationBuilder type="SQL"> <SQLBuilder> <SQLQuery mappedClass="com.attunedlabs.pic.Area">select * from table where areaType=?</SQLQuery> </SQLBuilder> </ConfigurationBuilder> </PermaStoreConfiguration> </PermaStoreConfigurations>