Hoje vamos falar um pouco de Oracle Concurrents. Os Concurrents, também chamados de Concorrentes, por nós Brazucas, são transações específicas dentro Oracle EBS (Oracle E-Business Suite, popularmente chamado de Application), com o objetivo de executar determinadas tarefas de forma organizada e lógica. Eles podem obedecer a uma hierarquia e a uma sequência de execução. Os concorrentes são cadastrados como programas dentro do EBS, onde é possível, inclusive, definir uma série de parametrizações e formas de execução. Eles também podem ser agrupados para execução em conjunto, inclusive interagindo-se entre si. As execuções são realizadas por uma tela de gerenciamento de execução, onde de lá, chamamos determinado concorrente cadastrado e submetemos o mesmo à execução. Através desta tela, podemos acompanhar o status de execução e algumas informações como saídas e logs de erro. Também podemos executar um concorrente através de uma opção de menu, o que é comum em alguns casos. Contudo, o foco deste post não é entrar em detalhes sobre como são cadastrados e definidos os concorrentes dentro do EBS. Para isto sugiro consultar a documentação do Oracle E-Business Suite. O foco aqui é demonstrar como executar um concorrente via código, de dentro de uma PROCEDURE, PACKAGE ou FORMS, por exemplo. Apenas para constatar, além dos objetos de banco de dados, também podemos executar concorrentes através de Forms, Reports ou arquivos externos, como por exemplo, arquivos com extensão SQL.
Abaixo segue o pacote para a execução de um concorrente. Conforme, falei, precisamos definir algumas informações e parametrizações para que a execução possa ser realizada com sucesso.
w_request_id := fnd_request.submit_request( application IN varchar2
,program IN varchar2
,description IN varchar2 default NULL
,start_time IN varchar2 default NULL
,sub_request IN boolean default FALSE
,argument1 IN varchar2 default CHR(0)
...
,argumentNN IN varchar2 default CHR(0));
Conforme pode ser visto a cima, o pacote é o FND_REQUEST e a função é a SUBMIT_REQUEST. Esta função retorna o REQUEST_ID (no exemplo, recebido pela variável W_REQUEST_ID), que é o número da solicitação (ID do concorrente, como nós chamamos). Caso o pedido de execução do concorrente tenha ocorrido com sucesso, a função retornará o ID gerado pela submissão. Caso contrário, ele retornará 0 (zero). Note que este retorno não diz repeito ao status da execução propriamente dita do concorrente, ele é referente a submissão de execução, ou seja, diz respeito ao seu start. Se o Oracle conseguiu iniciar a execução, isto é tido como sucesso, e, portanto, é gerado um ID de solicitação para então prosseguir para a execução.
Além dos parâmetros que podem ser definidos pelo usuário, existem outros que são nativos e requeridos, que devem ser informados para que o start da execução tenha sucesso. São eles:
- Application: Short Name (apelido) da aplicação, por exemplo, AR, PO, SQLAP, etc. Ele vai variar dependendo de qual aplicação origem você deseja executar o concorrente. Por exemplo, se você estiver executando um concorrente do AR e o mesmo estiver configurado para este módulo, é necessário verificar qual é o Short Name do AR. Lembrando, que um concorrente cadastrado no EBS, está ligado a uma aplicação. Este apelido, você pode encontrar no cadastro de aplicações no Oracle EBS, pelas responsabilidades de administração e desenvolvimento do sistema.
- Program: Nome abreviado do concorrente. Quando cadastramos a definição do concorrente, temos que criar um nome abreviado para o mesmo. É este nome que devemos informar neste parâmetro.
- Description: Nome que irá aparecer na janela de solicitações de concorrentes, quando o mesmo for submetido. Caso não seja informado um (o padrão é deixar nulo), ele pegará o nome cadastrado na definição do concorrente. (default NULL)
- Start_time: Indica a hora de início da solicitação. Deixando como nulo caracterizará execução imediata. (default NULL)
- Sub_request: Indica a execução como sendo uma execução filha de outra. (default FALSE)
- Argument1: Primeiro parâmetro da execução. Se o concorrente contiver parâmetros para execução, é aqui que são informados. (default CHR(0))
- ArgumentNN: Último parâmetro, tipo ARGUMENT, no total de 100, que podemos utilizar. (default CHR(0)
Note que todos os parâmetros são do tipo IN, ou seja, de entrada.
Considerações sobre os parâmetros (Arguments):
Como eles possuem valores padrões em suas definições, os chamados valores Default, não necessitamos informar os 100 parâmetros, caso os mesmos não sejam utilizados. Contudo, levando em conta minha experiência em desenvolvimento, já houve casos de problemas na execução, se estes valores padrões não fossem informados. Desta forma, fica a dica. Caso algum erro esteja acontecendo e tudo já foi verificado, pode ser o momento de testar coisas imagináveis, como por exemplo, esta. Por via das dúvidas, sempre informo ;-p. Veja como ficaria a chamada, informando o todos os parâmetros:
w_request_id := fnd_request.submit_request
( 'INV'
,'INV'
,null
,null
,false
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
);
No total, a chamada da função totaliza 105 parâmetros.
ATENÇÃO: Outro fator importante que deve ser considerado é que determinados concorrentes, principalmente, os nativos (se diz nativos, aqueles que são padrões do EBS, e não os customizados), podem necessitar de valores de determinadas variáveis de ambiente, ou variáveis locais para funcionar. Desta forma, quando você executa um concorrente nativo via código, através de um objeto customizado, por exemplo, estas variáveis podem não estar visíveis, podendo ocasionar um erro, não permitindo que o concorrente seja submetido. Caso isto aconteça, podemos simular o ambiente do EBS, configurando algumas varáveis.
Para mais detalhes sobre estas configurações, veja o artigo “Simulando sessão Oracle Application em Ferramentas de acesso a Banco de Dados”, neste blog.
Verificando Status do Concorrente:
Dentro do pacote FND_CONCURRENT há funções e procedimentos que podem ser úteis quando estamos manipulando concorrentes, e uma destas utilidades é a verificação do status ou da fase de um concorrente, em um determinado momento da execução, sendo durante ou após término da mesma. Veja a chamada a seguir:
w_request_status := fnd_concurrent.get_request_status( request_id IN OUT NOCOPY number,
,appl_shortname IN varchar2 default NULL,
,program IN varchar2 default NULL,
,phase OUT NOCOPY varchar2,
,status OUT NOCOPY varchar2,
,dev_phase OUT NOCOPY varchar2,
,dev_status OUT NOCOPY varchar2,
,message OUT NOCOPY varchar2);
Esta função, que retorna true ou false, possui parâmetros de saída e de entrada. Veja o significado de cada um deles:
Parâmetros de Entrada (IN):
- Request_id : ID do Concorrente que deve ser verificado. Obs. Este parâmetro também é de saída (OUT).
Obs.: Se a informação referente a aplicação (appl_shortname) e ao programa (Program) é passado como parâmetro, o ID do Concorrente mais recente para este programa é devolvido juntamente com o estado e fase.
- Appl_shortname: É referente a Aplicação o qual o programa pertence.
- Program: É referente ao nome do programa. Os parâmetros Appl_shortname e Program são usados somente se o ID do Concorrente não for fornecido.
Parâmetros de Saída (OUT):
- Phase: Retorna a Fase referente a execução do concorrente, no formato display, como por exemplo, “Em Execução” ou “Concluído” (depende da linguagem).
- Status: Retorna o Status referente a execução do concorrente, no formato display, como por exemplo, “Normal” (depende da linguagem).
- Dev_phase: Retorna a Fase referente a execução do concorrente, no formato código, como por exemplo, “RUNNING” ou “COMPLETE” (utilizado para comparações e verificações universais em programas).
- Dev_status: Retorna o Status referente a execução do concorrente, no formato código, como por exemplo, “NORMAL” (utilizado para comparações e verificações universais em programas).
- Message: Mensagem de conclusão do concorrente. Por exemplo, “Conclusão normal” (depende da linguagem).
Abaixo, um exemplo de chamada:
w_request_status := fnd_concurrent.get_request_status( w_request_id
,null
,null
,v_phase
,v_status
,v_dev_phase
,v_dev_status
,v_message);
Aguardando a conclusão...:
Quando um concorre é submetido através de código, o pacote envia a solicitação e libera o objeto que está submetendo, para continuar sua sequencia de execução. Contudo, dependendo da necessidade, pode-se querer esperar o término da execução do concorrente, para que seja possível tomar alguma ação mediante o status da execução. Para isto, podemos utilizar o pacote FND_CONCURRENT.WAIT_FOR_REQUEST. Este pacote faz com que o objeto chamador aguarde pelo término da execução do concorrente. A chamada deste pacote deve ser realizada após a submissão do concorrente, pela chamada SUBMIT_REQUEST e após se certificar que o concorrente foi submetido (através do retorno do ID do concorrente vindo da função). Outro detalhe, a chamada ao WAIT_FOR_REQUEST, deve ser precedida de um COMMIT. Veja o exemplo abaixo:
...
if not fnd_concurrent.wait_for_request(w_request_id, 2, 0, v_phase, v_status, v_dev_phase, v_dev_status, v_message) then
raise_application_error(-20001, v_message);
else
if v_dev_status not in ('NORMAL', 'WARNING') then
raise_application_error(-20001, v_message);
end if;
end if;
...
Note no exemplo acima, que através do parâmetro de retorno V_DEV_STATUS, conseguimos saber com qual status o concorrente finalizou. Lembrando, que a chamada WAIT_FOR_REQUEST só libera a continuação da execução do objeto chamador, após o término da execução do concorrente ou após um tempo que pode ser definido na chamada desta função.
Além dos parâmetros referentes ao Status do concorrente, esta função, que retorna true ou false, também possui outros parâmetros de entrada e saída. Veja o significado de cada um deles:
w_request_wait := wait_for_request( request_id IN number default NULL
,interval IN number default 60
,max_wait IN number default 0
,phase OUT NOCOPY varchar2
,status OUT NOCOPY varchar2
,dev_phase OUT NOCOPY varchar2
,dev_status OUT NOCOPY varchar2
,message OUT NOCOPY varchar2);
Parâmetros de Entrada (IN):
- Request_id: ID do Concorrente que deve ser monitorado, ou seja, esperar a conclusão.
- Interval: Frequência da verificação de término do concorrente (padrão 60 segundos).
- Max_wait: Quantidade máxima de espera (em segundos) para a conclusão do concorrente (coloque 0 para espera infinita).
Parâmetros de Saida (OUT):
- Phase: Retorna a Fase referente a execução do concorrente, no formato display, como por exemplo, “Em Execução” ou “Concluído” (depende da linguagem).
- Status: Retorna o Status referente a execução do concorrente, no formato display, como por exemplo, “Normal” (depende da linguagem).
- Dev_phase: Retorna a Fase referente a execução do concorrente, no formato código, como por exemplo, “RUNNING” ou “COMPLETE” (utilizado para comparações e verificações universais em programas).
- Dev_status: Retorna o Status referente a execução do concorrente, no formato código, como por exemplo, “NORMAL” (utilizado para comparações e verificações universais em programas).
- Message: Mensagem de conclusão do concorrente. Por exemplo, “Conclusão normal” (depende da linguagem).
Segue um exemplo completo, implementando todos estes recursos:
declare
--
-- Variável para a chamada SUBMIT_REQUEST.
w_request_id integer;
w_request_status boolean;
w_nr_verificacao number;
w_cancel_request boolean;
--
-- Variáveis para a chamada WAIT_FOR_REQUEST.
v_phase varchar2(20);
v_status varchar2(20);
v_message varchar2(150);
v_dev_phase varchar2(20);
v_dev_status varchar2(20);
--
-- Variáveis para simulação da sessão EBS.
w_resp_appl_id varchar2(50);
w_resp_id varchar2(50);
w_user_id varchar2(50);
w_org_id varchar2(50);
--
begin
--------------------------------
--Submete o processo concorrente
--------------------------------
w_request_id := fnd_request.submit_request( 'TGR'
,'TGR_GL_GERA_VIS_ORCATO_FUT_ALL'
,null
,null
,false
,'371' ,'N' ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0) ,chr(0)
);
--
-----------------------------------------------------------------------
-- Verifica se foi submetido com sucesso.
-- Se foi submetido com sucesso, W_REQUEST_ID terá o ID do concorrente.
-- Caso contrário, ele terá 0 (zero).
-----------------------------------------------------------------------
if w_request_id = 0 then
raise_application_error(-20001, 'Não foi possível submeter o concorrente !!!: '||w_request_id);
else
dbms_output.put_line('Concorrente gerado: '||w_request_id);
end if;
--
commit; -- Sempre colocar quando usar wait_for_request.
--
------------------------------------
-- Verifica o Status do Concorrente.
------------------------------------
w_request_status := fnd_concurrent.get_request_status( w_request_id
,null
,null
,v_phase
,v_status
,v_dev_phase
,v_dev_status
,v_message);
--
-- --------------------------------------------------------------
-- Entra no processo de espera pelo términco do concorrente.
-- --------------------------------------------------------------
w_nr_verificacao := 1;
loop
--
---------------------------------------
-- Aguarda a conclusão com concorrente.
---------------------------------------
if not fnd_concurrent.wait_for_request( w_request_id
,1 -- verifica após um 1 segundo (sleep).
,3 -- após o início da verificação, aguarda 3 segundos e encerra a espera.
,v_phase
,v_status
,v_dev_phase
,v_dev_status
,v_message) then
--
raise_application_error(-20001, v_message);
--
end if;
--
-- Após 3 verificações de espera, e o concorrente ainda não finalizou, cancela a execução.
if w_nr_verificacao = 3 then
-- ---------------------------------------------------------------------------------------
-- Se depois de 3 verificações o concorrente ainda não concluiu, cancelamos o concorrente.
-- ---------------------------------------------------------------------------------------
w_cancel_request := fnd_concurrent.Cancel_Request( w_request_id
,v_message);
--
dbms_output.put_line('O tempo de execução inspirou! ('||w_nr_verificacao||' verificações).');
--
end if;
--
exit when (v_dev_phase = 'COMPLETE');
--
w_nr_verificacao := w_nr_verificacao + 1;
--
end loop;
--
dbms_output.put_line('Mensagem: '||v_message);
--
-----------------------------------------
-- Verifica se foi concluído com sucesso.
-----------------------------------------
if v_dev_status not in ('NORMAL', 'WARNING') then
dbms_output.put_line('Concorrente terminou com erro: '||v_status);
else
dbms_output.put_line('Concorrente terminou com o status: '||v_status);
end if;
--
end;
Observações Gerais:
Para que a execução via código funcione, o concorrente deve estar cadastrado no EBS, com seus parâmetros definidos (caso houver), e repeitar a sequência destes parâmetros na chamada SUBMIT_REQUEST, ou seja, no caso da chamada via código, a sequencia dos parâmetros deve ser igual a sequencia cadastrada na definição do concorrente do EBS.
O que deve ficar claro, também, é que os parâmetros definidos no cadastro do concorrente (no EBS) são os equivalentes Argument1 a ArgumentNN da função.
Outro ponto que deve ser observado, é que alguns parâmetros utilizados nas chamadas de funções e procedimentos têm a diretriz NOCOPY. Parâmetros deste tipo não podem receber valores diretamente na chamada. Nestes casos, precisamos declarar variáveis para receber ou enviar valores, e utilizar as mesmas nas chamadas dos objetos.
Falows!