Mentawai Web Framework

Pool de Conexões

O Mentawai pode suportar qualquer pool de conexões através da interface org.mentawai.db.ConnectionHandler e já vem de fábrica com suporte a dois dos principais pool de conexões do mercado: Commons DBCP e C3P0. Além disso, através do filtro org.mentawai.filter.ConnectionFilter, as suas actions podem obter facilmente e sem esforço uma java.sql.Connection diretamente do input. Veja o exemplo da action abaixo:

public class HelloMyPool extends BaseAction {
	
    public String execute() throws Exception {
        
        Connection conn = (Connection) input.getValue("conn");
        PreparedStatement stmt = null;
        ResultSet rset = null;
        try {
            stmt = conn.prepareStatement("select username from profiles limit 1");
            rset = stmt.executeQuery();
            if (rset.next()) {
                output.setValue("username", rset.getString(1));
                return SUCCESS;
            }
        } catch(SQLException e) {
            throw new ActionException(e);
        } finally {
            try { if (rset != null) rset.close(); } catch(Exception e) { }
            try { if (stmt != null) stmt.close(); } catch(Exception e) { }
        }
        return ERROR;
    }
}    
        

Repare que não é necessário se preocupar em retornar a conexão ao pool pois o filtro se encarregará dessa tarefa mesmo que haja uma exception durante a execução da action. Vale notar também que o filtro org.mentawai.filter.ConnectionFilter implementa a interface org.mentawai.core.AfterConsequenceFilter de forma que a conexão só será retornada ao pool após a execução da consequência da action, ou seja, no caso de um forward a conexão continuará disponível durante o processamento da camada view (JSP, velocity, etc.).


Usando Jakarta Commons DBCP

O Tomcat já vem com o DBCP, portanto, se você estiver usando Tomcat, teoricamente não precisa baijar os jars do DBCP. Entretanto, se estiver usando algum outro container web ou mesmo se tiver problemas com o Tomcat, acesse http://jakarta.apache.org/commons/dbcp e baixe os jars. Coloque os jars do DBCP dentro do diretório /WEB-INF/lib de sua aplicação web.

A mesma coisa vale se você optar por usar o pool de conexão C3P0 através do C3P0ConnectionHandler. Acesse http://sourceforge.net/projects/c3p0 ae baixe os jars de C3P0.

Abaixo veremos como configurar o filtro ConnectionFilter dentro do ApplicationManager de sua aplicação:

public class ApplicationManager extends org.mentawai.core.ApplicationManager {
    
    private ConnectionHandler connHandler = null;
    
    public void init(Context application) {
    
        // assuming you have a mysql database with a "lohis" database with username "lohis" and password "lohis"
        this.connHandler = new DBCPConnectionHandler("com.mysql.jdbc.Driver", 
                                                                  "jdbc:mysql://localhost/lohis?autoReconnect=true", 
                                                                  "lohis", 
                                                                  "lohis");
    }
    
    public void loadAction() {
     
        // Java style
        addGlobalFilter(new ConnectionFilter(connHandler));
        
        // Ruby style
        filter(new ConnectionFilter(connHandler));
        
    }
}        
    

Note que estamos usando o driver JDBC Connector/J do MySQL (com.mysql.jdbc.Driver). Acesse o site para baixar a última versão do Connector/J e coloque os arquivos jar dentro do diretório /WEB-INF/lib da sua aplicação.

Repare também que o nosso ConnectionFilter é um filtro global, ou seja, ele será executado para todas as actions da sua aplicação (a não ser para aquelas que implementarem a interface GlobalFilterFree). Então isso significa que até aquelas actions que não precisam de uma conexão com o banco vão receber uma? Não, pois o ConnectionFilter, como todos os outros filtros do Mentawai, funcionam sob-demanda.


A interface ConnectionHandler

Para criar um filtro org.mentawai.filter.ConnectionFilter, você deve passar um org.mentawai.db.ConnectionHandler como argumento para o construtor do filtro. O ConnectionHandler é a abstração do Mentawai para todo e qualquer pool de conexões. Dessa maneira, o framework pode oferecer as principais implementações do mercado sem qualquer tipo de complicação para o usuário final. O código fonte da interface ConnectionHandler está abaixo:

package org.mentawai.db; // this class comes with mentawai

import java.sql.*;
        
public interface ConnectionHandler {

    public Connection getConnection() throws SQLException;
    public void release(Connection conn);

}        
        

O Mentawai vem com quatro abstrações de um pool de conexão:

  • DataSourceConnectionHandler: um pool através de javax.sql.DataSource

  • JNDIConnectionHandler: um pool através de um contexto JNDI

  • C3P0ConnectionHandler: pool de conexão C3P0

  • DBCPConnectoinHandler: pool de conexão Commons DBCP

Nede o impede também de implementar essa interface para criar ou usar o seu próprio pool de conexões.



Mais controle

É possível também acessar o BasicDataSource do DBCP para configurar o pool de conexão. Como você faria isso se a sua configuração fosse em XML?


public class ApplicationManager extends org.mentawai.core.ApplicationManager {
    
    private ConnectionHandler connHandler = null;
    
    public void init(Context application) {
    
        // assuming you have a mysql database with a "lohis" database with username "lohis" and password "lohis"
        this.connHandler = new DBCPConnectionHandler("com.mysql.jdbc.Driver", 
                                                                  "jdbc:mysql://localhost/lohis?autoReconnect=true", 
                                                                  "lohis", 
                                                                  "lohis");
                                                                  
        // access the org.apache.commons.dbcp.BasicDataSource                                                                  
        BasicDataSource ds = (BasicDataSource) ((DBCPConnectionHandler) connHandler).getBasicDataSource();
        ds.setInitialSize(5);
        ds.setMaxIdle(5);
        ds.setMaxActive(20);                                                                  
                                                                  
    }
    
    public void loadAction() {
     
        // Java style
        addGlobalFilter(new ConnectionFilter(connHandler));
        
        // Ruby style
        filter(new ConnectionFilter(connHandler));
        
    }
}