One option is to use "service" objects that sit between the DAOs and the
Actions. Following your example, one service class might look something like
this:

public class WidgetService {
        public void delete(int id) {
                WidgetDAO w = new WidgetDAO();
                try {
                        // start transaction
                        w.delete(id);
                        // deletes on other related tables could go here
                        // commit transaction
                } catch (Exception e) {
                        // rollback transaction
                }
        }
}

The action class would never access DAO classes directly, but would always
use service classes. This allows your action classes to remain relatively
simple and uncluttered.

execute(...) {
     WidgetService.delete(widgetId);
}

Your business rules would be implemented in WidgetService.delete(). You may
have to pass in additional parameters in order for your business rules to be
executed.

We typically have one service object per dao object.


-----Original Message-----
From: Paul Barry [mailto:[EMAIL PROTECTED] 
Sent: Thursday, April 15, 2004 11:13 AM
To: [EMAIL PROTECTED]
Subject: Struts, Business Logic, DAOs

I have a question about business logic.  The best way I can think to 
explain this is with an example.  I know this is kind of long, but I am 
trying to keep this as simple as possible while still being able to 
illustrate the point.  Let's say I have Users and Widgets.  I would have 
Business Objects for each one, something like this:

public User {
   public int getId();
   public boolean isAdmin();
}

public Widget {
   public int getId();
   public User getCreator();
}

Now assume I am using a DAO like this:

public WidgetDAO {
   public void delete(int id);
}

Assume the implementation of this DAO would delete a row from the widget 
table in the database.  So using struts I would have an action with a 
method like this:

execute(...) {
     WidgetDAO.delete(widgetId);
}

Assume the widgetId came from an ActionForm, the details are irrelevant. 
  The point is this would all work fine, you could call the action with 
a URL like /deleteWidget.do?widgetId=4 and it would delete widget 4. 
Also, assume there is other logic already handling logging in the user 
so there is a UserBO object in a session attribute, which is used to 
populate the creator property of the Widget.

But now let's say I have 2 business rules:

1.  users that are admins can delete any widget
2.  non-admin users can only delete widgets they created

So specifically from the objects above, you can delete a widget if 
user.isAdmin() returns true or widget.getCreator().getId() == 
user.getId().  The question is where should this kind of logic go?

You could get away with putting it in the action, but in a real world 
application this type of logic would be much more complicated and 
probably get re-used across different actions.  The Struts guidelines 
even say this:

"Rather than creating overly complex Action classes, it is generally a 
good practice to move most of the persistence, and "business logic" to a 
separate application layer. When an Action class becomes lengthy and 
procedural, it may be a good time to refactor your application 
architecture and move some of this logic to another conceptual layer; 
otherwise, you may be left with an inflexible application which can only 
be accessed in a web-application environment."

http://jakarta.apache.org/struts/userGuide/building_controller.html#action_c
lasses

I doesn't seem like this logic belongs in the DAO either, because if you 
  don't want that kind of logic mixed in with code to get the data out 
of the database.  Does it belong in the business objects, maybe by 
expanding the Widget object like this?

public Widget {
   public int getId();
   public User getCreator();
   public boolean canDelete(UserBO);
}

And then canDelete would in turn call a DAO to check that?  Or would a 
separate layer be better, like this:

public WidgetLogic {
     public boolean canDeleteWidget(User, Widget);
}


Are there any best practices or sample applications that you know of 
that have a good example of a business logic layer?











---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to