Details
-
Type: Bug
-
Status: Closed
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: EE-3.0.0.GA
-
Fix Version/s: 3.1, EE-3.0.0.GA_P01
-
Component/s: Framework
-
Labels:None
-
Environment:ICEfaces
-
Assignee Priority:P1
Description
Suggestion bellow is a fix for a possible NPE issue in our code located in org.icefaces.impl.context.DOMPartialViewContext.applyBrowserChanges(Map parameters, Document document), around lines 470-480:
// if we cannot loop through optionElements, we must have
// just a text node
if (0 == optionElementsLength) {
Node optionBodyNode = selectElement.getFirstChild();
// QUICK BUGFIX oboede 2012-06-04: In case of f:ajax updates this node value
// was sometimes <code>null</code>.
if (optionBodyNode != null) { <--------- (1) to avoid NPE at (2)
String optionBody = optionBodyNode.getNodeValue(); <--------------- (2)
// Should be constant, but may vary with JSF implementation
String SELECTED = "selected=\"true\"";
Matcher tagMatcher = OPTION_TAG.matcher(optionBody);
StringBuffer outBuffer = new StringBuffer();
while (tagMatcher.find()) {
String optionTag = tagMatcher.group(0);
Matcher valueMatcher = OPTION_VALUE.matcher(optionTag);
Matcher selectedMatcher = OPTION_SELECTED.matcher(optionTag);
String valuePair = null;
String value = null;
String selected = null;
if (valueMatcher.find()) {
valuePair = valueMatcher.group(0);
value = valueMatcher.group(1);
}
if (selectedMatcher.find()) {
selected = selectedMatcher.group(1);
SELECTED = selected;
}
if (values.contains(value)) {
if (null == selected) {
optionTag = optionTag.replace(valuePair, valuePair + " " + SELECTED);
}
} else {
if (null != selected) {
optionTag = optionTag.replace(" " + selected, "");
}
}
tagMatcher.appendReplacement(outBuffer, optionTag);
}
tagMatcher.appendTail(outBuffer);
optionBodyNode.setNodeValue(outBuffer.toString());
}
}
// if we cannot loop through optionElements, we must have
// just a text node
if (0 == optionElementsLength) {
Node optionBodyNode = selectElement.getFirstChild();
// QUICK BUGFIX oboede 2012-06-04: In case of f:ajax updates this node value
// was sometimes <code>null</code>.
if (optionBodyNode != null) { <--------- (1) to avoid NPE at (2)
String optionBody = optionBodyNode.getNodeValue(); <--------------- (2)
// Should be constant, but may vary with JSF implementation
String SELECTED = "selected=\"true\"";
Matcher tagMatcher = OPTION_TAG.matcher(optionBody);
StringBuffer outBuffer = new StringBuffer();
while (tagMatcher.find()) {
String optionTag = tagMatcher.group(0);
Matcher valueMatcher = OPTION_VALUE.matcher(optionTag);
Matcher selectedMatcher = OPTION_SELECTED.matcher(optionTag);
String valuePair = null;
String value = null;
String selected = null;
if (valueMatcher.find()) {
valuePair = valueMatcher.group(0);
value = valueMatcher.group(1);
}
if (selectedMatcher.find()) {
selected = selectedMatcher.group(1);
SELECTED = selected;
}
if (values.contains(value)) {
if (null == selected) {
optionTag = optionTag.replace(valuePair, valuePair + " " + SELECTED);
}
} else {
if (null != selected) {
optionTag = optionTag.replace(" " + selected, "");
}
}
tagMatcher.appendReplacement(outBuffer, optionTag);
}
tagMatcher.appendTail(outBuffer);
optionBodyNode.setNodeValue(outBuffer.toString());
}
}
The customer was unwilling to provide a test case or any markup that showed the process they were using to generate the NPE. However, they did provide the following description:
"We have a drop down menu 'country' which re-renders another menu 'states' by <f:ajax> annotation.
The problem occurs if you change the country from a country with states (e.g. the US) to a country without states (e.g. Germany). This leads to the "states" DDL being re-rendered without content, thus no option values are present and the NPE occurs."
I tried to generate a test case with two drop down lists where submitting the first one via Ajax would clear the options in the second list but was unable to reproduce the issue. No matter what I tried, the optionNodeBody in the code never came back with a null reference.
The check still seems relatively benign so I've checked the suggested change into the trunk. Resolving as fixed.