You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Michael Gerdau <mi...@cth.de> on 2001/01/03 14:42:07 UTC

Generic design for Business Logic Beanies (long)

Hi struts users !

As announced here comes a more detailed outline of how I think one could
have a generalized data interface.

The code provided should be enough to get the general idea.


Generic Entity class
====================
package foo.bar.datamodel;

public class MyEntity implements java.io.serializable
{
    private <type1> __data1;
    public <type_1> getData_1() {return __data1;}
    public void setData_1(<type_1> v) {__data1 = v;}

    private <type2> __data2;
    public <type_2> getData_2() {return __data2;}
    public void setData_2(<type_2> v) {__data2 = v;}

... (etc.)
}


Generic interfaces for generic Retriever classes
================================================
package foo.bar.base;

public interface RetrieveSingle
{
    public java.io.serializable select(java.sql.Connection connection);
    public java.io.serializable select(java.sql.Connection connection,
SqlQuery sqlQuery);
}
-----------------------
package foo.bar.base;

public interface RetrieveMany
{
    public java.util.List selectMany(java.sql.Connection connection);
    public java.util.List selectMany(java.sql.Connection connection,
SqlQuery sqlQuery);
}


Generic connection helper class
===============================
package foo.bar.base;

import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.Context;

public class MyConnection
{
    private DataSource __dataSource = null;
    private InitialContext __initialContext = null;
    private Connection __connection = null;

    //have to check if synchronized is necessary
    synchronized private Context getInitialContext() throws NamingException
    {
	if (null==__initialContext) 
	{
	    __initialContext = new InitialContext();
	}
	return __initialContext;
    }

    public Connection getConnection(String szPool)
    {
	if (__connection == null) 
	{
	    if (__dataSource == null) 
	    {
		try
		{
		    __dataSource = (DataSource)
getInitialContext().lookup(null==szPool?"foo.bar.genericpool":szPool);
		}
		catch(NamingException e)
		{
		    // add more errorlogging
		    e.printStackTrace();
		}
	    }
	    try
	    {
		__connection = __dataSource.getConnection();
	    }
	    catch(SQLException e)
	    {
		// add more errorlogging
		e.printStackTrace();
	    }
	}
	return __connection;
    }

    public void closeConnection()
    {
	if (__connection != null) 
	{
	    try
	    {
		__connection.close();
		__connection = null;
	    }
	    catch(SQLException e)
	    {
		// add more errorlogging
		e.printStackTrace();
	    }
	}
    }
}


Generic Retriever class
=======================
package foo.bar.datamodel;

public class MyRetriever implements RetrieveSingle, RetrieveMany
{
    private final static String __szSqlStmt = <some SQL query>
    // e.g. "SELECT a.field1 as field_1, a.field2 as field_2 ... a.fieldn as
field_n FROM table1 a";

    public MyEntity select(java.sql.Connection connection)
    {
	return select(connection, null);
    }

    public IfinEntity select(java.sql.Connection connection, SqlQuery
sqlQuery)
    {
	MyEntity result = new MyEntity();
	String szQuery;
	if (sqlQuery != null)
	{
	    SqlQueryBuilder sqlBuilder = new SqlQueryBuilder();
	    szQuery = sqlBuilder.buildSqlString(__szSqlStmt, sqlQuery);
	}
	else
	{
	    szQuery = __szSqlStmt;
	}
	Statement stmt = null;
	ResultSet resultSet = null;
	try
	{
	    stmt = connection.createStatement();
	    resultSet = stmt.executeQuery(szQuery);
	    if (resultSet.next())
	    {
		result.setData_1(resultSet.get<type_1>("field_1"));
		result.setData_2(resultSet.get<type_2>("field_2"));
		...
		result.setData_n(resultSet.get<type_n>("field_n"));
	    }
	    resultSet.close();
	    stmt.close();
	}
	catch(SQLException e)
	{
	    // add more errorlogging
	    e.printStackTrace();
	    return null;
	}
	return result;
    }

    public java.util.List selectMany(java.sql.Connection connection)
    {
	return selectMany(connection, null);
    }

    public java.util.List selectMany(java.sql.Connection connection,
SqlQuery sqlQuery)
    {
	java.util.ArrayList result = new java.util.ArrayList();
	String szQuery;
	if (sqlQuery != null)
	{
	    SqlQueryBuilder sqlBuilder = new SqlQueryBuilder();
	    szQuery = sqlBuilder.buildSqlString(__szSqlStmt, sqlQuery);
	}
	else 
	{
	    szQuery = __szSqlStmt;
	}
	Statement stmt = null;
	ResultSet resultSet = null;
	try
	{
	    stmt = connection.createStatement();
	    resultSet = stmt.executeQuery(szQuery);
	    while (resultSet.next()) 
	    {
		MyEntity result = new MyEntity();
		result.setData_1(resultSet.get<type_1>("field_1"));
		result.setData_2(resultSet.get<type_2>("field_2"));
		...
		result.setData_n(resultSet.get<type_n>("field_n"));
		result.add(result);
	    }
	    resultSet.close();
	    stmt.close();
	}
	catch(SQLException e)
	{
	    // add more errorlogging
	    e.printStackTrace();
	    return null;
	}
	return result;
    }
}


Note: you don't have to implement both RetrieveSingle and RetrieveMany
if you need only one of these.

Note2: the above class does utilizes two helperclasses SqlQuery and
SqlQueryBuilder. The whole purpose of these is to customize the SqlStmt
which is part of the Retriever class at runtime. To achieve this SqlQuery
has the 5 Strings __szSelect, __szFrom, __szWhere, __szGroupBy, __szOrderBy.
SqlQueryBuilder merges a SqlQuery with the __szSqlStmt from the Retriever.
I will check with the original author and ask for permission to publish the
code (of course such code could be newly written if need be).



Outline for Context Helper class
================================
package foo.bar.base;

import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class MyBaseController
{
    public Context getContext() throws NamingException
    {
        Hashtable env = new Hashtable();
        env.put(Context.PROVIDER_URL, <some PROVIDER_URL>);
        env.put(Context.INITIAL_CONTEXT_FACTORY, <some
INITIAL_CONTEXT_FACTORY>);
        env.put(Context.SECURITY_PRINCIPAL, <some SECURITY_PRINCIPAL>);
        env.put(Context.SECURITY_CREDENTIALS, <some SECURITY_CREDENTIALS>);
        return (new InitialContext(env));
    }
}



Rough outline of a generic controller class
===========================================
public class MyController extends MyBaseController
{
    public java.util.List get<dataobject_1>(...)
    {
	// retrieve all data needed to define the actual query from
parameters provided
        java.util.List list = null;
        try
        {
            Context ctx = getContext();
            MyEJBHome ejbHome = (MyEJBHome) ctx.lookup("foo.bar.MyEJB");
            MyEJB myEJB = ejbHome.create();
            list = (java.util.List) myEJB.get<dataobject_1>(...);
        }
        catch(NamingException ex)
        {
            ex.printStackTrace();
        }
        catch(RemoteException ex)
        {
            ex.printStackTrace();
        }
        catch(CreateException ex)
        {
            ex.printStackTrace();
        }
        return list;
    }   // end get<dataobject_1>(...)

    // add more "finder" as needed

}

The above code assumes we have an working EJB.


I think that's it. I have hacked together the above. If there is anything
missing or unclear feel free to ask. And of course if there are weak spots
don't hesitate to point them out.

For completeness I'd like to add that the above had been developed together
with my collegue Andre Wittenburg.

Best,
Michael