Return-Path: Delivered-To: apmail-jakarta-commons-dev-archive@www.apache.org Received: (qmail 42925 invoked from network); 3 Oct 2003 14:11:25 -0000 Received: from daedalus.apache.org (HELO mail.apache.org) (208.185.179.12) by minotaur-2.apache.org with SMTP; 3 Oct 2003 14:11:25 -0000 Received: (qmail 86955 invoked by uid 500); 3 Oct 2003 14:11:02 -0000 Delivered-To: apmail-jakarta-commons-dev-archive@jakarta.apache.org Received: (qmail 86858 invoked by uid 500); 3 Oct 2003 14:11:01 -0000 Mailing-List: contact commons-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Help: List-Post: List-Id: "Jakarta Commons Developers List" Reply-To: "Jakarta Commons Developers List" Delivered-To: mailing list commons-dev@jakarta.apache.org Received: (qmail 86786 invoked from network); 3 Oct 2003 14:11:01 -0000 Received: from unknown (HELO rwcrmhc13.comcast.net) (204.127.198.39) by daedalus.apache.org with SMTP; 3 Oct 2003 14:11:01 -0000 Received: from comcast.net (h-68-164-32-242.nycmny83.covad.net[68.164.32.242]) by comcast.net (rwcrmhc13) with SMTP id <2003100314110301500c744le> (Authid: hkrishnaswamy); Fri, 3 Oct 2003 14:11:03 +0000 Message-ID: <3F7D83D5.3020704@comcast.net> Date: Fri, 03 Oct 2003 10:12:37 -0400 From: Harish Krishnaswamy User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax) X-Accept-Language: en-us, en MIME-Version: 1.0 To: Jakarta Commons Developers List Subject: Re: [HiveMind] Question about DAO creation References: <16253.25308.261213.950333@lisa.zopyra.com> In-Reply-To: <16253.25308.261213.950333@lisa.zopyra.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N Here's what I have done in my project, I am using iBatisDB and I love it, I suppose you can do the same with JDBC too. I have a super DataAccessService... public class DataAccessServiceImpl implements DataAccessService, Initializable { // This will be a configuration provided in the module descriptor // In JDBC, this will probably be the JNDI path to the DataSource public void setResourcePath(String path) { _resourcePath = path; } // This is used to build the SqlMap, kind of registry for all sql statements. // In a plain JDBC env, this is probably where I would get the DataSource (from JNDI typically) and store it locally. public void initializeService(Object service) { try { Reader reader = Resources.getResourceAsReader(_resourcePath); _sqlMap = XmlSqlMapBuilder.buildSqlMap(reader); reader.close(); } catch (Exception ex) { throw new ApplicationRuntimeException("Error Initializing DAS :" + ex); } } // Generic statement executions public List getList(String statementName, Object parameterObject) throws DaoException { // executeQuery() } public Object getObject(String statementName, Object parameterObject) throws DaoException { // executeQuery() } public int update(String statementName, Object parameterObject) throws DaoException { // executeUpdate() } } And I have other DataAccess services compose the super DataAccessService which will be provided by HiveMind as specified in the module descriptor. For example... public class ClientDASImpl implements ClientDAS { private DataAccessService _das; public void setDataAccessService(DataAccessService das) { _das = das; } public List getClients() { List list = null; try { list = _das.getList("getClients", new Client()); } catch (DaoException e) { throw new ApplicationRuntimeException(e); } return list; } } And what I store in the Global is just the registry. That's one thing I noticed in your code, you seem to be building the registry eveytime a service is requested. Here my Global... public class Global { private Registry _registry; public Global() { ClassResolver resolver = new DefaultClassResolver(); RegistryBuilder builder = new RegistryBuilder(); builder.processModules(resolver); _registry = builder.constructRegistry(Locale.getDefault()); } public LookupService getLookupService() { return (LookupService) _registry.getService(ServiceTokens.LOOKUP, LookupService.class); } ... } I use DBCP for DB connection pooling, that way you externalize all the connection stuff out of the service. I hope this will be helpful. If you need more info, I will be glad to provide what ever I can. -Harish Bill Lear wrote: >I've been using hivemind to build a DAO factory. I think I may be >using this in a rather crude way that undoes some of the good hivemind >has done, so I thought I'd ask for some advice. I have a second question >regarding JDBC connections. > >First, in Tapestry, I store my DAO object in the Global class, but >I seem to have reverted to the singleton pattern instead of >doing things the hivemind way: > >public class Global { > private static DAO dao; > > private static Object daoMutex = new Object(); > > public DAO getDAO() throws DAOException { > synchronized (daoMutex) { > if (dao == null) { > dao = createDAO(); > } > } > return dao; > } > > private DAO createDAO() throws DAOException { > DAOFactory f = (DAOFactory) Services.getService(DAOFactory.class); > return f.createDAO(); > } >} > >Services is a wrapper around Hivemind that gets a service based on a >class name: > >public class Services { > public static Object getService(Class theClass) { > ClassResolver resolver = new DefaultClassResolver(); > RegistryBuilder builder = new RegistryBuilder(); > > builder.processModules(resolver); > > Registry registry = builder.constructRegistry(Locale.getDefault()); > > return registry.getService(theClass.getName(), theClass); > } >} > >My hivemodule looks like this: > > > interface="com.foobar.eci.dao.DAOFactory"> > > class="com.foobar.eci.dao.mysql.MySQLDAOFactory"> > > > value="org.gjt.mm.mysql.Driver"/> > > > > > > > > > >I'm not quite sure how to have hivemind construct both the Global >object and DAO object, and set the DAO object in the Global object. > > >Second question: I use a command pattern to separate the implementation of >different methods in the DAO class. So, if I have a DAO that looks like >this: > >public interface DAO { > Employee getEmployee(Integer employeeID) throws DAOException; > > Employee[] getEmployees(String sortColumn) throws DAOException; > > void insertEmployee(Employee employee) throws DAOException; >} > >I implement this with a class to expose this interface, and three >classes to implement each of the commands. Notice the MySQLDAO >class stores the JDBC connection object and passes it to each >of the command classes it constructs: > >public class MySQLDAO implements DAO { > void init(Connection connection) throws DAOException { > try { > getEmployee = new GetEmployee(connection); > getEmployees = new GetEmployees(connection); > insertEmployee = new InsertEmployee(connection); > } catch (SQLException sex) { > LOG.error(sex.toString()); > throw new DAOException(sex.toString()); > } > } > > private GetEmployee getEmployee; > > public Employee getEmployee(Integer employeeID) throws DAOException { > return getEmployee.execute(employeeID); > } > > private GetEmployees getEmployees; > > public Employee[] getEmployees(String sortColumn) throws DAOException { > return getEmployees.execute(sortColumn); > } > > private InsertEmployee insertEmployee; > > public void insertEmployee(Employee employee) throws DAOException { > insertEmployee.execute(employee); > } >} > >The factory is what I have Hivemind creating: > >public class MySQLDAOFactory implements DAOFactory { > private String name; > private String protocol; > private String driver; > private String host; > private String port; > private String user; > private String password; > > public DAO createDAO() throws DAOException { > MySQLDAO dao = new MySQLDAO(); > > try { > String connURL = "jdbc:" + protocol + "://"; > > if (host.length() == 0) { > connURL += name; > } else { > connURL += host + ":" + port + "/" + name; > } > > // This ensures no timeouts for MySQL after default idle period > connURL += "?autoReconnect=true"; > > Class.forName(driver); > dao.init(DriverManager.getConnection(connURL, user, password)); > } catch (SQLException sex) { > throw new DAOException(sex); > } catch (ClassNotFoundException ex) { > throw new DAOException(ex); > } > > return dao; > } > > // Get-Set methods for private variables elided ... >} > >So, what I'm wondering is: I have embedded a JDBC connection object in >the each of the three command objects. This seems too direct and >inflexible, but I don't know what other alternatives to use. Also, I >would like to be able to unit-test each of the three command classes, >but I would prefer to be able to use hivemind to construct the JDBC >connection for me, in which case, I might re-factor things in the >MySQLDAO class itself to also take advantage of hivemind to get the >connection object (but then, what about pooling? Can hivemind create >a JDBC connection? Is this desirable?). > >Finally, when testing the DAO, I need to be able to clear the database >before each test case method is run. I would prefer to use the same >connection that the DAO has, but exposing that in the DAO interface >seems a bit lame (Connection getConnection()) and too concrete. > >In any case, if anyone has comments or suggestions to share on managing >JDBC connections, I'd appreciate it. > > >Bill > >--------------------------------------------------------------------- >To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org >For additional commands, e-mail: commons-dev-help@jakarta.apache.org > > > > --------------------------------------------------------------------- To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org For additional commands, e-mail: commons-dev-help@jakarta.apache.org