Integração sem alteração da
aplicação
Este exemplo exibe a solução proposta para o problema de integrar fontes de dados sem alteração nem
das fontes de dados nem da aplicação cliente, conforme descreve o
modelo estendido de solução.
Os tópicos abaixo exibem o cenário utilizado para a demonstração desta
funcionalidade.
Fontes
de dados de
teste
O exemplo exibe a integração de duas fontes de dados
heterogêneas: uma fonte
de
dados relacional (uma base de dados HSQLDB) e um arquivo texto (um
arquivo CSV), cujos esquemas e registros são os seguintes:
HSQLDB
CREATE TABLE CLIENTES(
CODCLIENTE INTEGER NOT NULL PRIMARY KEY,
NOME VARCHAR(20) NOT NULL,
SOBRENOME VARCHAR(20) NOT NULL)
)
Fig.
1 - Registros de
teste
Arquivo CSV
Arquivo
depto.csv,
com os valores separados por vírgula, sendo que os valores em
cada linha correspondem às seguintes colunas: CODDEPTO, NOMEDEPTO,
CODCURSO, NOMECURSO, CODINSTRUTOR, NOMEINSTRUTOR, CELULARINSTRUTOR.
O conteúdo do arquivo .csv de teste é o seguinte:
1,INF-UFG,1,Engenharia de software,1,Fabio Lucena,8410-1010
1,INF-UFG,2,Banco de Dados,2,Juliano Oliveira,x
1,INF-UFG,1,Engenharia de software,3,Juliano Oliveira,x
2,INF-Alfa,3,Banco de Dados,4,Rogerio Arantes Gaioso,9956-8989
1,INF-UFG,4,Introdução a Java,1,Fabio Lucena,8410-1010
Arquivos
de
configuração
O arquivo
integrate-datasources.xml
recebeu a seguinte configuração:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<datasource id="mysql" type="jdbc">
<wrapper>br.ufg.integrate.wrapper.WrapperJDBC</wrapper>
<lookup>br.ufg.integrate.lookup.LookupJDBC</lookup>
<typeConfFile>conf/HSQLDBTypeConf.xml</typeConfFile>
<typeConfClass>br.ufg.integrate.xml.type.TypeJDBCConf</typeConfClass>
<schema>PUBLIC</schema>
<jdbc-driver>org.hsqldb.jdbcDriver</jdbc-driver>
<url>jdbc:hsqldb:file:testFiles/db-hsqldb/dep</url>
<user>sa</user>
<password></password>
</datasource>
<datasource id="csv" type="csv">
<wrapper>br.ufg.integrate.wrapper.WrapperCSV</wrapper>
<lookup>br.ufg.integrate.lookup.LookupCSV</lookup>
<typeConfFile>conf/CsvJdbcTypeConf.xml</typeConfFile>
<typeConfClass>br.ufg.integrate.xml.type.TypeCSVCConf</typeConfClass>
<schema>depto</schema>
<jdbc-driver>br.ufg.integrate.wrapper.csv.CsvDriver</jdbc-driver>
<url>jdbc:integrate:csv?testFiles/db-csv/CsvDmdExample.xml</url>
<user></user>
<password></password>
</datasource>
</datasources>
Observe os identificadores utilizados. Aqui que se configuram os
valores reais de conexão (
driver,
URL, usuário, senha), além da classe que responsáveis pelos serviços
de
lookup
e de tradutor. Repare também na URL de conexão da fonte de dados do
arquivo CSV, que utiliza o
driver
JDBC para arquivos CSV.
Foram configuradas diversas integrações possíveis, definidas no arquivo
integration.xml,
exibido abaixo:
<?xml version="1.0" encoding="UTF-8"?>
<integrations>
<integration id="all2hsqldb">
<source>hsqldb</source>
<target>hsqldb</target>
<target>csv</target>
</integration>
<integration id="csv2hsqldb">
<source>hsqldb</source>
<target>csv</target>
</integration>
<integration id="hsqldb2csv">
<source>csv</source>
<target>hsqldb</target>
</integration>
</integrations>
Repare nas
tags
<source> e <target>, que
utilizam os identificadores definidos no arquivo
integrate-datasources.xml.
A única alteração relevantes no arquivo
integrate-config.xml
é a informação da classe que implementa a interface Mediator (ver
próximo tópico).
Mediador
de testes
Para a execução dos testes, foi necessária a confecção de um mediador,
através da implementação da interface Mediator. Para facilitar o
desenvolvimento, foi implementada uma classe sem o emprego das técnicas
de integração, como combinação de esquemas ou ontologias. O Mediador
criado apenas mantém uma tabela relacional que faz o mapeamento
um-para-um de cada sentença SQL necessária para o funcionamento da
aplicação cliente, relacionada
também com o identificador de cada
fonte de dados definido no Integrate. Ou seja, para ser funcional, esta
tabela deve ser alimentada antes com cada sentença SQL original e todas
as subconsultas para as demais fontes de dados que se deseja integrar.
O
código criado também não se preocupa com a geração de esquemas
integrados, funções estas que exigem um maior conhecimento semântico
embutido, o que está fora do escopo do Integrate. Desta maneira, o
código criado não demonstra as funções de
lookup.
Para
executar a integração dos ResultSet’s obtidos, o mediador mantém uma
fonte de dados interna com o mesmo esquema da fonte de dados original
da aplicação cliente. Para cada ResultSet recebido, o Mediador faz as
devidas conversões (sem nenhum conhecimento semântico), inserindo os
valores nas colunas desta fonte de dados interna.
Finalmente, o
Mediador executa a sentença enviada originalmente nesta fonte de dados
temporária e o ResultSet gerado é retornado ao Controlador.
O código-fonte deste Mediador está disponível para consulta
aqui.
Aplicação
cliente
A aplicação cliente de teste (disponível
aqui) foi
construída para manipular especificamente a fonte de dados HSQLDB.
Neste
código, após obter a conexão com a fonte de dados, a aplicação executa
uma consulta SQL específica do esquema (SELECT CODCLIENTE,
NOME, SOBRENOME FROM CLIENTES). Por ser uma aplicação
específica, a manipulação do ResultSet trata as duas colunas
originalmente esperadas, e a linha 12 imprime as colunas 2 e 3
separadas por um espaço em branco.
A obtenção dos parâmetros de conexão
necessários para se obter uma conexão JDBC se dá através de um
arquivo de propriedades externo à aplicação, conforme boas práticas de
programação. Desta maneira, a URL definida neste arquivo de parâmetros
é que será alterada, ou seja, sem alterar o código-fonte da aplicação.
Para esta aplicação, os parâmetros originais definidos neste arquivo
são os seguintes:
driver=org.hsqldb.jdbcDriver
url=jdbc:hsqldb:file:testFiles/db-hsqldb/dep
user=sa
password=
Resultados
gerados
Com a configuração original, o funcionamento da aplicação é o
esperado, e são retornados os registros exibidos na
figura 1 acima. A
aplicação imprime na saída padrão apenas os valores das colunas NOME e
SOBRENOME separados por espaço, ou seja:
ROGERIO ARANTES
JOSE MAURO
JOAO SILVA
Se a configuração do arquivo de propriedades for alterada para
driver=br.ufg.integrate.jdbc.DriverImpl <<< driver do Interceptador
url=jdbc:jdbc:integrate:csv2hsqldb <<< URL usando a integração
user=
<<< sem senha de conexão
password=
Ao executar novamente a aplicação, ou seja, sem alteração, serão
exibidos os registros do arquivo CSV:
Fabio Lucena
Juliano Oliveira
Juliano Oliveira
Rogerio Arantes Gaioso
Fabio Lucena
Como
pode ser percebido, apesar da aplicação originalmente imprimir as
colunas 2 e 3 do ResultSet, os registros impressos correspondem a
apenas à sexta coluna de valores do arquivo CSV. Vale lembrar que quem
providencia esta integração é o mediador, que conhece os esquemas
envolvidos e tem conhecimento semântico para esta função.
Para um novo teste, é feita outra alteração no arquivo de propriedades
de conexão:
driver=br.ufg.integrate.jdbc.DriverImpl
url=jdbc:jdbc:integrate:all2hsqldb <<< usando outra integração
user=
password=
Com
esta configuração, a aplicação ao ser executada faz com que o Integrate
integre os dois ResultSet's gerados em um único resultado, e
os
valores impressos são:
ROGERIO ARANTES
JOSE MAURO
JOAO SILVA
Fabio Lucena
Juliano Oliveira
Juliano Oliveira
Rogerio Arantes Gaioso
Fabio Lucena
Códigos para download
A relação abaixo contém pequenas aplicações de teste das quais foram
retirados trechos de código para exemplificar alguns tópicos deste
manual, e estão disponíveis para download.
ClientHSQLDB |
Aplicação cliente criada especificamente para acessar a fonte de dados HSQLDB de exemplo |
Mediador |
Mediador fictício criado para a execução dos testes de integração |
TestLookup1 |
Testa o lookup obtendo os esquemas em memória. Um loop varre a coleção de esquemas configurados no
arquivo 'integrate-datasources.xml' e imprime os ID's. |
TestLookup2 |
Imprime o esquema de uma única fonte de dados configurada no arquivo 'integrate-datasources.xml'. |
TestLookup3 |
Testa o lookup obtendo os esquemas em memória. Um loop varre a coleção de esquemas configurados no
arquivo 'integrate-datasources.xml' e imprime a relação de tabelas de cada fonte de dados, através
da referência aos objetos do tipo DatabaseMetaData. |
TestLookup4 |
Testa o lookup, imprimindo a relação de tabelas de uma única fonte de
dados configurada no arquivo 'integrate-datasources.xml', através da referência ao
objeto do tipo DatabaseMetaData. |
TestLookup5 |
Testa o lookup. Um loop varre a coleção de esquemas configurados
no arquivo 'integrate-datasources.xml' e mostra os esquemas das fontes de
dados em arquivo formatado em XML Schema, através da chamada ao método
saveSchemasToXMLFile(). O nome do arquivo deve ser
passado como argumento na linha de comando. |
TestParams1 |
Imprime os parâmetros configurados no arquivo 'integrate-config.xml'. |
TestParams2 |
Imprime o valor de um dos parâmetros configurados no arquivo 'integrate-config.xml'. |
TestValidate |
Arquivo de exemplo utilizado para validar o arquivo
'integrate-datasources.xml'. O código pode ser alterado para validar
qualquer outro arquivo XML, bastando o arquivo XSD que valide o XML
desejado. |
TestWrapper1 |
Simula um mediador
que testa a manipulação de registros obtidos pelos wrappers, manipulando diretamente os ResultSets.
As consultas são passadas através de um arquivo validado pelo query.xsd. No
final, é impresso o tempo total com as consultas. |
TestWrapper2 |
Simula um mediator que envia uma consulta SQL para
uma fonte de dados específica, definida no arquivo
'integrate-datasources.xml'. No final, é impresso o tempo
total com a consulta. |
TestWrapper3 |
Simula um mediator que envia uma coleção de consultas SQL para uma coleção de
fonte de dados, todas definidas no arquivo 'integrate-datasources.xml'. No final, é
impresso o tempo total com as consultas. |
TestWrapper4 |
Simula um mediator
que envia uma coleção de consultas SQL para uma coleção de
fonte de dados, todas definidas no
arquivo 'integrate-datasources.xml'. O resultado é impresso
em um arquivo texto informado como argumento na linha de
comando. No final, é impresso o tempo total com as consultas. |
TestWrapper5 |
Simula um mediator
que envia uma coleção de consultas SQL para uma coleção de
fonte de dados, todas definidas no arquivo
'integrate-datasources.xml'. A coleção de consultas é definida
em 'integration.xml'. No final, é impresso o tempo total com
as consultas. Deve-se informar na linha de comando o ID da fonte de
dados, o arquivo de consulta e nome/local do arquivo de saída. |
TestWrapperError1 |
Simula um mediator
que envia uma consulta SQL para uma fonte de dados específica,
definida no arquivo 'integrate-datasources.xml'. Este exemplo
testa um erro no comando SQL informado (nome da
tabela errada). Se o parâmetro stopOnError, no
arquivo 'integrate-config.xml', estiver setado para true, uma mensagem
de erro é impressa na saída padrão. Se estiver setado
para false,
o resultado final (um XML na saída padrão) é gerado,
desconsiderando o ResultSet com erro e informando uma mensagem
de erro. No final, é impresso o tempo total com a
consulta. |
TestWrapperError2 |
Simula um mediator
que envia uma coleção de consultas SQL para uma coleção de
fonte de dados, definidas no
arquivo 'integrate-datasources.xml'. Este exemplo
testa um erro no segundo comando SQL informado (nome da
tabela errada). Se o arquivo
'integrate-config.xml', parâmetro stopOnError estiver
setado para true, uma
mensagem de erro é impressa na saída padrão. Se estiver setado
para false,
o resultado final (um XML na saída padrão) é gerado,
desconsiderando o ResultSet e informando uma mensagem de
erro. No final, é impresso o tempo total com as
consultas. |
Última atualização: 28/06/2009