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:
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);
}
};
}
}
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/