sábado, 1 de agosto de 2009

Chamando Metódo com vários parâmetros através de um click em uma Imagem.

Depois de muito tempo sem postar, estamos aqui novamente.

Hoje vamos mostrar como é feito o seguinte cenário:
Imaginem uma tela principal, onde a mesma contém uma Tabela com diversas colunas, e uma das colunas é um campo Imagem, onde eu tenha que chamar algum evento através de um click como a imagem abaixo.




O primeiro passo é colocarmos uma coluna em nossa Table ou AdvancedTable, com um objeto Image. No mesmo adicionar na propriedade Image URL o nome da imagem.
Obs. Segue o link onde contém todas as imagens e seus nomes que existem no servidor o Oracle EBS: http://www.oracle.com/technology/tech/blaf/specs/iconList.html

Em seguida, vamos alterar a propriedade da imagem "Action Type" para fireAction, e altere o atributo Event para um texto mais familiar ao evento. Para passar parâmetros que estão no View Object da nossa tabela, vá na propriedade da imagem "Parameters" e clique no mesmo, abrirá uma form como a imagem abaixo:



Assim podemos passar quantos parâmetros necessitarmo, lembrando que o "Name" é o nome que vamos pegar no Controller, e o "Value" é o ${oa..}.

Para recuperarmos os mesmos dentro do Controller e passarmos para o nosso Appication Module, é bastante simples.

No processFormRequest do controller da página colocamos o seguinte código:



Assim quando clicarmos na imagem ela irá passar os parâmetros do VO, onde pegaremos no Controller e repassaremos para nosso Appication Module, assim podendo fazer as ações que desejarmos como Alterar, Excluir, Processar, Chamar Concurrent e etc...

Um grande abraço e até a próxima.

terça-feira, 2 de junho de 2009

OAF Logging - Escrevendo Log de Erros no OAF

Boa tarde pessoal!

Hoje comentarei sobre o suporte do OAF a uma boa prática de desenvolvimento que é o tratamento correto de erros inesperados. Sabemos que todo sistema Java está sujeito a erros inesperados, sejam eles a falta de permissão para escrever um arquivo em um diretório do sistema operacional, ou então o famigerado NullPointerException, ou até mesmo as SQLExceptions que tratamos na chamada de procedures. No entanto, sabemos também que um erro como o abaixo pode ser extremamente interessante para o DBA ou desenvolvedor, porém não diz nada para o usuário final:

Erro: ORA-04068: Existing State of Packages has been Discarded

Portanto, as boas práticas de desenvolvimento ditam que em um caso desses, devemos silenciosamente gravar este erro em um local que os DBAs ou desenvolvedores monitorem, fazendo com que o mesmo chegue a quem é de interesse, porém mostrar uma mensagem mais amigável ao usuário final, algo como "Ocorreu um erro inesperado, favor contatar o Administrador do Sistema". Este procedimento é chamado de
Logging.

Em uma aplicação java comum, temos o suporte nativo da plataforma para o Logging e também alguns conhecidos frameworks de logging em arquivo ou tela (LOG4J, Commons Logging etc). Agora, trazendo para o nosso mundo Oracle, como podemos prover essa funcionalidade via OA Framework? Poderiamos obviamente utilizar os sistemas acima de logging, porém o OAF nos permite utilizar a ferramenta padrão de monitoramento do aplicativo, chamada Oracle Diagnostics. É um procedimento simples, vamos lá!

Passo 1: Codificar o Logging
O primeiro passo é marcar os pontos de logging no código fonte para que seja exibido pelo Diagnostics. Isto é feito por uma API presente nos objetos OAPageContext, para logging na camada Controller, e OAApplicationModule, para logging no modelo. Por exemplo, para logar uma exceção inesperada no modelo, veja um trecho de código no Application Module:


public void execPack() {
CallableStatement call = new CallableStatement("package",1);
try {
call.execute();
} catch (SQLException sqle) {
if (this.isLoggingEnabled(UNEXPECTED)) {
this.writeDiagnostics(this, sqle.getMessage(), UNEXPECTED);
}
throw new OAException("FND","WF_UNEXPECTED_MESSAGE");

}
}


O código acima faz uma checagem para ver se o nível UNEXPECTED está habilitado no Oracle Diagnostics (veremos como mudar isso nos passos seguintes). Caso afirmativo, irá logar a exceção técnica, logo em seguida disparamos a costumeira OAException, porém com a mensagem padrão WF_UNEXPECTED_MESSAGE que mostrará: "Ocorreu um erro inesperado, favor contatar o Administrador do Sistema". Bem melhor!

Passo 2: Habilitar o perfil FND: Diagnóstico
Quando quiser acompanhar o logging, o administrador do sistema deve trocar o valor do perfil "FND: Diagnóstico" para SIM. Este perfil habilitará, ao lado dos links do topo da tela como Logout, Retornar ao portal etc., um link chamado "Diagnóstico". Ao clicar neste link, aparecerá um dropdown. Escolha a opção "Mostrar Log na Tela", e ele irá perguntar o nível desejado, escolha então "Inesperado (6)". Este nível corresponde ao Logging do tipo UNEXPECTED.



Passo 3: Acessar a página desejada
Ao acessar a página desejada, perceberá que no rodapé da página aparecerá o Logging, no seguinte formato:

[356]:UNEXPECTED:[custom.oracle.apps.xxhr.test.TestAMImpl]:Existing State of Packages has been discarded.


Este tipo de logging em tela é interessante para Teste e Desenvolvimento. Em breve faremos um post explicando como configurar esta mesma funcionalidade, porém gravando em arquivos texto no servidor (para o Logging na base de Produção)
Até a próxima pessoal!

terça-feira, 12 de maio de 2009

OAF - Numeração Automática via Sequence - Sem pular números!

Olá pessoal!

O uso de Sequences para geração de IDs no OAF é, por padrão, feito sobrescrevendo-se o método create() do Entity Object, e dentro dele instanciando um objeto oracle.jbo.SequenceImpl. Um exemplo básico seria:

public void create() {
SequenceImpl seq = new SequenceImpl("MINHA_SEQUENCE");
this.setColunaId(seq.getValue());
}

No entanto, o método create() é executado toda vez que uma linha é criada no VO, ou seja, se o usuário clicar em "Cancelar" e dispensar a linha, a sequence já foi incrementada (o SequenceImpl roda SEQUENCE.NEXTVAL). Portanto, a dúvida é:
Como gerar identificadores via Sequence sem pular números?

A resposta é o método postChanges(), também pertencente ao Entity Object. Este método é chamado somente após todas as validações serem concluídas, alguns momentos antes de inserir a linha no banco. Portanto, é garantia de que qualquer coisa executada neste método só vai rodar se a linha for realmente ser inserida no banco. Por exemplo, escreva isto no seu EntityImpl:

public void postChanges() {
SequenceImpl seq = new SequenceImpl("MINHA_SEQUENCE");
this.setColunaId(seq.getValue());
}

Desta forma, o NEXTVAL na sequence só será chamado quando o framework tiver CERTEZA que a linha vai ser efetivada no BD, eliminando o efeito indesejável de "pulos" no meio da numeração sequencial e que pode ser proibido em alguns casos (ex.: Números de Nota Fiscal).

Até a próxima!

sábado, 11 de abril de 2009

Upload de Arquivos com Self Service E-Business Suite (OAF)

Oi Pessoal!

Seguindo a série de posts sobre OAF, hoje a dica é sobre upload de arquivos via Self-Service do Oracle E-Business Suite.

Em aplicações baseadas em Forms, a Oracle previu a necessidade de anexar documentos a uma determinada entidade, por exemplo anexar a NF digitalizada ao documento fiscal dentro do RI. Para isso, habilita-se um cadastro de Categorias de Anexo e Entidades, para que seja habilitado o botão de anexar (ícone do Clips) dentro do Forms. Ao habilitar este botão, clicando nele o usuário pode fazer o Upload de um arquivo, que é automaticamente anexo ao documento em questão. Isto é feito internamente nas tabelas FND_LOBS (guarda o conteúdo do arquivo em BLOB), FND_DOCUMENTS (dados do documento) e FND_ATTACHED_DOCUMENTS (Associação do DOCUMENT_ID com o PK1_VALUE que representa a chave primária da entidade origem, por exemplo, INVOICE_ID).

Em aplicações OAF, também é possível ativar essa funcionalidade, mesmo sem fazer o cadastro de Entidade mencionado acima. Por exemplo, podemos adicionar um Link de Anexos (Ícone de Clips) em uma coluna de uma Table ou AdvancedTable. Para isto, basta adicionarmos um item do tipo "AttachmentImage" dentro da tabela, conforme abaixo:



Como vocês podem notar acima, o AttachmentImage tem alguns sub-elementos, a saber:

EntityMap (PlayFuncPKMap): é o que define a entidade a qual o anexo será subordinado. no atributo "Entity" devemos inventar um nome que será usado como referência, por exemplo, PlayFuncPK. Todas as telas OAF que tiverem link de anexos para esta mesma entidade (EO) devem usar essa mesma referência.

PrimaryKeys (PlayFuncPK): define qual a chave primária da entidade que deve ser gravada no campo PK1_VALUE da FND_ATTACHED_DOCUMENTS, para guardar a associação anexo/registro. Informe no campo "ViewAttribute" o atributo do VO que é a chave primária do EO correspondente.

CategoryMap (PlayFuncCatMap): define quais categorias de anexo são permitidas para esta entidade. Informe no campo "Category" o nome interno da categoria criada (campo NAME da tabela FND_DOCUMENT_CATEGORIES). Caso não queira limitar as categorias possíveis, é só não incluir o CategoryMap debaixo do EntityMap que ele libera todas.

Após estes simples passos, a tela ficará conforme abaixo, mostrando um ícone de Clips (para visualizar os anexos existentes) e um ícone de Mais ao lado (para adicionar o anexo):



Ao clicar no ícone de Mais, segue-se para a tela de adicionar anexo (core), podendo adicionar anexos do tipo Link, Texto Curto ou então Arquivos (botao browse):


Ao clicar no ícone de Clips, vemos a tabela de anexos:


Abraços, e até a próxima!

sábado, 4 de abril de 2009

AdvancedTable dentro de AdvancedTable

Bom Dia Pessoal,

Hoje, após um grande período sem posts como o Thiago mesmo falou anteriormente, vamos voltar com alguns assuntos bastante interessante referente a OAF (Oracle Applications Framework).
Para quem não conhece, OAF é a tecnologia que a Oracle utiliza para Customização e Desenvolvimento de Páginas WEB dentro do ERP (eBS).
E como é uma recomendação da própria Oracle a não utilização do Forms nas próximas releases, vamos iniciar uma sessão de posts interessantes para quem quer iniciar ou mesmo os desenvolvedores mais experientes. O Post de hoje é muito interesasnte, pois se trata de uma Página contendo uma AdvancedTable dentro de outra AdvancedTable.
Nosso objetivo é criar uma página onde a visualização fique bastante facilitada, por conta do Máster-Detail entre as tabelas, como a imagem abaixo.


Primeiro Passo: Nesse caso teremos dois ViewObjects (VO) ligados através de um ViewLink (VL). Imaginem uma tabela de Períodos e outra de Trabalhos realizados, onde a ligação entre as mesmas seja o atributo PeriodId, existe vários trabalhos realizados para cada período. Seu ApplicationModule (AM) vai ficar dessa forma:
Segundo Passo: Feito a amarração entre os VO´s, vamos criar a página.
Crie uma página comum Oracle Applications (OA), na mesma você pode criar uma região para que a tabela fique mais organizada. Adicione uma AdvancedTable dentro da Região criada, e atribua suas respectivas colunas referente ao VO de Períodos conforme sua necessidade, feito isso vamos clicar com o botão direto na mesma e habite a opção “detail”.
Dentro do “detail” vamos adicionar outra AdvancedTable que será baseada no VO de trabalhos Realizados. A imagem abaixo irá ilustrar a estrutura da página.


Terceiro Passo: Criar o Controller (CO) da página, onde será criado a amarração entre os VO´s através do VL.
No método do controller “processRequest”, vamos colocar o seguinte código:

OAWebBean outerTable = (OAWebBean)webBean.findChildRecursive("AdvancedTableRN");
OAWebBean innerTable = (OAWebBean)webBean.findChildRecursive("SubAdvancedTableRN");
if (outerTable != null)
{
//temos que setar exatamento o atributo do VO
outerTable.setAttributeValue(CHILD_VIEW_ATTRIBUTE_NAME,"PeriodId");
// temos que setar exatamento o valor do VL que está no AM
outerTable.setAttributeValue(VIEW_LINK_NAME,"PeriodToWorkRealizedVL");
}
if (innerTable != null)
{
//temos que setar exatamento o atributo do VO
innerTable.setAttributeValue(CHILD_VIEW_ATTRIBUTE_NAME,"PeriodId");
// temos que setar exatamento o valor do VL que está no AM
innerTable.setAttributeValue(VIEW_LINK_NAME," PeriodToWorkRealizedVL ");
}

Feito esses 3 passos acima, é só rodar a página e visualizar o resultado.

Esse foi mais um post da série OAF, um grande abraço e boa diversão.