Application Cache Example
Let us consider the following scenario:
The list of currencies along with the description, number of decimal places is present in the database. Instead of querying every time, the same needs to be cached in memory for faster access.
This is a typical case for using the GenericDatabaseCacheDataBuilder. Assuming that the following SQL Map has been defined in the Default Logical Data Source:
<sqlMap> <resultMap id="CCY_LIST_RESULTMAP" class="java.util.HashMap"> <result property="CURRENCY" nullValue="" column="CURRENCY" javaType="java.lang.String" jdbcType="VARCHAR"/> <result property="NBR_DECIMAL" nullValue="" column="NBR_DECIMAL" javaType="java.lang.String" jdbcType="VARCHAR"/> </resultMap> <select id="CCY_LIST_SELECT_MASTER_DATA" parameterClass ="java.util.HashMap" resultMap="CCY_LIST_RESULTMAP"> SELECT COD_CCY CURRENCY,NBR_DECIMAL FROM CURRENCY_MASTER order by COD_CCY </select> </sqlMap>
The cache can be defined as –follows:
<Cache Id="MY_CURRENCY_CACHE" Scope="application" Preload="Y"> <Handler>com.intellectdesign.canvas.cache.handler.GenericDatabaseCacheDataBuilder</Handler> <HandlerParams> <Param Name="DATA_ACCESS_MAP_KEY">CCY_LIST</Param> <Param Name="DATA_ACCESS_EXTN">MASTER_DATA</Param> </HandlerParams> </Cache>
The keys highlighted in yellow help identify how the Data Access Location needs to be provided to the generic database cache handler. To consume this cache from the application code, the following sample code is provided:
List ccyCacheData = CacheManager.getInstance().getDataFromCache(null, "MY_CURRENCY_CACHE"); int numRecords = ccyCacheData.size(); Map aCcyData = null; for (int count = 0; count < numRecords; count++) { aCcyData = (Map)ccyCacheData.get(count); //Perform your application logic here.... }
The ccyCacheData retrieved in the sample code segment is equivalent of the query result of the earlier query configuration code segment. Hence, a simple iteration of the list will return the Maps (as configured in the SQL Map) that can be used for retrieving the data.
Let us consider a different scenario that requires some content to be loaded from XML and cached.The application configuration is stored as XML and needs to be parsed and validated.
Since the validation could be a costly affair and the XML will not typically change, the validation needs to be done only once. The parsed XML content should be stored in an in-memory cache for reuse.
This type of requirement needs a custom CacheDataBuilder for handling the cache data preparation logic.
public class MyCacheDataBuilder extends CacheDataBuilder { protected List initializeCache(HashMap parameters) { // Your logic goes here for parsing and validating the XML. // Assuming that at the end of validation, every node in the XML is returned as // a custom class MyCongurationObject. MyConfigurationObject[] allConfig = parseXML(); List<MyConfigurationObject> cacheData = Arrays.asList(allConfig); return cacheData; } private MyConfigurationObject[] parseXML() { //Your logic on parsing XML and converting to the Configuration Object. } }
Now that the CacheDataBuilder is created, let us define the cache and use it from the application.
<Cache Id="MY_CONFIG_CACHE" Scope="application" Preload="Y"> <Handler>com.myapplication.MyCacheDataBuilder </Handler> </Cache>
To consume this cache from the application code, the following sample code is provided:
List<MyConfigurationObject> cacheData = CacheManager.getInstance().getDataFromCache(null, "MY_CONFIG_CACHE"); for (MyConfigurationObject obj : cacheData) { //Perform your application logic here... }