Talend Contextualizado

Olá pessoal! Após o sucesso absoluto das Canecas Talend Brasil e depois de muito tempo sem tutoriais iremos falar sobre algo essencial dentro do Talend: variáveis de contexto e contextos de execução. Pegue sua caneca Talend Brasil, tome um café e se prepare – ou caso você ainda não tenha uma, não perca tempo e adquira já!

Variáveis de contexto são variáveis de acesso global dentro de um job, cujo conteúdo pode variar de acordo com o contexto de execução.

No Talend, os Contextos são organizados em três níveis, os quais iremos conferir hoje:

Variáveis de Contexto -> Grupos de Variáveis -> Contextos de Execução

– Variáveis de contexto representam o menor nível na definição de contextos. Podemos entendê-las como variáveis simples, mas que podem armazenar conteúdos diferentes de acordo com o Contexto de Execução.

– Grupos de Variáveis, como o próprio nome sugere, são grupos de variáveis criados para proporcionar maior organização ao projeto, agrupando variáveis correlacionadas (exemplo: variavéis que formam a conexão com um Mysql).

– Contextos de Execução são os contextos em si. Exemplos de contexto podem ser “Produção” e “Homologação“, ou “Servidor A” e “Servidor B“.

Contexto01
Além disso, você pode definir Grupos de Variáveis armazenados em repositório – desta forma você poderá reaproveitar o mesmo conjunto de variáveis em vários jobs.

Para começar, vamos criar um job e definir uma variável de contexto chamada “Servidor“, do tipo String – vá até a aba Contexts e clique no ícone com um “+”:

Contexto02
Agora iremos definir os contextos de execução do job.
Clique em Values as tree ou Values as table na aba Contexts.
Em seguida clique em Configure Contexts… (botão destacado na imagem abaixo):
Contexto03
E então iremos atribuir valores diferentes para cada contexto:
Contexto04
E como acessar as variáveis de contexto?

Simples! Todas as variáveis de contexto são acessadas da mesma forma:

context.NOME_DA_VARIÁVEL

Vamos dar um exemplo: Adicione um componente tJava ao job e acrescente o seguinte código ao mesmo:

System.out.println(context.Servidor);
Contexto05
Na sequência iremos executar o job. Na aba Run, experimente alterar os contextos a cada execução e observe o que acontece!
Contexto06

Agora você já sabe definir variáveis dentro de um job, mas e se você quiser reutilizá-las em outros jobs?

Vamos até a árvore do repositório e criaremos um Grupo de Variáveis, ou Context Group:

Contexto07
Em seguida vamos definir uma Variável de Contexto chamada arquivo:
Contexto08
E então iremos definir os Contextos:
Contexto09

Por fim, atribuímos os valores a cada contexto:

Contexto10

Dê um Finish e pronto.

Para importar o grupo de variáveis criado para dentro do job que estávamos trabalhando, vá até a aba Contexts e selecione o grupo de variáveis a importar, conforme nas imagens abaixo:

Contexto11

Contexto11

Contexto12

E como o Talend associa tudo isso?

Como você deve ter percebido, é possível criar variáveis sem grupos, grupos sem variáveis, contextos sem variáveis… Não há uma “amarração” muito forte entre os três. Essa é uma flexibilidade que pode ajudar mas também confundir.

É importante compreender como variáveis, grupos e contextos são interligados entre si e a resposta mais simples é: através dos contextos.

Você pode ter tantas variáveis e grupos de variáveis dentro de um job quanto forem necessários. Mas sejam eles importados do repositório ou locais, os nomes de seus contextos de execução deverão coincidir – só assim o Talend poderá compreender em qual contexto executar o job. Observe na imagem anterior: tanto a variável local “Servidor” quanto o grupo denominado “Contexto” possuem dois contextos de execução iguais: Default e Desenvolvimento.

Se você importar um grupo de variáveis cujos contextos de execução são “Servidor A” e “Servidor B” e outro grupo de variáveis cujos contextos de execução são “Desenvolvimento” e “Producao”, não haverá como o Talend compreender em qual contexto executar o job, pois ele terá 4 contextos de execução diferentes.

Dica de boas práticas: variáveis de contexto tem acesso global e funcionam como parâmetros dentro de um job. Seus valores podem ser alterados por quem irá executá-lo e por isso tenha cuidado. Quando for preciso declarar variáveis que influenciam no comportamento de um job e não for sua intenção expor isso, opte por utilizar o globalMap, pois variéveis declaradas lá não ficam expostas externamente à modificações. Como declarar variáveis via globalMap ficará para outro dia… 😉

Muitos usos podem ser feitos das variáveis de contexto, o limite é a criatividade e o motivador é a necessidade – como sempre. Você pode utilizá-las como variáveis de controle de fluxo – como elas tem acesso global dentro do job e seu valor pode ser alterado via parâmetro, você pode utilizá-las para modificar os passos de execução de um job.

Até a próxima!

Anúncios

Retornando valores entre jobs

Neste pequeno tutorial vou demonstrar como retornar valores de jobs “filhos” utilizando o componente tRunJob sem “fluxo de dados”, ou seja, sem utilizar o schema deste componente.

A passagem de parâmetros entre jobs no Talend é feita através de variáveis de contexto. Geralmente os parâmetros do job pai são transferidos para o job filho e quando este precisa retornar algo, são dados cujos metadados são definidos no schema do componente tRunJob. Na forma como foi implementado, o Talend possibilita transferir parâmetros do job pai para o filho através de variáveis de contexto, mas não o contrário. Também não é possível transferir parâmetros entre jobs através do globalMap, pois cada job possui sua própria área de globalMap.

Porém, algumas vezes você pode desejar retornar valores de um job filho que não estão necessariamente em um fluxo de dados. Como fazer isso?

Vamos criar dois jobs de exemplo para demonstrar como retornar valores de subjobs:

Em ambos os jobs, defina uma variável de contexto com tipo Object, vamos chamá-la aqui de SUBJOB_CONTEXT.

pass_param_subjob (1)

Vamos começar pelo job filho. Adicione um componente tJava ao mesmo, e na guia Advanced adicione as seguintes linhas para importar as bibliotecas necessárias:

import java.util.Map;
import java.util.HashMap;

pass_param_subjob (2)

Ainda no componente tJava, na guia Basic, adicione as seguintes linhas:

//Imprime o parâmetro recebido do job pai
System.out.println("param=" + ((Map<String, String>)context.SUBJOB_CONTEXT).get("param"));

//Define uma nova variável, denominada "retVal" e atribui o valor "Ok" à mesma
((Map<String, String>)context.SUBJOB_CONTEXT).put("retVal", "Ok");

pass_param_subjob (3)

O job filho está concluído. Salve.

Agora no job pai, acrescente um componente tJava, importe as mesmas bibliotecas Map e HashMap, conforme no job filho e na guia Basic acrescente as seguintes linhas:

//Instancia um HashMap na variável de contexto definida
context.SUBJOB_CONTEXT = new HashMap<String, String>();

//E então atribui "valor" à uma chave denominada "param" (poderia ter qualquer nome, funciona exatamente como o globalMap)
((Map<String, String>)context.SUBJOB_CONTEXT).put("param", "valor");

pass_param_subjob (6)

Agora arraste o job filho do repositório para o job pai e no campo “Context Param” lembre-se de acrescentar à variável SUBJOB_CONTEXT e atribuir o valor context.SUBJOB_CONTEXT à mesma. Neste exemplo você pode optar também por marcar a opção “Transmit whole context”.

pass_param_subjob (8)

Agora acrescente outro tJava e na guia Basic cole a seguinte linha:

//Imprime o retorno do job filho
 System.out.println("retVal=" + ((Map<String, String>)context.SUBJOB_CONTEXT).get("retVal"));

pass_param_subjob (7)

Ligue os três componentes através da trigger OnSubJobOk.

pass_param_subjob (4)

Execute:

pass_param_subjob (5)

Agora você já viu como é possível retornar valores de jobs filhos utilizando poucas linhas de código. Embora esse seja um exemplo muito simples, é apenas uma porta para várias possibilidades.

Até a próxima!

Fonte: http://bekwam.blogspot.com.br/2011/05/passing-parameters-and-variables-to.html

Otimizando extração e carga de dados utilizando componentes Bulk

Neste artigo vou demonstrar como otimizar a extração e carga de dados quando utilizando componentes Bulk. Para a maioria das tecnologias de bancos de dados suportadas pelo Talend existem os componentes BulkOutput, BulkExec e OutputBulkExec, estes componentes permitem a extração para arquivo (OutputBulk), carga do arquivo utilizando o método de load do próprio banco (BulkExec) e extração e carga utilizando o mesmo componente (OutputBulkExec).

O job de demonstração abaixo foi desenvolvido para a extração de dados de um banco de dados Oracle e carga em um Sybase IQ, mas alguns tweaks foram necessários para otimizar da performance do mesmo, pois apenas esta tabela possuia um volume na casa dos terabytes.

Para começar, primeiramente estabelecemos as conexões com os databases. Como este job executa mais de um subjob em paralelo (veremos adiante como ativar multithreads) temos de garantir que as conexões sejam estabelecidas antes da execução de qualquer outro subjob, para isso utilizamos o componente tPrejob, e por segurança caso a última execução tenha terminado sem sucesso deletamos os arquivos extraídos utilizando os componentes tFileList e tFileDelete. Além do tPrejob, existe o tPostjob, que garante que os subjobs ligados a ele através de triggers sejam executados somente após a execução dos demais subjobs não ligados a ele.

Job completo: clique para visualizar em tamanho real

Um subjob é um segmento do job que pode ser executado independentemente da execução de outros segmentos, ou pode estar conectado a outros através de triggers. Graficamente eles são delimitados por retângulos de fundo azul claro, laranja ou outra cor caso você tenha customizado.

Estabelecidas as conexões e removidos os arquivos de execuções anteriores, damos início à extração e carga de nossos dados.

O subjob logo abaixo do Prejob executa uma query no nosso banco destino, neste caso um Sybase IQ, obtendo o maior ID da tabela que pretendemos carregar, desta forma podemos extrair de nossa fonte apenas os registros novos, cujo ID seja maior que o carregado na última execução. O resultado desta query é propagado ao componente tJavaRow, que armazena o valor em uma variável de contexto.

Trabalhar com o tJavaRow é simples: clique em Sync Columns e então em Generate code, e o Talend irá gerar um código geralmente no padrão

output_row.MAX = input_row.MAX;

onde MAX é o nome de um dos campos do schema do componente (neste caso há apenas um campo), output_row é a saída do tJavaRow e input_row é a entrada, o que ele está recebendo do componente predecessor. Mas como não pretendemos propagar dados a partir deste componente, substituímos output_row por context.NOME_DA_VARIAVEL ficando desta forma:

context.NOME_DA_VARIAVEL = input_row.MAX;

Para criar variáveis de contexto vá até a view Contexts, adicione suas variáveis, defina seus tipos e valores default, você pode ver mais detalhes neste artigo: Usando variáveis de contexto.

Extraído este valor máximo e armazenado em uma variável, partimos para o subjob de extração dos dados da fonte e para garantir que esta etapa seja executada somente após a execução da etapa anterior, ligamos os dois subjobs com a trigger OnSubjobOk.

Este banco de dados que utilizamos como origem é um Oracle RAC (Real Application Cluster), um cluster de databases Oracle para garantir a alta disponibilidade. Como o Talend ainda não suporta a conexão a RAC especificando mais de um host (especificando um apenas funciona, mas não garante a alta disponibilidade) utilizamos uma conexão do tipo General JDBC, onde podemos editar a URL de conexão livremente (O suporte a conexão com RACs Oracle utilizando os componentes desta tecnologia está previsto para a versão 5.0).

Então editamos a query no database de origem, para trazer apenas os dados onde o ID seja maior do que o presente no database destino. Para isso selecione o componente de input e vá em Query, lá edite a query para que ela fique semelhante a esta:

"SELECT
...
...
FROM ORIGEM
WHERE ID > " + context.VARIAVEL

Observe como adicionamos a variável de contexto à query: como no fim das contas isso é uma String para a linguagem Java, colocamos a parte constante entre aspas e então concatenamos o conteúdo da variável, que será definido em tempo de execução, utilizando o operador +.

Dica de desempenho: em alguns componentes de Input de algumas tecnologias, existem opções que permitem otimizar a forma como os dados são extraídos. Nos componentes Oracle e JDBC (dentre outros) existe a opção Enable Cursor que em alguns casos permite obter um ganho de performance considerável. Já no componente de input do MySQL existe a opção Enable stream que também pode incrementar sua performance na extração de dados. Mas atenção: com a opção de stream no Mysql não é possível utilizar uma única conexão em modo multithread com a opção Use an existing connection.

E como modo de armazenamento intermediário destes dados obtidos do database de origem utilizamos arquivo(s) de texto puro. Neste caso utilizaríamos normalmente um componente OutputBulk, mas ao invés disso utilizamos um componente tFileOutputDelimited, que no fim das contas tem o mesmo propósito: gerar um arquivo de texto puro, mas além disso possui uma opção interessante: na guia Advanced do componente ativamos a opção Split output in several files que fará surgir uma outra opção chamada Rows in each output file, com estas opções especificamos que o conjunto de registros obtidos da fonte deverá ser dividido em vários arquivos com um número máximo de registros, cujo valor é definido por você. Neste caso defini um limite de 100 milhões de registros por arquivo. Assim teremos vários arquivos com o nome PRODUCTS1.dat, PRODUCTS2.dat…


O propósito de se dividir o resultset em vários arquivos você entenderá agora com a descrição do outro subjob, que é executado em paralelo ao que foi descrito até aqui.

Este subjob executa enquanto o outro subjob não tiver concluído sua execução. Para isso utilizamos o componente tLoop, onde podemos definir o tipo de Loop que pretendemos executar (for ou while) e as condições de sua execução. O loop “for” é recomendado quando você consegue estimar o número de execuções e o loop “while”, como o próprio nome já diz, é recomendado quando você deseja executar ENQUANTO uma condição for verdadeira. Utilizaremos o loop while e mais à frente irei mostrar como construíremos a condição de execução.

Após o tLoop temos o componente tSleep que permite pausarmos a execução deste subjob por um tempo pré determinado, neste caso um minuto. Observe que a ligação entre o tLoop e tSleep é feita através da linha Iterate, pois não há fluxo de dados sendo transmitido, apenas uma repetição de execuções.

Quando o componente tSleep termina a sua execução é chamado o componente tFileList através da trigger OnComponentOk, ou seja, quando a execução apenas deste componente (tSleep) tiver sido concluída, e então o tFileList irá listar o conteúdo de um diretório especificado por você, sendo que é possível adicionar uma máscara para os arquivos listados para que você filtre o resultado.

Estamos listando o conteúdo do diretório onde o componente tFileOutputDelimited está criando arquivos, então definimos uma máscara com o formato de nome que esperamos para estes arquivos, neste caso “PRODUCTS*.dat”, onde * é um caractere curinga onde esperamos a sequència de números que o tFileOutputDelimited irá inserir na criação dos arquivos.


O resultado dos arquivos listados pode ser obtido através de um loop mais uma vez utilizando a linha Iterate, desta forma conectamos o componente tFileList e tSystem.

Através do componente tSystem executamos comandos do sistema, independente do sistema onde o job está sendo executado, Windows, Linux, FreeBSD… quem sabe outros.. E neste especificamente executamos um comando pertencente a sistemas Unix e similares: o lsof, que lista os arquivos abertos no momento por algum processo.

Observe o comando sendo executado:

"sudo /usr/sbin/lsof " + ((String)globalMap.get("tFileList_1_CURRENT_FILEPATH"))

Chamamos o comando lsof e concatenamos à String o caminho do arquivo atual listado pelo componente tFileList, mas como obter este caminho?

Observe que no canto esquerdo inferior da suite, abaixo do repositório, existe uma view chamada Outline. Dentro desta view existem variáveis de retorno dos componentes que você está utilizando no job atualmente aberto, como número de linhas inseridas em um arquivo ou erro retornado por um componente. Para utilizar estas variáveis você simplesmente seleciona e arrasta para o local desejado, um campo de código livre como no tJava ou tJavaRow ou mesmo um campo de opção de algum componente, como iremos fazer agora.

Para obter os nomes dos arquivos que listamos no componente tFileList, incluindo o caminho de sua localização, e concatenar esta String ao comando lsof, vamos até a view Outline, expandimos a visão do componente que desejamos, neste caso o tFileList_1 e arrastamos a variável Current File Name with path para o campo onde executamos o comando do sistema no componente tSystem, concatenando as Strings com o operador +.

Atenção: Tome o cuidado de observar o nome único do componente na view Outline, neste job temos por exemplo os componentes tFileList_1 e tFileList_2. Você pode obter o nome único do componente clicando no mesmo e olhando o cabeçalho da view Component.

Agora que já listamos os arquivos criados naquele diretório e executamos o comando lsof sobre a lista obtida, partimos para a carga em si destes arquivos no database destino e então você entenderá o por que de tudo isso.

Como estamos gerando vários arquivos separados em 100 milhões de registros e em paralelo temos um subjob responsável pela carga destes arquivos no Sybase IQ, temos de garantir que a carga dos arquivos extraídos somente seja executada após a conclusão destes, ou seja, após o seu fechamento. Para isso executamos o comando lsof e, dependendo do resultado, saberemos se o arquivo está fechado, significando que o mesmo está pronto para carga, ou aberto, significando que a extração de registros para este arquivo ainda não foi concluída.

Então utilizamos o componente BulkExec da tecnologia destino, aqui um Sybase IQ, para carregar o arquivo do loop atual. Neste componente você define o schema da tabela destino e aponta para o arquivo a ser carregado, mais uma vez obtendo o nome do arquivo e caminho listado no tFileList através da view Outline.

E para garantir que sejam carregados apenas os arquivos fechados, conectamos o componente tSystem ao tSybaseIQBulkExec utilizando a trigger If, onde poderemos especificar uma condição para execução do componente sucessor. Como condição utilizamos o retorno do componente tSystem, que caso seja igual a 1 indica que o arquivo atual não foi listado, ou seja, não está aberto por nenhum processo e então podemos carregá-lo.

Por fim, chamamos os componentes tSybaseCommit e tFileDelete logo após a carga do arquivo, que como os próprios nomes descrevem, realizam o Commit da transação e exclusão do arquivo carregado (mais uma vez utilizamos a variável Current file with path do componente tFileList).

Agora os detalhes adicionais para conclusão deste job. Como condição de execução do componente tLoop, queremos que este subjob seja executado enquanto houver algum arquivo a carregar, então irei lhe mostrar como construir esta condição:

Procure pelo nome único do componente tFileOutputDelimited dentro de Outline (neste caso provavelmente haverá apenas tFileOutputDelimited1) e arraste a variável Number of line para o campo Condition do componente tLoop e compare o seu valor com null, ficando desta maneira:

(((Integer)globalMap.get("tFileOutputDelimited_1_NB_LINE")) == null)

Desta forma garantimos que o subjob continue sua execução mesmo se o seu início se der antes do subjob de extração dos dados, pois o número de linhas retornado pelo componente tFileOutputDelimited será igual a null. Mas isto não é suficiente: devemos agora testar se o componente tFileList retornou algum arquivo e para isto arrastamos a variável Number of files da view outline e separamos as condições pelo operador || , que significa OU. Ainda, damos uma margem caso o componente tFileList ainda não tenha sido executado, comparando o conteúdo da variável Number of files também com null e aglomeramos estes dois testes entre parenteses para que seja retornato true (verdadeiro) caso um ou o outro retorne true, mesmo que o outro teste retorne false.

(((Integer)globalMap.get("tFileList_1_NB_FILE")) >= 1 || ((Integer)globalMap.get("tFileList_1_NB_FILE")) == null)

Juntos, os três testes com compoem a condição do loop ficarão assim:

(((Integer)globalMap.get("tFileOutputDelimited_1_NB_LINE")) == null) || (((Integer)globalMap.get("tFileList_1_NB_FILE")) >= 1 || ((Integer)globalMap.get("tFileList_1_NB_FILE")) == null)

Para concluir, utilizamos o componente tPostJob para conectar os componentes tSybaseClose e tJDBCClose, que como os nomes já descrevem, fecham as conexões estabelecidas logo no início da execução do job.

Um último detalhe antes de pressionar F6 é habilitar a execução multithread. Vá até a view Job, entre em Extra e habilite a opção Multithread Execution.

Conclusão

Para muitas cargas quando se tratam de alguns megabytes não há a necessidade de um job como este, provavelmente você utilizará um “input” e um “outputbulkexec“, mas conforme o volume de dados aumenta, a complexidade dos jobs responsáveis por sua carga se eleva proporcionalmente se você quiser incrementar a performance.

Com esta abordagem o espaço em disco não precisa ser uma preocupação: imagine extrair alguns terabytes de dados em um único arquivo para só então carregar este arquivo, enquanto você pode consumir apenas alguns gigabytes para isso!

Além do espaço em disco, há um ganho de tempo considerável, pois o database destino não precisa ficar horas (ou dias!) esperando a extração ser concluída para só então realizar a carga, enquanto pode fazê-la em partes.

Por fim, a carga de dados a cada 100 milhões de registros torna o processo mais simples de se recuperar de qualquer execução falha: imagine se a 99% da extração dos dados da fonte a rede vai abaixo? Você tem a segurança de que ao menos algo em torno de 95% já tenha sido carregado no destino com sucesso e é esse o motivo de excluírmos quaisquer arquivos existentes no início do processo: pode haver algum registro truncado e então extraímos apenas os registros cujo ID seja maior do que o último carregado no destino.

Usando variáveis de contexto

Olá, neste job mostraremos como definir variáveis de contexto. Variáveis de contexto podem armazenar diretórios, configuração de banco de dados, em fim tipos de dados como string, interger, char, .. Se mostra útil no uso repetitivo de determinado valor. Imagine um job onde você utiliza repetidamente uma string que determina o caminho de um arquivo a ser o destino de nossos dados. Com uma variável de contexto guardando este valor a manutenção e possível mudança no job quanto ao diretório de destino será bastante simples e rápido, podendo alterar apenas a variável de contexto e alterar várias saídas.

Em posts anteriores já vimos como iniciar um projeto. Partiremos daqui.

Botão direito em Job Design‘create job’. Dê um nome ao nosso job, sugiro “usando vairiáveis de contexto”. Job criado, acesse a ‘paleta de componentes’ na aba Misc e selecione o componente tRowGenerator e clique na Job Design ou segure e arraste. Faça o mesmo para o componente tFileOutputDelimited localizado na aba File. Ligue os dois componentes usando o botão direito em tRowGenerator e selecionando ‘main’, ou segurando o botão direito arrastando até o segundo componente, tFileOutputDelimited. Assim criamos um ‘row link’, que será nosso duto para o fluxo de dados. Existem outros tipos de links, lógicos, que serão apresentados futuramente.

Clique duas vezes em tRowGenerator para abrir sua edição. Aqui temos dois grandes campos, sendo o primeiro para a criação e edição dos campos para nossos registros e o segundo para edição do parâmetros a serem utilizados no primeiro. No primeiro campo vamos configurar duas colunas, “company” e “randomNumber”. Na coluna ‘company’, escolha o tipo de dados como String, ‘…’ para a função, e então em parâmetros  digite “Client” em ‘value’. Já para a coluna ‘randomNumber’, escolha Integer para o tipo de dados, random para a função. Clique em ok. Aparecerá uma caixa de diálogo,

clique em Yes para sincronizar o esquema que criamos com o esquema de saída, ou seja, o esquema montado no arquivo. Clique duas vezes em tFileOutputDelimited para abrir sua edição na aba inferior ‘component view’. Clique em […] para determinar o diretório, nome e extensão do arquivo de saída. Use o diretório que entender melhor, com nome extensão, client1.csv.

Até aqui, temos nosso job desenvolvido em seu componentes e links. No componente de entrada, irá gerar registros da maneira como acabamos de configurar. Assim como o de saída, que já tem seu caminho configurado. Então vamos partir para o que interessa, as variáveis de contexto. Execute e job e verifique o arquivo criado, bem como seus dados, diretório, e nome, assim como foram setados. Crie as variáveis de contexto no repositório. Para isso, clique com o botão direito em Contexts na aba lateral de repositório de trabalho. Selecione Create constext group, dê um nome ao seu grupode contexto. Sugiro sempre usar um nome parecido ao do projeto. Clique em next. Estamos agora no campo onde poderemos criar e setar nossas variáveis. Para criar, clique em [+], três vezes,dê nomes as variáveis e indique seus tipos, company(String), diretory(Directory) e nbrows(int).  Clique na aba Values as tree e em Configure Contexts. Então, clique em New para adicionar novos contextos, sendo eles: contextClient1 e contextClient2. Dê OK. Ainda na aba Values as tree, defina vlaores para as variáveis de cada contexto.

Então, recaptulando, até aqui criamos um grupo de contexto. Neste grupo de contexto há três contextos, que serão nossas opções para execução do job final. E cada contexto é composto de trêsvariáveis de contexto.

Agora temos de disponibilizar estes contextos para o job que queiramos que trabalhe com estes. Clique no Context view (aba inferior). E Clique no botão de contexto para importar as variáveis. Então selecione todas as variávies de contexto que acabalmos de criar e dê OK. Então adicione o grupo de contexto em Add Context Group. Selecione os contextos e dê OK. Pronto, nossas variávies criadas já estão disponíveis na Context view.

Agora então, nos falta apenas usar nossas variáveis de contexto na execução dos jobs. Clique duas vezes no componente tRowGenerator para abrir seu editor. No campo, Number of Rows, coloque a variável de contexto nbrows, você pode fazer isso apenas digitando context.nbrows ou selecionando o campo e teclando Ctrl+Space, isso listará opções de sistema e contexto para que não precisse se preocupar em lembrar o nome da variável que usou. Faça o mesmo para o campo Parameter no campo de função de parametros do nosso esquema, setando a variável context.company. Dê OK.

Usamos duas das três variáveis de contexto. Falta apenas a variavel que indicava nosso diretório. Este será usado para não ter que ficarmos repetindo um diretório extenso para cada execução de nosso job. Isso facilita bastante. Pode imaginar o tempo que economizamos. Clique duas vezes no componente tFileOutputDelimited. No campo File Name, devemos passas do diretório, o nome do arquivo e ainda sua extensão. Assim usaremos nossas variáveis criadas. Lembrando que estamos lidando com Java, podemos concatenar Strings de forma a usar nossos contextos e gerar a String com diretório, nome e extensão para nosso arquivo de saída, assim:  context.directory+context.company+”.csv”.

Contextos criados, configurados e indicados para uso podemos rodar nossso job nos diversos contextos criados para que possamos ver o resultado. Para isso basta ir na aba inferior Run e dentro desta na aba de contexto selecionar um dos três contextos e clicar no botão de Run para executar nosso job usando o contexto selecionado. Fazendo isso para os três que criamos, podemos notar diferenças no númro de linhas criadas, na informção do campo company da nossas tabelas, e ainda no diretório e no nome do arquivo, isso tudo apenas usando as três variáveis de contextos que criamos. Essa se mostra uma boa prática, pois a mudança em cada um desses campos se mostra bem mais demorada que a simples criação dos variados contextos. E uma necessária re-execução se mostra ainda mais lenta.

Espero que tenha sido um post claro e útil.

O uso de variáveis de contexto se mostra muito mais ampla, segura e necessária que essas simples explicação. Mostraremos mais detalhes, principalmente sobre segurança, futuramente.

Um abraço a todos.