I found a solution which does not require to modify existing JSF code.
- make my component renderer extend Tomahawk's
HtmlMessagesRenderer
, which is capable of use a component label instead of its id
- use
HtmlMessagesRenderer#findInputId
to retrieve the Id of the component with messages
- use
HtmlMessagesRenderer#findInputLabel
to retrieve the Label of the component with messages
- replace component Id with component Label in the message.
Below is an excerpt from the code of my component Render encodeBegin
method, in which I made two separated loops, the first for component messages the other for global messages.
Note that FacesContext#getClientIdsWithMessages
returns also null
, which is considered the clientId for global messages.
Note that, because the component itself manages to retrieve and use the component label, if exists; this solution it only need to place a <myCustomMessages />
tag in JSF page code.
public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
// ....
// replace id with label in messages for components
Iterator<String> clientIdsWithMessages=context.getClientIdsWithMessages();
while(clientIdsWithMessages.hasNext()){
String clientIdWithMessages=clientIdsWithMessages.next();
if(clientIdWithMessages!=null){
Iterator<FacesMessage> componentMessages=context.getMessages(clientIdWithMessages);
while(componentMessages.hasNext()){
String stringMessage=componentMessages.next().getDetail();
try{
String inputId =findInputId(context, clientIdWithMessages);
String inputLabel = findInputLabel(context, clientIdWithMessages);
if(inputId!=null && inputLabel!=null)
stringMessage=stringMessage.replace(inputId, inputLabel);
} catch(Exception e){
// do nothing in this catch, just let the message be rendered with the componentId instead of a label }
msgBuilder.append(stringMessage);
msgBuilder.append("<br />");
}
}
}
// process global messages
Iterator<FacesMessage> globalMessages=context.getMessages(null);
while(globalMessages.hasNext()){
FacesMessage message=globalMessages.next();
msgBuilder.append(message.getDetail());
msgBuilder.append("<br />");
}
// ...
Here is a reference to HtmlMessagesRenderer#findInputLabel
source code, to take a look on how it works.