valueChangeListener code as a managed bean by Tony McGuckin, which was linked from
valueChangeListener implementation code from Declan Sciolla-Lynch, which pointed to
A better way to update log fields by Chris Toohey
I used my "R&D skills" to set up the code in my application and was excited when it seemed to work right off the bat. I moved it to the QA environment and then things started going bad. I kept getting Null Pointer Exception errors when I tried to add and update documents. I eventually realized a) I hadn't tried to create documents on the development server, and b) I hadn't tried to update documents that had never been updated previously. Neither the valueChangeListener bean nor the addToList function were working if the starting value of the field was an empty string.
I still need to figure out how to identify an empty string in those fields to properly handle that situation, but I got around it by making a few changes in the code and by adding a default value to a field so it doesn't start as blank.
The "do something useful" code to put in Tony's bean ('c' is a UIComponent object):
// Get the name of the field that changedCode to read the old and new values and write them to a log field named ActivityHistory:
String changedExpression = c.getValueBinding("value").getExpressionString();
int firstDot = changedExpression.indexOf(".") + 1;
int closingBracket = changedExpression.indexOf("}");
String changedField = changedExpression.substring(firstDot,closingBracket);
// Get the old and new values in the field
String oldValue;
try {
oldValue = valueChangeEvent.getOldValue().toString();
} catch (NullPointerException npex) {
oldValue = "";
} catch (Exception ex) {
System.out.println("Major failure");
ex.printStackTrace();
oldValue = "";
};
String newValue = valueChangeEvent.getNewValue().toString();
MapviewScope = ExtLibUtil.getViewScope();
HashMapoldValuesMap = new HashMap ();
HashMapnewValuesMap = new HashMap ();
if (viewScope.containsKey("oldValues")){
oldValuesMap = (HashMap) viewScope.get("oldValues");
newValuesMap = (HashMap) viewScope.get("newValues");
}
oldValuesMap.put(changedField, oldValue);
newValuesMap.put(changedField, newValue);
viewScope.put("oldValues", oldValuesMap);
viewScope.put("newValues", newValuesMap);
var dNow = @Now();Updated addToList code (I used 'first' and 'last' instead of 'prepend' and 'append'):
if (viewScope.containsKey("oldValues")){
var oldValues:java.util.HashMap = viewScope.get("oldValues");
var newValues:java.util.HashMap = viewScope.get("newValues");
for (key in oldValues.keySet()) {
actText = "Field " + key + " changed from '" + oldValues.get(key) + "' to '" + newValues.get(key) + "' - " + @Name("[CN]",session.getEffectiveUserName()) + " on " + @Text(dNow);;
addToList(bundleDoc,"ActivityHistory",actText,"last");
}
}
function addToList(datadoc:NotesXspDocument, fieldname:string, newVal:string, addPos:string) {
var newArr = new Array(datadoc.getItemValue(fieldname));
switch (addPos) {
case 'first':
newArr.unshift(newVal);
break
case 'last':
newArr.push(newVal);
break
}
datadoc.replaceItemValue(fieldname,newArr);
return true;
};
If anyone can explain what I missed with fields that start with a value of empty string, I'd appreciate it as I'm very early in my XPages and Java learning. In the mean time, I hope this proves useful to others.