ひとつの解決策を考えます。beforePhase メソッド内でPhaseListener
検索する new をPhaseEvent
追加して、次のように記述できます。PhaseId = RENDER_RESPONSE
public class MyPhaseListener implements PhaseListener {
private void findKeyValuePairInTree(UIComponent root,
Map<String, String> map) {
if (root instanceof HtmlOutputLabel) {
map.put(((HtmlOutputLabel) root).getFor(),
((HtmlOutputLabel) root).getValue());
}
if (root.getChilder() != null && !root.getChildren().isEmpty()) {
for (UIComponent child : root.getChilder()) {
findKeyValuePairInTree(child, map);
}
}
private HashMap<String, String> idToLabelMap= new HashMap<String,String>();
public void beforePhase(PhaseEvent event) {
if (event.getPhaseId().equals(PhaseId.RENDER_RESPONSE) {
findKeyValuePairInTree(FacesContext.getCurrentInstance().getViewRoot(),
idToLabelMap);
// after above function finished execution in idToLabelMap will be all
// pairs of component ID used in standard FacesMessage as key
// and HtmlOutputLabel value attr used as value
Set<String> keySet = idToLabelMap.keySet();
for(String key : keySet) {
Iterator messages = FacesContext.getCurrentInstance().getMessages(key);
while (iterator.hasNext) {
FacesMessage msg = (FacesMessage) iterator.next();
// now replace all occurences of clientId with label value from map
msg.setSummary(msg.getSummary().replaceAll(key, idToLabelMap.get(key)));
msg.setDetails(msg.getDetails().replaceAll(key, idToLabelMap.get(key)));
}
}
FacesContext.getCurrentInstance().getMessages();
}
}
...
}
このメソッドの後に来るレンダー フェーズでは、すべてのメッセージがラベル値でFacesContext.getCurrentInstance().getMessages()
変更されclientId
ます。検証フェーズはレンダー フェーズの前にあるため、すべての検証が成功または失敗します。検証からのメッセージはもうありません。
唯一の問題は、インスタンスのfor
属性でHtmlOutputLabel
同じ ID を 2 回以上使用する場合です。これは、異なるフォームで同じ ID がコンポーネントに使用される可能性があるためです。次に、for
attr 内部<h:outputLabel>
でより洗練された ID を使用できます。たとえば、フォーム ID などで手がかりを付けることができます。