Search expression framework
In before JSF versions, it uses an absolute hierarchical ID, or a relative local ID to locate a component, it is useful to rerender a component in an ajax request. For more flexible to query the component, JSF added @all, @form, @this expression to search the component to be re-rendered.
JSF 2.3 extends these expression by introducing new Component search expression framework, which adds some useful and powerful keywords, and also provides APIs to define your own keywords in the expression.
The following table lists all new keywords added in JSF 2.3, it is just a copy from Arjan Tijms' blog entry: What's new in JSF 2.3.
Keyword
Description
@child(n)
The nth child of the base component
@composite
The closest composite component ancestor of the base component
@id(id)
All component descendants of the base component with the specified component id
@namingcontainer
The closest NamingContainer ancestor of the base component
@next
The next component in the view after the base component
@parent
The parent of the base component
@previous
The previous component to the base component
@root
The UIViewRoot
Let's try to create a custom keyword to find the grant parent node of the certain component in the component tree.
Create a new SearchKeywordResolver.
1
public class GrandParentKeywordResolver extends SearchKeywordResolver {
2
3
@Override
4
public boolean isResolverForKeyword(SearchExpressionContext searchExpressionContext, String keyword) {
5
return "grandParent".equals(keyword);
6
}
7
8
@Override
9
public void resolve(SearchKeywordContext searchKeywordContext, UIComponent current, String keyword) {
10
UIComponent parent = current.getParent();
11
if (parent != null) {
12
searchKeywordContext.invokeContextCallback(parent.getParent());
13
} else {
14
searchKeywordContext.setKeywordResolved(true);
15
}
16
}
17
}
Copied!
Register it via a @WebListener class.
1
@WebListener
2
public class WebInit implements ServletContextListener {
3
4
@Override
5
public void contextInitialized(ServletContextEvent sce) {
6
FacesContext.getCurrentInstance()
7
.getApplication()
8
.addSearchKeywordResolver(new GrandParentKeywordResolver());
9
10
}
11
}
Copied!
A simple facelets template.
1
<h:panelGroup id="panelgroup">
2
<h:form id="form">
3
<h:button id="button" outcome="foo2">Button foo</h:button>
4
<h:commandButton id="commandButton" action="#{backingBean.foo()}" value="invoke foo"/>
5
<h:outputText id="body" value="body"/>
6
</h:form>
7
</h:panelGroup>
Copied!
Get the grandParent id of the certain component at runtime.
1
public void foo() {
2
SearchExpressionContext searchContext = createSearchExpressionContext(context, context.getViewRoot());
3
4
context.getApplication()
5
.getSearchExpressionHandler()
6
.resolveComponent(
7
searchContext,
8
":form:@parent",
9
(c, target) -> out.print(":form:@parent -> "+target.getId()));
10
11
context.getApplication()
12
.getSearchExpressionHandler()
13
.resolveComponent(
14
searchContext,
15
":form:@grandParent",
16
(c, target) -> out.print(":form:@grandParent -> "+target.getId()));
17
}
Copied!
Grab the source codes from my GitHub account, and have a try.
Last modified 8mo ago
Copy link