1 Reply Latest reply on Feb 21, 2011 7:47 PM by Tim Evers

    Exceptions, jUnit integration testing, and conventions

    Mason Harding Newbie

      Hi all.  This is more of a discussion than a technical question.  Lets say I have the following (simplified) AccountService bean (which handles stuff for an Account)




      @Name("accountService")
      @Stateless
      public class AccountService implements Account, Serializable {
           public AccountService(com.mydomain.persistence.Account account) {
                this.account = account;
           }
      
           public com.mydomain.Persistence.Account register() {
                if (this.account.getEmailAddress() == null) {
                     throw new IllegalArgumentException("account.emailAddress cannot be null");
                }
      
                      com.mydomain.Persistence.Account registeredAccount = persistAccount(this.account);
                   return registeredAccount;
              }
      }
      


      and an AccountServiceTest of



           @Test(expected = IllegalArgumentException.class)
           public void testRegisterAccountEmptyEmailAddress() {
                Lifecycle.beginCall();
                
                Account registerAccount = new Account();
                       registerAccount.setUserName("failAccount1");
                       registerAccount.setPasswordPlainText("failAccount1");
                       //registerAccount.setEmailAddress("failAccount1@mydomain.com");
                
                       AccountService as = new AccountService(registerAccount);
                   as.register();
                
                Lifecycle.endCall();
           }




      I like having my java code to be able to throw Exceptions if need be, and not have all of the FacesMessages stuff in it.  I think it makes testing very clear. 


      So here is the discussion part.  What is the best way to handle building the page bean?  Do I have my registration on the page be something like


      #{accountServiceUI.register(account)}



      that points to a page like



      @Name("accountServiceUI")
      public class AccountServiceUi {
           public boolean register(Account account) {
                if (account.getEmailAddress == null) {
                     FacesMessages.instance().addFromResourceBundleOrDefault(...);
                }
                AccountSerive as = new AccountService(account);
                as.register
           }
      }
      


      or add FacesMessage to my AccountService bean, and have AccountServiceUI just catch any exceptions so the end user only sees the FacesMessages?  Or would the standard just be to only report errors in AccountService to FacesMessages and not throw Exceptions?


      I realize any of those ways would work, but I would like to figure out the best practice.


      Thanks,
      Mason









        • 1. Re: Exceptions, jUnit integration testing, and conventions
          Tim Evers Master

          I'm probably not the best source of information about this but, from what I understand there is not necessarily a one size fits all approach to be had here.


          My understanding is that the exception approach is not as good performance wise and can sometimes make the code harder to call from other services. (Everyone who calls the method needs to know to catch the exception, or at least understand the implications of letting the exception bubble up)  But, there are certainly circumstances where throwing an exception is probably the right thing to do.


          The approach we have widely used in our app is that methods will return a list of Errors how the calling code handles those errors is entirely up to the caller. It could turn them into faces messages or generate a report or completely ignore them if it wants to. Behind the scenes however we have another layer of validation that happens at the persist/update phase that essentially calls these same methods and if the list of errors it not empty it will then throw an exception (A custom exception for our app).


          This exception can be caught and turned into faces messages in order to allow the user to go fix this problem.


          The obvious benefit of this approach is that you can build up a list of errors and tell the user all their problems at once rather then one at a time. (Although with enough effort the same could be done with an exception too).


          At the end of the day though, I'm not sure there is really a right strategy, rather there are many strategies all with benefits and flaws. Choosing the best one for you will depend highly on how your app is built my guess is.