Proxy4jdbc3  - The Proxy for JDBC 3

(Wait…. a home Page in English version is coming soon)

É um componente de software desenvolvido para interceptar o SQL executado por um aplicativo Java através das chamadas sobre a JDBC. Uma solução rápida e simples para quem deseja depurar, fazer logging  ou perfilar a execução do SQL sem ter que modificar a arquitetura da aplicação.

Para usá-lo primeiro são necessários apenas 4 passos:

1.        É necessário saber qual o componente provedor das conexões com os dados da sua aplicação, exemplo: Driver Manager,  DataSource,  algum Componente de Pooling, etc...,

2.        Conhecido o provedor, então deve se escolher o componente correspondente de Proxy.  Obs.: Você também pode estender ou criar seu componente customizado.

3.  Implementar o Proxy criando a solução vendor-especifc, i.e, especifica do seu SGBD. No pacote proxy4jdbc3.solutions.* você encontrará soluções-exemplo.

4.       Substitua a referência ao provedor de conexão pela referência ao Proxy.

 

Overview:

 

 class_diagram.jpg

 

Exemplo 1: 

        Cenário: Uma aplicação JDBC simples que faz consultas ao servidor de dados Oracle, criando as conexões a partir do DriverManager.

1.       Provedor de conexões:  DriverManager

2.       Proxy escolhido:  DriverProxy

3.       Solução Exemplo (Oracle) : Estenda o Proxy, implementando a referência ao OracleDriver.

package proxy4jdbc3.solutions;

 

import proxy4jdbc3.JDBCReporter;

import proxy4jdbc3.jdbc.DriverProxy;

 

public class OracleDriverProxy extends DriverProxy {

 

      public OracleDriverProxy() {// must have a default constructor

      }

 

      static {// must register the driver in DriverManager at load time

            register(new OracleDriverProxy());

      }

 

      @Override

      public String getDriverClassName() {

            return "oracle.jdbc.driver.OracleDriver";

      }

 

      public JDBCReporter getReporter() {{//A instância do JDBCReporter será responsável

//por invocar a resposta adequada da aplicação.

 

            return new JDBCReporter() {

                  public void reportUpdate(String sql) {

                        System.out.println("Oracle Server updating... " + sql);

                  }

 

                  public void reportExecute(String sql) {

                        System.out.println("Oracle Server Server executing... " + sql);

                  }

 

                  public void reportQuery(String sql) {

                        System.out.println("Oracle Server querying... " + sql);

                  }

 

            };

      }

}

 

1.        

2.        

3.        

4.       Substitua em sua aplicação a referência ao OracleDriver pela referência ao Proxy.  Abaixo segue um exemplo de uma aplicação JDBC simples, que consulta a data/hora no banco de dados.

 

public class MyApp{

      //Exemplo de uma

public static void main(String[] args) {

            try {

 

                  // Passo 1: Carregue o driver JDBC.

                  Class.forName("proxy4jdbc3.solutions.OracleDriverProxy");

                   

                  // Passo 2: Estabeleça a conexão

                  String url = "jdbc:oracle:thin:@localhost:1521:mybd";

                  Connection conn = DriverManager.getConnection(url,"user","passwd"); 

                  Statement s = conn.createStatement();

                  s.execute("select sysdate from dual"); //Imprime "Oracle Server querying... select sysdate from dual

 

              } catch (Exception e) {

                  System.err.println(e.getMessage());

             

      }

}

 

Exemplo 2 (Criando sua própria solução): 

Cenário: Uma aplicação WEB que possui a camada de persistência implementada usando Hibernate3, acessando servidor de dados MySql através de um Pool de conexões implementado pelo componente C3P0.

1.       Provedor de conexões: C3P0ConnectionProvider

2.       Proxy escolhido: Implementaremos nosso próprio: MyConnectionProxyProvider.

3.       Solução: Estenderemos o provedor, sobrescrevendo  os métodos de acesso a conexão e fazendo-os retornar wapper ConnectionProxy, que encapsulará a conexão original.

4.       Configuramos a camada de persistência para utilizar nosso proxy.

Este cenário é um pouco mais complexo, uma aplicação WEB geralmente não acessa diretamente as conexões, essas são providas por algum componente especial (como um DataSource) e gerenciadas por um Pool. No caso do hibernate existe uma interface chamada org.hibernate.connection.ConnectionProvider, que faz exatamente o que o nome diz, provê o acesso às conexões, você pode configurá-lo no arquivo hibernate.cfg.xml:

<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

      <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

      <property name="hibernate.connection.provider_class">br.com.myapp.MyConnectionProxyProvider</property>

               

Então está será a interface do proxy MyConnectionProxyProvider que iremos criar.  Por estarmos utilizado o C3P0 para gerenciar nossas conexões, faremos também com que a classe estenda a implementação org.hibernate.connection.C3P0ConnectionProvider já existente:

package br.com.myapp;

 

import java.sql.Connection;

import java.sql.SQLException;

 

import org.hibernate.connection.C3P0ConnectionProvider;

import org.hibernate.connection.ConnectionProvider;

import proxy4jdbc3.jdbc.ConnectionProxy;

 

public class MyConnectionProxyProvider extends C3P0ConnectionProvider

            implements ConnectionProvider {

 

      private JDBCReporter myJDBCReporter = new JDBCReporter(){

            public void reportQuery(String sql) {

                  //do some logging

            }

 

            public void reportExecute(String sql) {

                  //do some logging

            }

 

            public void reportUpdate(String sql) {

                  // do some logging

            }          

      };

 

@Override

      public Connection getConnection() throws SQLException {

            Connection c = super.getConnection();

 

//Encapsulando a conexão original num objeto ConnectionProxy

            if (!(c instanceof ConnectionProxy)) {

                  c = new ConnectionProxy(myJDBCReporter, c);

 

            }

            return c;

      }

 

}

Perceba que esta solução é independente do SGBD utilizado, visto que estamos encapsulando o acesso conexão numa camada onde a mesma já está instanciada.  A única restrição é que a classe provedora de conexão da sua aplicação, no caso  a C3P0ConnectionProvider, seja extensível, isto é, não pode ser uma classe final ou privada.

 

Considerações

O componente foi desenvolvido sobre a JDBC 3, e está ainda em fase de teste (beta).

Página principal: http://sourceforge.net/projects/proxy4jdbc3/