quinta-feira, 9 de agosto de 2012

Tratando caracteres HTML em Oracle PL/SQL


O pacote dbms_xmlgen traz diversas funcionalidades para tratamentos de sistemas web, a função que abordarei nesse post é a convert. Essa função é utilizada para conversão de caracteres HTML. Para isso, basta no segundo argumento informar 0=codificar, 1=Decodificar.

0=codificar - por exemplo: troca ‘<’ por ‘$lt;’

SQL> SELECT dbms_xmlgen.convert('Please escape <this> tag', 0) fun from dual;

FUN
------------------------------------------------------------------
Please
escape &lt;this&gt; tag

1=Decodificar - por exemplo: troca ‘$lt;’ por  ‘<’;

SQL> SELECT dbms_xmlgen.convert('Please escape &lt;this&gt; tag', 1) fun from dual;

FUN------------------------------------------------------------------
Please escape <this> tag

Para mais informações:

That´s all folks

segunda-feira, 5 de dezembro de 2011

DBMS_SCHEDULER Oracle 10g

DEFINIÇÃO
À partir da versao 10g do banco de dados, a Oracle disponibilizou um novo pacote para criação de jobs/schedulers o DBMS_SCHEDULER. Esse pacote não vem para substituir a antiga DBMS_JOB, mas sim para ampliar sua funcionalidade.
Nesse post vou falar um pouco sobre as principais funcionalidades desse novo pacote.

DIFERENÇA EM RELAÇÃO À DBMS_JOB
A principal diferença em relação à DBMS_JOB, é que agora é possível ter uma estrutura mais modular, onde é possível ter o programa/tarefa/rotina que será executada separada do tempo de execução(periodicidade). Assim, temos agora 3 novos termos, programa, schedule e job.

PROGRAMA
Um programa é a tarefa que será executada, seja ela um bloco anônimo, uma Stored Procedure ou um executável do sistema operacional. Ao criar um programa, não se define quando o mesmo será executado, apenas faz-se o registro do quê será executado.
Exemplo:

-- Criando um programa de teste
BEGIN
  -- Bloco PL/SQL .
  DBMS_SCHEDULER.create_program (
    program_name   => 'test_plsql_block_prog',
    program_type   => 'PLSQL_BLOCK',
    program_action => 'BEGIN DBMS_STATS.gather_schema_stats(''SCOTT''); END;',
    enabled        => TRUE,
    comments       => 'Programa para coletar as estatísticas do usuário SCOTT''s usando um bloco PL/SQL.');

  -- Shell Script.
  DBMS_SCHEDULER.create_program (
    program_name        => 'test_executable_prog',
    program_type        => 'EXECUTABLE',
    program_action      => '/u01/app/oracle/dba/gather_scott_stats.sh',
    number_of_arguments => 0,
    enabled             => TRUE,
    comments            => 'Programa para coletar as estatísticas do usuário SCOTT''s usando shell script.');

  -- Stored Procedure com argumentos.
  DBMS_SCHEDULER.create_program (
    program_name        => 'test_stored_procedure_prog',
    program_type        => 'STORED_PROCEDURE',
    program_action      => 'DBMS_STATS.gather_schema_stats',
    number_of_arguments => 1,
    enabled             => FALSE,
    comments            => 'Programa para coletar as estatísticas do usuário SCOTT''s usando uma stored procedure.');

  -- Definindo um argumento para a stored procedure criado anteriormente
  DBMS_SCHEDULER.define_program_argument (
    program_name      => 'test_stored_procedure_prog',
    argument_name     => 'ownname',
    argument_position => 1,
    argument_type     => 'VARCHAR2',
    default_value     => 'SCOTT');

  -- habilitando o programa criado anteriormente
  DBMS_SCHEDULER.enable (name => 'test_stored_procedure_prog');
END;
/
PL/SQL procedure successfully completed.

Podemos em seguida consultar os programas criados no bloco acima:

SELECT owner, program_name, enabled FROM dba_scheduler_programs;

OWNER                          PROGRAM_NAME                   ENABL
------------------------------ ------------------------------ -----
SYS                            PURGE_LOG_PROG                 TRUE
SYS                            GATHER_STATS_PROG              TRUE
SYS                            TEST_PLSQL_BLOCK_PROG          TRUE
SYS                            TEST_EXECUTABLE_PROG           TRUE
SYS                            TEST_STORED_PROCEDURE_PROG     TRUE

5 rows selected.

Podemos verificar na 3ª coluna o status do programa criado, todos são criados como enabled por default. É possível desabilitá-los através da procedure DBMS_SCHEDULER.DISABLE.
Para eliminar um programa, basta executar a procedure abaixo:

   
DBMS_SCHEDULER.drop_program (program_name => 'test_plsql_block_prog');

SCHEDULE
Um schedule define um horário ou período para execução de um/vários programa(s). Essa é a grande sacada dessa nova estrutura de jobs da versão 10g, é possível associar um schedule a mais de programa, o que facilita a administração.
Para criar um schedule, usamos os exemplos abaixo:

-- Criando o schedule.
BEGIN
  DBMS_SCHEDULER.create_schedule (
    schedule_name   => 'test_hourly_schedule',
    start_date      => SYSTIMESTAMP,
    repeat_interval => 'freq=hourly; byminute=0',
    end_date        => NULL,
    comments        => 'Repetir a cada hora, por tempo indeterminado.');
END;
/

PL/SQL procedure successfully completed.

Para consultarmos se um schedule foi realmente criado, utilizamos a query abaixo:

SELECT owner, schedule_name FROM dba_scheduler_schedules;

OWNER                          SCHEDULE_NAME
------------------------------ ------------------------------
SYS                            DAILY_PURGE_SCHEDULE
SYS                            TEST_HOURLY_SCHEDULE

2 rows selected.

Para eliminar um schedule, utilizamos o exemplo abaixo:

BEGIN
  DBMS_SCHEDULER.drop_schedule (schedule_name => 'TEST_HOURLY_SCHEDULE');
END;
/

PL/SQL procedure successfully completed.

JOB
A essas alturas você já deve estar se perguntado: "Pra tanto trabalho pra se criar um job, sendo que até hoje eu criei tudo com uma única linha de comando?". Calma, existe também a possibilidade de criar tudo em um único passo, tudo como era antigamente, a diferença é que agora quando for utilizado a built-in DBMS_SCHEDULER, o job já vai ser criado modularizado, ou seja, tanto a rotina quando o período podem ser reaproveitados.
Vamos ver um pouco mais sobre a variação de formas de se criar um job:

BEGIN
  -- Job criado totalmente através da procedure CREATE JOB.
  DBMS_SCHEDULER.create_job (
    job_name        => 'test_full_job_definition',
    job_type        => 'PLSQL_BLOCK',
    job_action      => 'BEGIN DBMS_STATS.gather_schema_stats(''SCOTT''); END;',
    start_date      => SYSTIMESTAMP,
    repeat_interval => 'freq=hourly; byminute=0',
    end_date        => NULL,
    enabled         => TRUE,
    comments        => 'Job criado totalmente através da procedure CREATE JOB.');

  -- Job criado usando um programa e schedule existentes.
  DBMS_SCHEDULER.create_job (
    job_name      => 'test_prog_sched_job_definition',
    program_name  => 'test_plsql_block_prog',
    schedule_name => 'test_hourly_schedule',
    enabled       => TRUE,
    comments      => 'Job criado usando um programa e schedule existentes.');

  -- Job criado por um programa existente e um schedule inline(não existente).
  DBMS_SCHEDULER.create_job (
    job_name        => 'test_prog_job_definition',
    program_name    => 'test_plsql_block_prog',
    start_date      => SYSTIMESTAMP,
    repeat_interval => 'freq=hourly; byminute=0',
    end_date        => NULL,
    enabled         => TRUE,
    comments        => 'Job criado por um programa existente e um schedule inline(não existente).');

  -- Job criado por um programa e um schedule inline(não existentes).
  DBMS_SCHEDULER.create_job (
     job_name      => 'test_sched_job_definition',
     schedule_name => 'test_hourly_schedule',
     job_type      => 'PLSQL_BLOCK',
     job_action    => 'BEGIN DBMS_STATS.gather_schema_stats(''SCOTT''); END;',
     enabled       => TRUE,
     comments      => 'Job criado por um programa e um schedule inline(não existentes).');
END;
/

PL/SQL procedure successfully completed.

Para confirmar se os jobs foram criados, usamos a query abaixo:

SELECT owner, job_name, enabled FROM dba_scheduler_jobs;

OWNER                          JOB_NAME                       ENABL
------------------------------ ------------------------------ -----
SYS                            PURGE_LOG                      TRUE
SYS                            GATHER_STATS_JOB               TRUE
SYS                            TEST_FULL_JOB_DEFINITION       TRUE
SYS                            TEST_PROG_SCHED_JOB_DEFINITION TRUE
SYS                            TEST_PROG_JOB_DEFINITION       TRUE
SYS                            TEST_SCHED_JOB_DEFINITION      TRUE

6 rows selected.

Ou seja, através dos exemplos acima, vemos que é possível criar os jobs com programas e schedules existentes ou não. Complementando a resposta à questão do início do tópico, eu adiciono uma  outra pergunta: "Você pretende reutilizar o período ou a rotina que será executada?" se a sua resposta foi não, continue utilizando a boa e velha DBMS_JOB, se foi sim....

Para excluir um job, utilizamos o bloco abaixo:

BEGIN
    DBMS_SCHEDULER.drop_job (job_name => 'test_full_job_definition');
END;


CONTROLE DE EXECUÇÃO DE JOBS
Um job tem sua execução de forma assíncrona, ou seja, é o próprio banco quem controla sua execução de acordo com os atributos definidos na criação do mesmo. Porém, é possível ter um controle manual, como abaixo:

BEGIN
  -- Forçando a execução de um job
  DBMS_SCHEDULER.run_job (job_name            => 'test_full_job_definition',
                          use_current_session => FALSE);

  -- Parando a execução de um job
  DBMS_SCHEDULER.stop_job (job_name => 'test_full_job_definition, test_prog_sched_job_definition');
END;
/

PRIVILÉGIOS
Nessa versão de banco, uma nova rule foi criado para controlar o Scheduler, o SCHEDULER_ADMIN. Esse grant inicialmente só é concedido ao DBA e permite ao mesmo qualquer ação sobre um Job criado por ele ou por qualquer outro usuário. Esse grant é poderoso, portanto deve-se ter muito cuidado ao concedê-lo aos usuários. Porém, existe também a rule  MANAGE SCHEDULER, que permite ao usuário consultar atributos de um Job ou alterá-los através das procedures GET_SCHEDULER_ATTRIBUTESET_SCHEDULER_ATTRIBUTE respectivamente.


Artigos relacionados:
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_sched.htm
http://www.oracle-base.com/articles/10g/Scheduler10g.php


That´s all Folks

eXtreme Go Horse (XGH)

1- Pensou, não é XGH. XGH não pensa, faz a primeira coisa que vem à mente. Não existe segunda opção, a única opção é a mais rápida.

2- Existem 3 formas de se resolver um problema, a correta, a errada e a XGH, que é igual à errada, só que mais rápida. XGH é mais rápido que qualquer metodologia de desenvolvimento de software que você conhece (Vide Axioma 14).

3- Quanto mais XGH você faz, mais precisará fazer. Para cada problema resolvido usando XGH, mais uns 7 são criados. Mas todos eles serão resolvidos da forma XGH. XGH tende ao infinito.

4- XGH é totalmente reativo. Os erros só existem quando aparecem.

5- XGH vale tudo, só não vale dar o toba. Resolveu o problema? Compilou? Commit e era isso.

6- Commit sempre antes de update. Se der m*****, a sua parte estará sempre correta.. e seus colegas que se fodam.

7- XGH não tem prazo. Os prazos passados pelo seu cliente são meros detalhes. Você SEMPRE conseguirá implementar TUDO no tempo necessário (nem que isso implique em acessar o BD por um script malaco).

8- Esteja preparado para pular fora quando o barco começar a afundar… ou coloque a culpa em alguém ou algo.
Pra quem usa XGH, um dia o barco afunda. Quanto mais o tempo passa, mais o sistema vira um monstro. O dia que a casa cair, é melhor seu curriculum estar cadastrado na APInfo, ou ter algo pra colocar a culpa.

9- Seja autêntico, XGH não respeita padrões. Escreva o código como você bem entender, se resolver o problema, commit e era isso.

10- Não existe refactoring, apenas rework. Se der m*****, refaça um XGH rápido que solucione o problema. O dia que o rework implicar em reescrever a aplicação toda, pule fora, o barco irá afundar (Vide Axioma 8).

11- XGH é totalmente anárquico.A figura de um gerente de projeto é totalmente descartável. Não tem dono, cada um faz o que quiser na hora que os problemas e requisitos vão surgindo (Vide Axioma 4).

12- Se iluda sempre com promessas de melhorias. Colocar TODO no código como uma promessa de melhoria ajuda o desenvolvedor XGH a não sentir remorso ou culpa pela cagada que fez. É claro que o refactoring nunca será feito (Vide Axioma 10).

13- XGH é absoluto, não se prende à coisas relativas.Prazo e custo são absolutos, qualidade é totalmente relativa. Jamais pense na qualidade e sim no menor tempo que a solução será implementada, aliás… não pense, faça!

14- XGH é atemporal. Scrum, XP… tudo isso é modinha. O XGH não se prende às modinhas do momento, isso é coisa de v****. XGH sempre foi e sempre será usado por aqueles que desprezam a qualidade.

15- XGH nem sempre é POG. Muitas POG’s exigem um raciocínio muito elevado, XGH não raciocina (Vide Axioma 1).

16- Não tente remar contra a maré. Caso seus colegas de trabalho usam XGH para programar e você é um coxinha que gosta de fazer as coisas certinhas, esqueça! Pra cada Design Pattern que você usa corretamente, seus colegas gerarão 10 vezes mais código podre usando XGH.

17- O XGH não é perigoso até surgir um pouco de ordem.Este axioma é muito complexo, mas sugere que o projeto utilizando XGH está em meio ao caos. Não tente por ordem no XGH (Vide Axioma 16), é inútil e você pode jogar um tempo precioso no lixo. Isto fará com que o projeto afunde mais rápido ainda (Vide Axioma 8). Não tente gerenciar o XGH, ele é auto suficiente (Vide Axioma 11), assim como o caos.

18- O XGH é seu brother, mas é vingativo.Enquanto você quiser, o XGH sempre estará do seu lado. Mas cuidado, não o abandone. Se começar um sistema utilizando XGH e abandoná-lo para utilizar uma metodologia da moda, você estará fudido. O XGH não permite refactoring (vide axioma 10), e seu novo sistema cheio de frescurites entrará em colapso. E nessa hora, somente o XGH poderá salvá-lo.

19- Se tiver funcionando, não rela a mão. Nunca altere, e muito menos questione um código funcionando. Isso é perda de tempo, mesmo porque refactoring não existe (Vide Axioma 10). Tempo é a engrenagem que move o XGH e qualidade é um detalhe desprezível.

20- Teste é para os fracos. Se você meteu a mão num sistema XGH, é melhor saber o que está fazendo. E se você sabe o que está fazendo, vai testar pra que? Testes são desperdício de tempo, se o código compilar, é o suficiente.

21- Acostume-se ao sentimento de fracasso iminente.O fracasso e o sucesso andam sempre de mãos dadas, e no XGH não é diferente. As pessoas costumam achar que as chances do projeto fracassar utilizando XGH são sempre maiores do que ele ser bem sucedido. Mas sucesso e fracasso são uma questão de ponto de vista. O projeto foi por água abaixo mas você aprendeu algo? Então pra você foi um sucesso!

22- O problema só é seu quando seu nome está no Doc da classe. Nunca ponha a mão numa classe cujo autor não é você. Caso um membro da equipe morra ou fique doente por muito tempo, o barco irá afundar! Nesse caso, utilize o Axioma 8.



That´s all Folks!

quinta-feira, 24 de novembro de 2011

Como configurar modo debug no JDeveloper com OC4J 10.1.3.5 remoto

Resolvi montar esse blog após uma certa dificuldade em "debugar" um webservice criado utilizando o JDeveloper e OC4J 10.1.3.5.
Em primeiro lugar é necessário iniciar o OC4J em modo debug, para isso precisamos da linha de comando abaixo:
java -Xdebug -Xnoagent -Djava.compiler=NONE 
-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=4000 -jar oc4j.jar


Porém, para facilitar a inicialização em modo debug, é possível editar o arquivo oc4j.cmd, conforme postado anteriormente aqui.

O comando acima pode ser iniciado diretamente pelo prompt, ou para facilitar pode ser criada uma "external tool", veja passos abaixo:
1) Entre na opção External Tool:

2) Crie uma nova entrada External Tool:

3) Agora preencha a linha de comando, conforme exemplo abaixo:

Pronto, agora basta escolher a opção criada no menu External Tool:

Feito isso, basta verificar no log sua inicialização:

Primeira etapa concluída, agora vamos iniciar o modo debug.
1) Escolha o botão de debug na barra de ferramentas, e vá em "Manage Run Configuration"
2) Preencha os campos de acordo com as configurações pré-definidas na inicialização do server, e defina  o protocolo como "Attach to JDPA".

Confira no log se o JDeveloper foi conectado ao OC4J corretamente

Pronto, agora basta definir seus breakpoints e rodar a aplicação.

That´s all Folks!

Como criar uma entrada para debug editando o arquivo oc4j.cmd

Para  iniciar o OC4J em modo debug precisamos incluir a linha de comando abaixo:
java" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=4000 -jar oc4j.jar



Agora precisamos localizar o arquivo oc4j.cmd, que fica no path abaixo:
%OC4J_HOME\%oc4j_extended_101350\bin


Em seguida seguem os passos para edição do arquivo:



1) Criar uma variável para receber a porta de escuta do modo debug. No exemplo abaixo, a variável foi iniciado com 4000 (valor default), pois caso a mesma não seja informada, esse será o valor para a porta.

2) Incluir validação para verificar se o parâmetro de debug ("-debug") foi informado
3) Alterar as informações do help do comando, explicando como passar o novo parâmetro
4) Criar a entrada de tratamento do parâmetro de debug
5) Entrada para execução da linha de comando de debug:


Pronto, basta salvar o arquivo e chamá-lo na linha de comando como abaixo:
oc4j.cmd -debug -port 4000

Thta´s all folks!