0

I have a question according to <h:message for="" /> JSF object. I have a JSF 1.1 (yes, unfortunatelly) myFaces project. I've prepared a simple JSP file with label, inputText and message holder:

<h:form id="sacLinkForm">
    <cblFaces:outputLabel for="dedicatedCashAccountNumber"
        value="#{appBundle.KUSTA_DEDICATED_CASH_ACCOUNT_NUMBER}"/>
    <t:inputText id="dedicatedCashAccountNumber"
        value="#{createController.modelFE.sacLink.dedicatedCashAccountNumber}"/>
    <h:message id="dedicatedCashAccountNumberError"
        for="dedicatedCashAccountNumber" />
</h:form>

Also I've created simple validation method:

public static boolean validate(SACLink link) {
    boolean isError = false;
    FacesContext context = FacesContext.getCurrentInstance();
    FacesMessage message = new FacesMessage();
    message.setSeverity(FacesMessage.SEVERITY_ERROR);

    if (StringUtils.isEmpty(link.dedicatedCashAccountNumber)) {
        //MessageUtils.addErrorMessage("dedicatedCashAccountNumber", "Dedicated Cash Account Number is mandatory");
        message.setSummary("Field mandatory");
        message.setDetail("Dedicated Cash Account Number is mandatory");
        context.addMessage("sacLinkForm:dedicatedCashAccountNumber", message);
        isError = true;
    }
    return !isError;
}

My problem is with sacLinkForm:dedicatedCashAccountNumber because compiled JSP has generated id (f.e. _idJsp12:DynTab2:DynView2:tabK.....er:vKustaMa....Controller:sacLinkForm:dedicatedCashAccountNumber) and it probably causes that addMessage method doesn't correspond with h:message for=".." attribute.

So the message is not displayed correctly because java could not find correct h:message object. Is there any way how to set message to the correct h:message from Java? I assume that there is no way how to force 'constant' component ID in the JSF 1.1 pages.

Thank you.

Jiri Vlasimsky
  • 684
  • 6
  • 13

1 Answers1

4

You should not be manually performing validation in a JSF action method at all. You should utilize JSF builtin validation facilities. You should use a normal JSF Validator. Any ValidatorException which you throw from that will end up in the right message component.

Replace that validate() method by the following class:

public class AccountNumberValidator implements Validator {

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        if (StringUtils.isEmpty(value)) {
            FacesMessage message = new FacesMessage();
            message.setSeverity(FacesMessage.SEVERITY_ERROR);
            message.setSummary("Field mandatory");
            message.setDetail("Dedicated Cash Account Number is mandatory");
            throw new ValidatorException(message);
        }
    }

}

Register it in faces-config.xml as follows:

<validator>
     <validator-id>accountNumberValidator</validator-id>
     <validator-class>com.example.AccountNumberValidator</validator-class>
</validator>

Use it in the view as follows:

<t:inputText id="dedicatedCashAccountNumber"
    value="#{createController.modelFE.sacLink.dedicatedCashAccountNumber}"
    validator="accountNumberValidator" />

That's it. Note that the JSF action method won't be invoked if validation (or conversion) has failed. No need for nonsensicial isError clutter as well.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks for your response. I was also considering usage of dedicated validator for each rule. But I don't want to create new validator for every new validation rule. But you are right, this is definitely working and clean solution. But I am little bit afraid of some more complex validation rules like f.e. dependent form fields (like startDate > endDate; checkbox == checked then another field will be validated differently). But I can most of the cases validate them after in the controller with returning error message to error summary tab (not to field h:message) and block further progress. – Jiri Vlasimsky Mar 13 '13 at 20:36
  • 1
    Multi-field validation is explained in http://stackoverflow.com/questions/6282466/jsf2-0-doesnt-support-cross-field-validation-is-there-a-workaround/6282509#6282509 If you happen to use JSF2 or understand JSF2 source code, OmniFaces has several open source solutions, see "validators" section on the bottom of the left menu: http://showcase.omnifaces.org/ – BalusC Mar 13 '13 at 20:39