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:

<module id="com.foobar.eci.dao" version="1.0.0">
    <service-point id="DAOFactory"
                   interface="com.foobar.eci.dao.DAOFactory">
        <invoke-factory service-id="hivemind.BuilderFactory">
            <construct
                class="com.foobar.eci.dao.mysql.MySQLDAOFactory">
                <set property="name" value="eci"/>
                <set property="protocol" value="mysql"/>
                <set property="driver"
                     value="org.gjt.mm.mysql.Driver"/>
                <set property="host" value="localhost"/>
                <set property="port" value="3906"/>
                <set property="user" value="bogon"/>
                <set property="password" value="foobar"/>
            </construct>
        </invoke-factory>
    </service-point>
</module>

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: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to