Este projeto visa disponibilizar um framework para auxiliar no desenvolvimento de projetos de interoperabilidade utilizando as tecnologias InterSystems, tais como:
O objetivo principal é encapsular todo o desenvolvimento repetitivo em componentes configuráveis.
Nesta primeira versão é disponibilizadao o módulo XDBC para desenvolvimento de interoperabilidade com acesso a banco de dados relacionais. Este módulo pode ser utilizado no Ensemble, IRIS, IRIS for Health e Health Connect.
Todas as colaborações são bem vindas. Fiquem a vontade para fazer fork do repositório e contribuir.
Este módulo visa agilizar o desenvolvimennto de interoperabilidade utilizando ODBC ou JDBC. a intalação e bem simples. Baixe o pacote xml Interopway_XDBC-V0.0.1.xml e importe no namespace desejado.
A importação pode ser feita de 3 modos:
- Via Studio (apenas em Windows);
- Via SMP (qualquer SO);
- Terminal ou WebTerminal (qualquer SO)
Do $system.OBJ.Load("</caminho/arquivo>/Interopway_XDBC-V0.0.1.xml","ck")
O uso é fácil e quase auto explicativo. No pacote cjs.interopway.samples existe uma Production configurada demonstrando o uso de interoperabilidade ODBC e JDBC.
A classe cjs.interopway.tests.InteropProduction com os casos de testes a serem executados para validar se a instalação.
Abaixo são detalhados os pré-requistos e passos necessários para a excução dos casos de testes. Os testes foram executados em ambiente Windows em uma instância Ensemble:
$ZV=Cache for Windows (x86-64) 2018.1.5 (Build 659U) Mon Mar 22 2021 07:03:57 EDT
- JDK 1.7 ou 1.8 instalado. Usado pela conexão JDBC;
- DSN de Sistemas com o nome Ensemble Samples usado pela conexão ODBC;
- Diretório vazio C:\Temp\tests. Usado pelo Test Manager;
- Credencial Ensemble Samples configurada no SMP no namespace da instalação.
Uma vez que os pré-requistos estejam atendidos abra uma sessão do Terminal ou WebTerminal no namespace onde o módulo XDBC foi instalado e execute a linha abaixo:
Do ##Class(%UnitTest.Manager).RunTest("tests:cjs.interopway.tests.InteropProduction", "/noload/nodelete")
Ao término da execução dos testes, se tudo ocorreu conforme o esperado, a saída deverá ser algo pareceido com a imagem abaixo. Para um relatório detalhado da execução acesse a URL que aprece no destaque da imagem.
A URL te levará até o Portal de Testes onde pode-se inspecionar cada caso de teste individualmente.
Detalhe execução do Caso de Teste TestExecuteProcedureODBC
Detalharemos o uso da Lookup Table TESTS_XDBC_CONFIG e as classes do pacote de exemplo cjs.interopway.samples:
-
TESTS_XDBC_CONFIG - Lookup Table com as configurações necessárias para a execução dos comandos SQL a serem executos nos bancos de dados externos.
<?xml version="1.0"?> <lookupTable> <entry table="TESTS_XDBC_CONFIG" key="cjs.interopway.samples.company.bo.UpdateCompanyRequest">{ "credential":"ENSEMBLE Samples", "statement":"UPDATE Sample.Company SET TaxID = ? WHERE ID = ?" } </entry> <entry table="TESTS_XDBC_CONFIG" key="cjs.interopway.samples.person.bo.PersonSetsRequest">{ "credential":"ENSEMBLE Samples", "statement":"? = CALL Sample.PersonSets(?,?)" } </entry> <entry table="TESTS_XDBC_CONFIG" key="cjs.interopway.xdbc.bo.QueryRequest">{ "credential":"ENSEMBLE Samples", "statement":"SELECT * FROM Sample.Person" } </entry> <entry table="TESTS_XDBC_CONFIG" key="cjs.interopway.xdbc.bo.QueryStreamRequest">{ "credential":"ENSEMBLE Samples", "statement":"SELECT * FROM Sample.Employee" } </entry> </lookupTable>
A Lookup Table acima é utilizada por todas as classes que constam no atributo key da lookup mais especificamente no construtor que fica definido na classe base de request cjs.interopway.xdbc.bo.BaseRequest:
Method %OnNew(lookupTable As %String = "XDBC") As %Status
{
#Dim exception As %Exception.General = ""
#Dim statusCode As %Status = $System.Status.OK()
Try
{
#Dim configString As %String = ##Class(Ens.Util.FunctionSet).Lookup(lookupTable, $ClassName())
If (configString = "")
{
Return statusCode
}
#Dim config As %DynamicObject = {}.%FromJSON(configString)
If (config.credential '= "" && '##Class(Ens.Config.Credentials).%ExistsId(config.credential))
{
Return $System.Status.Error(5001, "Credential does not exists.")
}
If (config.credential '= "")
{
Set ..Credential = config.credential
}
If (config.statement '= "")
{
Set ..Statement = config.statement
}
If (config.dsn '= "")
{
Set ..DSN = config.dsn
}
}
Catch (exception)
{
Set statusCode = exception.AsStatus()
}
Return statusCode
}
- cjs.interopway.samples.company.bo.UpdateCompanyRequest - Request específico para executar uma atualização com parâmetros sem descrevê-los.
ClassMethod GetInstance(companyId As %Integer, taxId As %String) As UpdateCompanyRequest
{
#Dim updateRequest As UpdateCompanyRequest = ..%New("TESTS_XDBC_CONFIG")
//
Do updateRequest.Parameters.Insert(##Class(ParameterDefinition).%New(1, taxId))
Do updateRequest.Parameters.Insert(##Class(ParameterDefinition).%New(2, companyId))
//
Return updateRequest
}
- cjs.interopway.samples.person.bo.PersonSetsRequest - Request específico para executar a proceduere que retorna 2 ResultsSets e descreve os parâmetros da chamada.
ClassMethod GetInstance(name As %Integer, state As %String) As PersonSetsRequest
{
#Dim procedureRequest As UpdateCompanyRequest = ..%New("TESTS_XDBC_CONFIG")
#Dim returnParameter As ParameterDefinition = ##Class(ParameterDefinition).%New(1)
#Dim nameParameter As ParameterDefinition = ##Class(ParameterDefinition).%New(2, name)
#Dim stateParameter As ParameterDefinition = ##Class(ParameterDefinition).%New(3, state)
//
Set returnParameter.IOType = returnParameter.IOTypeDisplayToLogical("OUTPUT")
Set nameParameter.IOType = nameParameter.IOTypeDisplayToLogical("INPUT")
Set stateParameter.IOType = stateParameter.IOTypeDisplayToLogical("INPUT")
Set returnParameter.SqlType = $$$SqlInteger
Set nameParameter.SqlType = $$$SqlVarchar
Set stateParameter.SqlType = $$$SqlVarchar
//
Do procedureRequest.Parameters.Insert(returnParameter)
Do procedureRequest.Parameters.Insert(nameParameter)
Do procedureRequest.Parameters.Insert(stateParameter)
//
Return procedureRequest
}
-
cjs.interopway.samples.InteropProducion.cls - Class da Production de exemplo contento os componentes:
-
EnsLib.JavaGateway.Service - Busines Service que se comunica com a JVM. Dev-se configurar o caminho para os drivers JDBC da base de dados externa.
-
JDBC Sample Operation - Instância da classe cjs.interopway.xdbc.bo.Operation. Business Operation que se comunica com a base de dados exteran via JDBC. Aqui é configurado a DSN que neste caso é a String de conexão, Credencial e classe do driver
-
ODBC Sample Operation - Instância da classe cjs.interopway.xdbc.bo.Operation. Business Operation que se comunica com a base de dados exteran via ODBC. Aqui é configurado a DSN e Credencial.
-
Abaixo é detalhado cjs.interopway.tests:
-
cjs.interopway.tests.InteropProduction - Classe com os casos de testes a serem executados:
-
TestExecuteQueryODBC - Executa o comando SQL SELECT * FROM Sample.Person na conexão ODBC.
-
TestExecuteQueryJDBC - Executa o comando SQL SELECT * FROM Sample.Person na conexão JDBC.
-
TestExecuteQueryStreamODBC - Executa o comando SQL SELECT * FROM Sample.Employee na conexão ODBC.
-
TestExecuteQueryStreamODBC - Executa o comando SQL SELECT * FROM Sample.Employee na conexão JDBC.
-
TestExecuteUpdateODBC - Executa o comando SQL UPDATE Sample.Company SET TaxID = ? WHERE ID = ? na conexão ODBC com parâmetros porém se descrevê-los.
-
TestExecuteUpdateJDBC - Executa o comando SQL UPDATE Sample.Company SET TaxID = ? WHERE ID = ? na conexão JDBC com parâmetros porém se descrevê-los
-
TestExecuteProcedureODBC - Executa o comando SQL ? = CALL Sample.PersonSets(?,?) na conexão JDBC com parâmetros e descrevendo-os.
-
TestExecuteProcedureODBC - Executa o comando SQL ? = CALL Sample.PersonSets(?,?) na conexão JDBC com parâmetros e descrevendo-os.
-
Para a utilização do interopway_xdbc basta seguir o simples quia abaixo:
-
Adicione o Busines Operation (cjs.interopway.xdbc.bo.Operation à Production;
-
No uso de conexão via ODBC configurar o DSN no Sistema Operacional;
-
No uso de conexão via JDBC adicionar o caminho do driver no CLASSPATH;
-
De acordo com a necessidade pode-se configurar a Credencial e/ou DSN nas configurações do Business Operation.
-
Caso a Credencial e/ou o DSN não sejam cofigurados no Business Operation, essas configurações devem ser passadas para o Business Operation através das mensagems de request, podendo ser atribuidas diretamenta na mensagem,ou podem ser adicionadas na Lookup Table utilizada no construtor das mensagems. Veja: cjs.interopway.xdbc.bo.BaseRequest
-
Para grande maioria dos bancos de dados os comandos SQL que possuem parâmetros, não é necessário fazer a descrição dos mesmos através das propriedades SQLType, Precision e Scale da classe cjs.interopway.xdbc.bo.ParameterDefinition. Veja: cjs.interopway.samples.company.bo.UpdateCompanyRequest;