-
Notifications
You must be signed in to change notification settings - Fork 118
Description
Describe the bug
When you call SearchExpressionHandlerImpl.resolveClientIds(...) with an expression like "@this," that ends with the delimiter the function will call handler.invokeOnComponent(searchExpressionContext, expression, internalCallback); with an empty string leading to a IllegalArgumentException
java.lang.IllegalArgumentException: ""
at jakarta.faces.component.UIComponentBase.findComponent(UIComponentBase.java:371)
at com.sun.faces.component.search.SearchExpressionHandlerImpl.invokeOnComponent(SearchExpressionHandlerImpl.java:294)
at jakarta.faces.component.search.SearchExpressionHandler.invokeOnComponent(SearchExpressionHandler.java:180)
at com.sun.faces.component.search.SearchExpressionHandlerImpl.resolveClientIds(SearchExpressionHandlerImpl.java:109)
The problem lies in function splitExpressions(...) which does not remove trailing separators.
But it does remove leading separators since ",@this" will work as expression, making it inconsistent.
This leads to problems with composite components having optional expressions like <p:commandButton update="@form, #{cc.attrs.update}"/>
To Reproduce
Call the function with expression "@this," or "@this, " (optional space at end)
or using PrimeFaces with below example since PF 14 delegates the ajax client-id resolving to the faces implementation `SearchExpressionHandlerImpl. primefaces/primefaces#14114
<!-- not working - separator at end -->
<p:commandButton update="@this,"/>`
<!-- working - separator at start -->
<p:commandButton update=",@this"/>`
Solution
Fix splitExpression to ignore trailing separators (or empty sub expressions) in the expression argument
or
check the splitted expression inside the loop of resolveClientIds(...) to not be empty, consistent with checking the whole expression before splitting to not be empty.
mojarra/impl/src/main/java/com/sun/faces/component/search/SearchExpressionHandlerImpl.java
Line 103 in 932606d
| for (String expression : handler.splitExpressions(facesContext, expressions)) { |
// "@this," will split to
if (!expressions.isEmpty()) {
// ["@this", ""] - splitExpressions should only return ["@this"]
for (String expression : handler.splitExpressions(facesContext, expressions)) {
// check single expression to not be empty
if (!expression.trim().isEmpty()) {
if (handler.isPassthroughExpression(searchExpressionContext, expression)) {
internalCallback.addClientId(expression);
} else {
handler.invokeOnComponent(searchExpressionContext, expression, internalCallback);
}
}
}
}
Expected behavior
Ignore empty expressions.