Question

I have a question in handling the "business validation" done on the service layer. The code belows shows a typical account fund transfer example, which validates for sufficient fund, transfer amount is lesser than defined limit.

In this example, the caller have to handle and catch the exception defined in the Action class and used the corresponding ActionError to display the error message.

It is a "must" to use exceptions for all business validation?

If I decide not to use exception for this, I will have to defined the corresponding ActionError in the business layer(which violates the coupling / cohesion) rule in a certain sense.

How should one handle the message propagating by service layer back to the Action classes?

public void transfer(String fromAccount, String toAccount, double amount) throws InsufficientFundsException, TransferLimitException, FactoryException { 
    try { 
        Account from = getAccountHome().findByPrimaryKey( 
new AccountKey(fromAccount)); 
        Account to = getAccountHome().findByPrimaryKey( 
new AccountKey(toAccount)); 
        if (from.getBalance() < amount) 
            throw new InsufficientFundsException(); // Add action errors

        if (from.getTransferLimit() > amount) 
            throw new TransferLimitException();  // Add action errors
        to.deposit(amount); 
        from.withdraw(amount); 
    } catch (Exception e) { 
        throw new FactoryException( 
"cannot perform transfer. Nested exception is " + e); 
    } 
}
Was it helpful?

Solution

Your business should be handled in the Model and any problems encountered in your business logic should be propagated to the caller, which in this case is Struts Action classes.

But you do not want to couple your Struts classes (Action, ActionForm, ActionError, ActionMessage etc) with the Model, so you basically have two ways of notifying the caller of any problems:

  • return some error codes that the caller can check;
  • throw some exceptions that the caller can catch.

I prefer using exceptions because they can be thrown to the top layers from anywhere inside the business layer no matter how deep in the execution chain. This keeps the business code clean as you don't have to bubble up error codes as it would have been the case with the first approach.

The exceptions will then be caught by the Action class who will transform them into ActionError objects to be shown in the View. Just make sure you don't overdo it and end up throwing the kitchen sink or your Action classes will become crowded with excessive try-catch blocks. Additionally you could let the exceptions propagate and create an exception handler of some sort that catches all exceptions thrown from below and redirects to appropriate Views based on the exception type.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top