2 Replies Latest reply on Jan 26, 2011 7:34 AM by donestebanc

    Error handling - conceptual question

    donestebanc

      Hi all,

       

      hopefully, my question fits in this forum.

       

      I found a lot of information about Converters and Validators and I think I understand the basic concept. But I don't know where/how to handle errors, occurring later in the JSF lifecycle? Imagine inserting a new user in a database. First passing Converters and Validators, to check that basic information and constraints like proper date values or reasonable age ranges are given. But where to check constraints which needs backend information like "no duplicate user name permitted".

       

      One place to detect this kind of error is the action method in the corresponding form bean. The action method calls a database service, which returns success or failure or throws an exception. It would not help anticipate this check in a validator. The check for the duplicate user must be in the same Transaction as the insert.

       

      I tried something like this in the action method:

       

          public String update() throws LoginNameExistsException {

              try {

                  DSServices.updateUser(currentUser);

              } catch (LoginNameExistsException e) {

                  FacesContext fc = FacesContext.getCurrentInstance();

                  fc.addMessage("password", new FacesMessage(FacesMessage.SEVERITY_ERROR, "short", "looooong"));

                  fc.validationFailed();

              }

              return null;

          }

       

      First of all, this does not work. I get this message in the log:

       

      INFO: WARNUNG: FacesMessage(s) wurde(n) in die Warteschlange gestellt, aber möglicherweise nicht angezeigt.

       

      Which means that the message is in the queue but not displayed.

       

      Client Code:

       

      <h:inputText id="name" label="Login-Name" value="#{adminUsersBean.currentUser.loginName}" />

                              <h:message for="name" styleClass="errorMessage" />

       

      Other messages from Validators are displayed correct.

       

      Second it just doesn't feel right manipulating messages in the action methods. But thats just a feeling.

       

      I don't know how to handle situations like this and I did not find information about this task, neither in my book nor on the web or the examples. Perhaps someone can point me to missing information.

       

      I'm aware, that this is not primary a RichFaces question, but I participate only in this forum. If someone could recommend an active forum about JSF2, it would be fine too.

       

      Thanks

      Don

        • 1. Error handling - conceptual question
          ilya40umov

          1) The best way to output a message is described below:

          - create field private UIComponent componentUI in your bean

          - bind one of your form components (a4j:commandButton, h:input etc) to this field

          - add h:message or rich:message for this component(But if you are going to use h:message you MUST re-render the parent element of h:message in order to show the message)

          - use the following approch in your bean:

          public void displayError(UIComponent component, String summary, String details) {

                  FacesContext facesContext = getFacesContext();

                  facesContext.addMessage(component.getClientId(facesContext),

                          new FacesMessage(FacesMessage.SEVERITY_ERROR, summary, details));

              }

          P.S. If your message is not shown add rich:messages on your page. It shows all the messages.

          2) I'm pretty sure that creating message in JSF bean is OK because actully if you have EJBs with all the logic inside your JSF beans only have to work like Controller/View. So their job is to show users results of their actions.

          • 2. Re: Error handling - conceptual question
            donestebanc

            Thanks a lot Ilya, this made things clear.

             

            Following a complete, very basic example as starting point for "very beginners" like me:

             

            Facelet

             

            <h:form>

               <h:inputText id ="alwaysWrong" binding="#{backing02.alwaysWrong}" />

               <h:message for="alwaysWrong" />

               <br />

               <h:commandButton value="Click me to see the error" action="#{backing02.consultBackendFake}"/>

            </h:form>

             

            Backing bean

             

            @ManagedBean

            @RequestScoped

            public class Backing02 implements Serializable {

             

                private static final long serialVersionUID = 1L;

             

                private HtmlInputText alwaysWrong;

             

                public String consultBackendFake() {

                    FacesContext facesContext = FacesContext.getCurrentInstance();

                    facesContext.addMessage(alwaysWrong.getClientId(facesContext),

                            new FacesMessage(FacesMessage.SEVERITY_ERROR,

                                    "Summary: I'm a fake",

                                    "Detailed: I'm a fake and I never succeed"));

                    return "failure";

                }

             

                public void setAlwaysWrong(HtmlInputText alwaysWrong) {

                    this.alwaysWrong = alwaysWrong;

                }

             

                public HtmlInputText getAlwaysWrong() {

                    return alwaysWrong;

                }

             

            }

             

            It's the most basic example I can come up with. As Ilya mentioned, using rich- and a4j-components offers more functionality.