Creating a caching search system in java for xpages

We have several search databases that we use in several applications, and I'm trying to find the best and most efficient way to make these search databases accessible through a java function or bean in the OSGi plugin library.

What I would like to achieve is a way to create a function that I can pass in the search key and field name, and the function will return the correct value and, possibly, the type of the object (to deal with data values). You also need to cache the value for about an hour at the application level, as these search documents do not change at all.

Usually I would like to use them for display, so I only need to save the key in the notes document, and then use something like the following to display on the screen:

<xp:text escape="true" id="computedField1"> <xp:this.value><![CDATA[#{javascript:com.mycompany.lookup.GetDoc("docID","fieldName")}]]></xp:this.value> </xp:text> 
+6
source share
2 answers

You can do this pretty well now with the beans scope, with one caveat that the bean is an NSF specification. Despite the fact that the XSP Starter set, in my opinion, includes an example of how to make a server bean (which is really a singleton, that is, there is only one instance of the class for the entire JVM).

First, create a simple serializable POJO called CachedData, which has two members, the first is a field that contains a date time value that indicates when you last read data from disk, and the second is some kind of list object, like a vector which contains your values.

Then create another POJO called ServerMap, which has a map <string, map <string, map <string, map <Object, map <object, CachedData> gt; > gt; > gt; as a member, and a function called doCachedLookup () or something like that. The parameters of this function can be almost the same as @DbLookup, server, database, view, key, etc. Then in doCachedLookup check your ServerMap for the specified server as the key. If this does not exist, create a new card and insert it into ServerMap with the key being the server name. If it exists, then find the database name on this map, then the view on the next map, and then finally the value on the last map. When you receive the CachedData object, you can check the date date field and see if it has expired, if not, return the vector, and if it is, drop it, then perform a new search and re-cache the data, and then return the vector.

Here are code examples, I was a bit lazy in my overloaded methods to get the column and get the field name, and I use some deprecated java date methods, but it will give you a good base to start with. All code checked:

CachedData Class:

 package com.ZetaOne.example; import java.io.Serializable; import java.util.Date; import java.util.Vector; public class CachedData implements Serializable { private static final long serialVersionUID = 1L; private Date updateTime; private Vector<Object> values; public Date getUpdateTime() { return this.updateTime; } public void setUpdateTime(Date UpdateTime) { updateTime = UpdateTime; } public Vector<Object> getValues() { return this.values; } public void setValues(Vector<Object> values) { this.values = values; } } 

The CachedLookup class, which is implemented as a singleton, so that it can be used on the server:

 package com.ZetaOne.example; import java.io.Serializable; import java.util.Date; import java.util.Vector; import com.ZetaOne.example.CachedData; import java.util.HashMap; import java.util.Collections; import java.util.Map; import lotus.domino.Session; import lotus.domino.Database; import lotus.domino.View; import lotus.domino.NotesException; import lotus.domino.ViewEntryCollection; import lotus.domino.ViewEntry; import lotus.domino.Document; import javax.faces.context.FacesContext; public class CachedLookup implements Serializable { private static CachedLookup _instance; private static final long serialVersionUID = 1L; private Map<String, HashMap<String, HashMap<String, HashMap<Object, HashMap<Object, CachedData>>>>> cachedLookup; public static CachedLookup getCurrentInstance() { if (_instance == null) { _instance = new CachedLookup(); } return _instance; } private CachedLookup() { HashMap<String, HashMap<String, HashMap<String, HashMap<Object, HashMap<Object, CachedData>>>>> cachedLookupMap = new HashMap<String, HashMap<String, HashMap<String, HashMap<Object, HashMap<Object, CachedData>>>>>(); this.cachedLookup = Collections.synchronizedMap(cachedLookupMap); } @SuppressWarnings("deprecation") public Vector<Object> doCachedLookup(String serverName, String filePath, String viewName, Object keyValues, int columnNumber, boolean exactMatch) { if (cachedLookup.containsKey(serverName)) { if (cachedLookup.get(serverName).containsKey(filePath)) { if (cachedLookup.get(serverName).get(filePath).containsKey(viewName)) { if (cachedLookup.get(serverName).get(filePath).get(viewName).containsKey(keyValues)) { if (cachedLookup.get(serverName).get(filePath).get(viewName).get(keyValues).containsKey(columnNumber)) { CachedData cache = cachedLookup.get(serverName).get(filePath).get(viewName).get(keyValues).get(columnNumber); if (cache.getUpdateTime().compareTo(new Date()) > 0) { System.out.println("Cache Hit"); return cache.getValues(); } } } } } } System.out.println("Cache Miss"); // if we drop to here, cache is either expired or not present, do the lookup. try { Session session = (Session)resolveVariable("session"); Database db = session.getDatabase(serverName, filePath); View view = db.getView(viewName); ViewEntryCollection vc = view.getAllEntriesByKey(keyValues, exactMatch); ViewEntry ve, vn; ve = vc.getFirstEntry(); Vector<Object> results = new Vector<Object>(); while (ve != null) { results.add(ve.getColumnValues().elementAt(columnNumber)); vn = vc.getNextEntry(); ve.recycle(); ve = vn; } vc.recycle(); if (!cachedLookup.containsKey(serverName)) { cachedLookup.put(serverName, new HashMap<String, HashMap<String, HashMap<Object, HashMap<Object, CachedData>>>>()); } if (!cachedLookup.get(serverName).containsKey(filePath)) { cachedLookup.get(serverName).put(filePath, new HashMap<String, HashMap<Object, HashMap<Object, CachedData>>>()); } if (!cachedLookup.get(serverName).get(filePath).containsKey(viewName)) { cachedLookup.get(serverName).get(filePath).put(viewName, new HashMap<Object, HashMap<Object, CachedData>>()); } if (!cachedLookup.get(serverName).get(filePath).get(viewName).containsKey(keyValues)) { cachedLookup.get(serverName).get(filePath).get(viewName).put(keyValues, new HashMap<Object, CachedData>()); } CachedData cache; if (cachedLookup.get(serverName).get(filePath).get(viewName).get(keyValues).containsKey(columnNumber)) { cache = cachedLookup.get(serverName).get(filePath).get(viewName).get(keyValues).get(columnNumber); } else { cache = new CachedData(); } Date dt = new Date(); dt.setHours(dt.getHours() + 1); cache.setUpdateTime(dt); cache.setValues(results); cachedLookup.get(serverName).get(filePath).get(viewName).get(keyValues).put(columnNumber, cache); view.recycle(); db.recycle(); return results; } catch (NotesException e) { // debug here, im lazy return null; } } public Vector<Object> doCachedLookup(String serverName, String filePath, String viewName, Object keyValues, String fieldName, boolean exactMatch) { if (cachedLookup.containsKey(serverName)) { if (cachedLookup.get(serverName).containsKey(filePath)) { if (cachedLookup.get(serverName).get(filePath).containsKey(viewName)) { if (cachedLookup.get(serverName).get(filePath).get(viewName).containsKey(keyValues)) { if (cachedLookup.get(serverName).get(filePath).get(viewName).get(keyValues).containsKey(fieldName)) { CachedData cache = cachedLookup.get(serverName).get(filePath).get(viewName).get(keyValues).get(fieldName); if (cache.getUpdateTime().compareTo(new Date()) > 0) { System.out.println("Cache Hit"); return cache.getValues(); } } } } } } System.out.println("Cache Miss"); // if we drop to here, cache is either expired or not present, do the lookup. try { Session session = (Session)resolveVariable("session"); Database db = session.getDatabase(serverName, filePath); View view = db.getView(viewName); ViewEntryCollection vc = view.getAllEntriesByKey(keyValues, exactMatch); ViewEntry ve, vn; ve = vc.getFirstEntry(); Vector<Object> results = new Vector<Object>(); while (ve != null) { Document doc = ve.getDocument(); results.add(doc.getItemValue(fieldName)); doc.recycle(); vn = vc.getNextEntry(); ve.recycle(); ve = vn; } vc.recycle(); if (!cachedLookup.containsKey(serverName)) { cachedLookup.put(serverName, new HashMap<String, HashMap<String, HashMap<Object, HashMap<Object, CachedData>>>>()); } if (!cachedLookup.get(serverName).containsKey(filePath)) { cachedLookup.get(serverName).put(filePath, new HashMap<String, HashMap<Object, HashMap<Object, CachedData>>>()); } if (!cachedLookup.get(serverName).get(filePath).containsKey(viewName)) { cachedLookup.get(serverName).get(filePath).put(viewName, new HashMap<Object, HashMap<Object, CachedData>>()); } if (!cachedLookup.get(serverName).get(filePath).get(viewName).containsKey(keyValues)) { cachedLookup.get(serverName).get(filePath).get(viewName).put(keyValues, new HashMap<Object, CachedData>()); } CachedData cache; if (cachedLookup.get(serverName).get(filePath).get(viewName).get(keyValues).containsKey(fieldName)) { cache = cachedLookup.get(serverName).get(filePath).get(viewName).get(keyValues).get(fieldName); } else { cache = new CachedData(); } Date dt = new Date(); dt.setHours(dt.getHours() + 1); cache.setUpdateTime(dt); cache.setValues(results); cachedLookup.get(serverName).get(filePath).get(viewName).get(keyValues).put(fieldName, cache); view.recycle(); db.recycle(); return results; } catch (NotesException e) { // debug here, im lazy return null; } } private static Object resolveVariable(String variable) { return FacesContext.getCurrentInstance().getApplication() .getVariableResolver().resolveVariable( FacesContext.getCurrentInstance(), variable); } } 

XPage example:

 <xp:text id="text1"> <xp:this.value><![CDATA[#{javascript: com.ZetaOne.example.CachedLookup.getCurrentInstance().doCachedLookup( database.getServer(), database.getFilePath(), "lookup", "Test Category", "Value", true ) }]]></xp:this.value> </xp:text> 

+8
source

When you make beans, you can use EL to get content that is faster than SSJS. And YES - use the server area from the XSP Starter Kit. For caching: don't reinvent the wheel! There is a VERY complete implementation of all kinds of fancy caching: http://commons.apache.org/jcs/ I used this in the Tomcat application before and it worked very reliably. I do not understand why this would not be a good choice for your task.

+2
source

Source: https://habr.com/ru/post/910093/


All Articles