Dashboard > HOW-TOS > Home > Spring, OJB, and Struts. Version 2 with DAO.
HOW-TOS Log In   View a printable version of the current page.
Spring, OJB, and Struts. Version 2 with DAO.
Added by Jason McKerr, last edited by K Lars Lohn on Jul 26, 2005  (view change)
Labels: 
(None)

Part 1 Part 2 Part 3

OK, in the previous installment of Spring, Struts, and OJB we got things up and running, integrating OJB and Spring to use Declarative Transactions with OJB's PersistenceBroker engine. Good stuff, all in all. I promise, this article is much shorter. For people that don't want to read this whole thing, just download the second app, and read the INSTRUCTIONS FOR DAO/FACADE STRATEGY in the applicationContext.xml file.

Now we have a new application that enhances the first one somewhat by using a "true" Data Access Object pattern.

To get the app to run in tomcat:

  • Download it from here: here
  • unzip into your webapps directory and REMOVE THE WAR FROM THE WEBAPPS DIRECTORY
  • If you are starting the application from the command line, move the myusers/db folder to the directory from which you are starting tomcat (likely <tomcat-home>/bin).
  • Start Tomcat by going to <tomcat-root>/bin and running catalin.sh run or catalina.bat run.
  • With a browser go to http://localhost:8080/myusers

As with last time, out of sheer laziness, I have put Java source files in the same directories as class files, meaning that the source code is in WEB-INF/classes/.

The key to that application was simplicity. Because of that, I simplified the object model considerably. In that application, there was an Interface (UserDAO) and a single implementation class (UserDAOOjb). Using that system, you program to the interface UserDAO and activities are invoked on the UserDAOOjb. That means that I had actual OJB call in the implementing class. The model looks like UserDAO --> UserDAOOJBImpl. The problemn there is that you are now tied your data strategy (OJB) and your DAO implemtation class must have specific implementation knowledge. That sort of defeats the idea of a true Data Access Object. The new implementation will look like UserDAO --> UserDAOImpl --> UserDAOOJBImpl.

This implementation requires very little actual code.

  • Create the UserDAOImpl class:
    package org.appfuse.dao;
    
    import java.util.List;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.appfuse.model.User;
    
    public class UserDAOImpl implements UserDAO {
    	
      private static Log log = LogFactory.getLog(UserDAOImpl.class);
    	
      private UserDAO userDAO;
    	
      public void setUserDAO(UserDAO userDAO) {
        this.userDAO = userDAO;
      }
    
      public List getUsers() {
        return userDAO.getUsers();
      }
    
      public User getUser(Long userId) {
        User user = userDAO.getUser(userId);
    
        if (user == null) {
        log.warn("UserId '" + userId + "' not found in database.");
        }
        return user;
      }
    
      public void saveUser(User user) {
        userDAO.saveUser(user);
      }
    
      public void removeUser(Long userId) {
        userDAO.removeUser(userId);
      }
    }
  • Edit your applicationContext.xml file
    • Step 1: Add bean registration above for UserDAO with class as UserDAOOjbImpl
    • Step 2: Change your userManagerTarget class to UserDAOImpl.
    • Step 3: Add a property to userManagerTarget that assigns UserDAOOjbImpl to the userDAO property in the UserDAOImpl class:
      <bean id="userDAO" class="org.appfuse.dao.UserDAOOjbImpl"/>
      
      <bean id="userManagerTarget" class="org.appfuse.dao.UserDAOImpl">
        <property name="userDAO">
          <ref local="userDAO"/>
        </property>
      </bean>

That's it. That's all you have to do. Now let's walk through it. Your UserAction class calls userDAO:

...
private UserDAO mgr = null;

public void setUserManager(UserDAO userManager) {
  this.mgr = userManager;
}
...

public ActionForward list(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		
  request.setAttribute("users", mgr.getUsers());
  return mapping.findForward("list");
}

That in turn calls your userDAO interface:

...
public List getUsers();
...

Which in turns acts upon UserDAOImpl:

...
public List getUsers() {
  return userDAO.getUsers();
}
...

Finally, that calls the actual data-strategy implementation, UserDAOOJBImpl:

public List getUsers() {
  QueryByCriteria query = new QueryByCriteria(User.class);
  query.addOrderByAscending("lastName");
  query.addOrderByAscending("firstName");
  return (List) getPersistenceBrokerTemplate().getCollectionByQuery(query);
}

Let's sequence that out like in the first article:

  • In your web page you hit a user.do action (a link or form action)
  • Struts looks up the action in struts-config.xml
  • Struts knows now to delegate the action to Spring, and use Spring's config files applicationContext.xml and action-servlet.xml
  • Now Spring is basically looking at the action-servlet.xml file for an action that looks like /user.
  • Once Spring finds that action, it associates the action with a Class to use, UserAction.
  • Spring notices that there is a property that it needs to set in the UserAction class, and that the value of the property is the userManager bean that was registered in applicationContext.xml
  • It then looks in applicationContext.xml
  • It finds the userManager object, and understands that:
    • The transactionManager is org.springframework.orm.ojb.PersistenceBrokerTransactionManager
    • The target is an implementation class that implements the Interface that you are programming (org.appfuse.dao.UserDAOImpl) by referencing userManagerTarget.
    • The userManagerTarget, in turn, has a property defining the inteface that you program too, and what the data-strategy-specific implementation of interface is (UserDAOOJBImpl).
    • It checks the transactionAttributres to find out how to manage transactions for certain methods.
  • Now you can do actions in your Struts Action class that operate on the UserDAO interface which is an instance of UserDAOImpl.

Site powered by a free Open Source Project / Non-profit License (more) of Confluence - the Enterprise wiki.
Learn more or evaluate Confluence for your organisation.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.2.7 Build:#524 Jul 28, 2006) - Bug/feature request - Contact Administrators