Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução...

81
Manual de Técnicas Construção de DBOs 2.0 Junho/2005 Versão 2.0 Não homologado

Transcript of Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução...

Page 1: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

Manual de Técnicas

Construção de DBOs 2.0

Junho/2005 Versão 2.0

Não homologado

Page 2: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

Copyright © 1998 DATASUL S.A. Todos os direitos reservados.

Nenhuma parte deste documento pode ser copiada, reproduzida, traduzida ou

transmitida por qualquer meio eletrônico ou mecânico, na sua totalidade ou em

parte, sem a prévia autorização escrita da DATASUL S.A., que se reserva o

direito de efetuar alterações sem aviso prévio. A DATASUL S.A não assume

nenhuma responsabilidade pelas conseqüências de quaisquer erros ou

inexatidões que possam aparecer neste documento.

DATASUL S.A.

Av. Santos Dumont, 831, Joinville, SC, CEP 89.222-900

Page 3: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

i

Índice

CAPÍTULO 1 Conceitos ................................................................................ 5

CAPÍTULO 2 Concepção do DBO ............................................................... 9

DBO de Entidade ......................................................................................... 11 DBOs X APIs .............................................................................................. 19

Qual a função do DBO e da API.................................................... 19

Como ficam as APIs existentes atualmente ................................... 20

Quando criar API ou DBO............................................................. 20

CAPÍTULO 3 Como construir o DBO ........................................................ 21

Acesso a Banco de Dados ............................................................................ 21 Arquitetura do DBO .................................................................................... 21

Definições ...................................................................................... 21

Objetos de trabalho ........................................................................ 22

Métodos Básicos ............................................................................ 22

Métodos de Negócio ...................................................................... 22

Override de Métodos ..................................................................... 23 Construção do DBO ..................................................................................... 25

Criar programa e include de DBO a partir do template ................. 25

Acertar os preprocessadores padrão .............................................. 25

Definição da temp-table de comunicação ...................................... 26

Definição da Query ........................................................................ 27

Definição das Aberturas de Query e setConstraint ........................ 27

Criação do método goToKey ......................................................... 30

Criação do método linkTo<Description> ...................................... 31

Criação do método getKey ............................................................ 32

Fazer validações comuns ao create e update do registro ............... 32

Page 4: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

ii

Verificar ocorrência de chave duplicada ou outras validações

referentes somente a criação de registros ...................................... 33

Criação de erros ............................................................................. 34

Definição das Aberturas de Query e setConstraint com Join entre

Tabelas ........................................................................................... 36

Criação do método setSecurityConstraint ..................................... 37 XML no DBO .............................................................................................. 38

Informar os pré-processadores para XML Producer ..................... 38

Informar os pré-processadores para XML Receiver ...................... 39 Utilizando Serviços no DBO ....................................................................... 40

Serviço de Banco ........................................................................... 40

Serviço de Autenticação ................................................................ 41

Serviço de Customização ............................................................... 41

Serviço de Segurança ..................................................................... 43 Redução do Tamanho do DBO .................................................................... 43

Uso de sub-programas ................................................................... 44 Considerações Gerais ................................................................................... 44

CAPÍTULO 4 Convertendo BO 1.1 para DBO 2.0 ..................................... 46

Relação entre métodos ................................................................... 46

Criar o novo DBO.......................................................................... 48

Transferir lógicas dos métodos básicos do DBO 1.1 para o DBO

2.0 .................................................................................................. 48

CAPÍTULO 5 Convertendo SmartObjects para DBO 2.0 ......................... 57

Criar o novo DBO.......................................................................... 57

Transferir lógicas dos métodos dos SmartObjects para o DBO 2.0

....................................................................................................... 57

CAPÍTULO 6 Serviços Padrão ................................................................... 67

Serviço de Banco ......................................................................................... 68 Serviço de Customização ............................................................................. 68 Serviço de Erros ........................................................................................... 69 Serviço de Segurança ................................................................................... 71 Serviço de Message Broker ......................................................................... 73

sendMessage .................................................................................. 73

getSendMode ................................................................................. 74 Contexto de Sessão WEB no DBO .............................................................. 75

Page 5: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

iii

CAPÍTULO 7 Técnicas ................................................................................ 77

Melhorar Performance em Bancos Oracle ................................................... 77

Page 6: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características
Page 7: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

5

CAPÍTULO 1

Conceitos

O objetivo deste documento é apresentar os métodos para codificação de

regras de negócio, a fim de que possamos utilizá-las nas seguintes situações:

Internamente: as equipes de desenvolvimento podem acessar regras de

negócio de outros módulos;

Clientes/Parceiros: podem acessar estas regras sem necessidade de

conhecimento profundo da base de dados;

Diferentes Interfaces: com a necessidade do desenvolvimento para WEB

surgiu a necessidade do reaproveitamento das regras de negócio entre GUI

e WEB. Além disso, devem surgir outras interfaces que também viriam a

reutilizar estas regras de negócio.

Para codificação destas e posterior reaproveitamento foi definida uma

arquitetura de desenvolvimento de aplicações chamada de Datasul Business

Objects (DBO). Neste manual, estaremos descrevendo o que é o DBO, a

relação com APIs atuais, como construir, etc.

A arquitetura DBO foi definida com o objetivo de separar a camada de lógica

de apresentação (interface com usuário) da camada de lógica da aplicação

(regras de negócio). Assim, podemos usar a mesma lógica de aplicação para

diferentes interfaces, as quais destacamos: GUI, CHUI, WEB e Java.

O DBO é um programa Progress que contém a lógica de negócio e acesso a

dados para uma tabela do banco de dados.

Introdução

Definição

Page 8: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

6

WEB

GUI

CHUI

Java

BO Database

Interface Lógica Dados

As características desta arquitetura são:

A camada cliente pode ser escrita em Progress 4GL, Java ou qualquer

linguagem que trabalhe com ActiveX. Esta camada pode ser escrita tanto

pela Datasul como por qualquer outra empresa ou pessoa, por isso não é

possível confiar na integridade dos dados fornecidos por ela ao DBO;

O DBO deverá ser a forma da camada cliente ter acesso ao banco de dados

e por este motivo é função dele garantir a segurança e integridade dos

dados:

Segurança: Significa que o DBO deve usar um mecanismo seguro de

autenticação para determinar quais registros podem ser acessados pelo

cliente, ou em outras palavras não é o cliente que determina ao DBO

os registros que podem ou não ser acessados;

Integridade: Como o cliente acessa os dados através do DBO, este é

responsável por verificar se as informações passadas por ele estão

consistentes e podem ser gravados no banco de dados. Ele deve

também realizar o trabalho de garantia da integridade referencial.

Arquitetura

Características da Arquitetura

Page 9: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 1 Conceitos 7

As características gerais de um DBO são:

É uma evolução das APIs dos produtos Datasul (adiante é explicada a

diferença entre DBO e API);

Permite o reaproveitamento de regras de negócio;

contém a regra de negócio referente a um objeto, podendo este objeto ser

uma tabela ou um processo;

Normalmente, trabalha com temp-tables para troca de informações com a

interface;

É um programa Progress executado de forma persistente;

Um DBO deve fornecer a relação de seus métodos (procedures internas

que contém as regras de negócio).

O que são as regras de negócio que queremos reaproveitar ?

São todas as operações que podemos realizar em um registro. Estas operações

podem ser, por exemplo:

Validações do campo: não pode ser espaços, não pode ser 0, can-find em

outra tabela, faixa de valores;

Validações no registro: validações que envolvam mais de um campo no

registro;

Transações: conjunto de alterações no banco de dados que devem ser

feitas por completo ou não;

Validações no registro por causa do Dataserver: por exemplo, o banco de

dados Progress não tem restrição quanto ao tamanho do campo, mas no

caso do Dataserver Oracle se deve fazer esta validação nos registros.

Estas regras não podem estar na interface (tela). Devem estar no DBO

permitindo o reaproveitamento. Na interface ficam apenas as chamadas a

estas regras de negócio e apresentação do resultado (este resultado pode vir em

diversos formatos: Sim/Não, temp-table de erros etc).

Características

Regras de Negócio

Page 10: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características
Page 11: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

9

CAPÍTULO 2

Concepção do DBO

Neste capítulo estão informações para que o analista possa projetar o DBO, a

fim de permitir que o desenvolvedor possa construir um DBO de forma mais

segura, integra, rápida e eficiente.

O analista deve definir a estrutura de DBOs do sistema. Para tanto, ele pode

seguir a seguinte linha:

1 Como regra inicial podemos ter 1 (um) DBO por tabela de banco de

dados, são os DBOs de entidade;

1.1 Para tabelas que contém muitos campos (ex.: item, emitente, etc.) pode-se

definir mais de um DBO. Por exemplo: teríamos para a tabela Item vários

DBOs de acordo com o grupo de informações organizadas, DBO Item

Básico, DBO Item-Estoque, DBO Item-Compras, etc. Neste caso, a

criação do registro deve ser feita somente no DBO Básico. Os outros

apenas atualizam as informações pertencentes à área.

2 Para processos também podem ser definidos DBOs. Por exemplo:

processo de fechamento contábil, atualização de movimento, etc..

Podemos dizer que cada API é um DBO. Nestes casos, escolhe-se a tabela

mais importante do DBO para nomeá-lo.

O nome do DBO deve ser: BOxxxxx.p

onde:

xxxxx = DumpName da Tabela

Descrição

Definição

Nomenclatura

Page 12: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

10

Quando for necessário criar um novo DBO, deve ser usado o DumpName da

tabela principal para qual está sendo criada esta BO + uma letra (A, B, C, D...).

O DBO deve sempre estar relacionado à tabela principal da mesma.

Exemplo: boad001a.p, boad001b.p ...

Além do DBO, deve se criar um include com o mesmo nome do programa e

terminação “.i”. Este include contém a definição da temp-table de

comunicação dos programas que vão utilizar o DBO.

Exemplo: boad001.i, boad002.i ...

O nome do DBO e o nome dos diretórios devem estar em letra minúscula.

Nos casos onde já existe o BO 1.1 para determinada tabela, e alguns módulos

desejarem utilizá-lo como DBO 2.0 e a equipe responsável pela conversão da

BO 1.1 para DBO 2.0 não tiver disponibilidade para conversão da mesma,

pode-se criar a DBO 2.0, utilizando a nomenclatura BOXX999O.P, onde:

XX999 = dump-name da tabela;

O = letra que indicará que essa DBO é uma DBO que contém a

funcionalidade desejada.

A construção do DBO 2.00 por outra equipe deve ser comunicada à equipe

responsável pela sua manutenção, e ter a aprovação desta, a qual deverá incluir

um comentário no BO 1.1 indicando a existência de uma versão 2.00. O DBO

2.00 deverá ser extremamente simples e ter apenas (por enquanto) métodos de

leitura de registros. É importante lembrar que a equipe responsável pela tabela

do DBO, deverá, no futuro, complementar a sua construção com as regras de

negócio e padrões de arquitetura.

Deve-se ter 1 (um) diretório de DBOs por aplicativo.

Exemplo: ADBO INBO UNBO DIBO

Para o desenvolvimento de DBOs deve ser utilizado a partir do Progress

versão 8.2. Só não é aconselhado a utilização de características disponíveis

somente para a versão 9.0, já que os DBOs podem ser utilizados em versões

diferentes de Progress.

Convivendo com BO 1.1 x DBO 2.0

Estrutura de Diretórios

Versão do Progress para o DBO

Page 13: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 2 Concepção do DBO 11

DBO de Entidade

Estes são os DBOs mais comuns e que normalmente estão relacionados a uma

determinada tabela do banco de dados.

São chamados de entidades os objetos do mundo real como Clientes,

Fornecedores, Títulos a Pagar etc. Uma entidade na maioria das vezes é

representada por uma tabela no banco de dados, quando este está totalmente

normalizado.

Quando uma entidade possui no banco de dados mais de uma tabela, é porque

o modelo lógico (entidade) é diferente do modelo físico (tabela). Isto ocorre

geralmente para ganhar performance no acesso ao banco de dados.

Nota: Uma tabela deve ser mantida por um único DBO.

O DBO normalmente se relaciona a uma única tabela e, portanto, esta é uma

etapa bastante simples. Quanto houver mais de uma tabela, devem ser todas

relacionadas, e descritos os campos que as relacionam.

O DBO comunica-se com os seus clients recebendo e enviando um conjunto

de campos (atualmente através de uma temp-table). Nesta etapa devem ser

definidos os campos que fazem parte do registro. Normalmente os campos são

os mesmos da tabela (LIKE tabela). Eventualmente alguns campos poderão ser

campos calculados que não estão presentes na tabela do banco de dados. Estes

devem então ser relacionados juntamente com a sua fórmula de cálculo.

Exemplo: Valor Total do Item do Pedido Valor Unitário * Quantidade.

Definir as validações para os campos definidos na etapa anterior. Estas

validações podem ser:

Valores permitidos para o campo;

Obrigatoriedade dos campos serem diferentes de branco ou zero;

Existir registro com a chave informada (chave estrangeira);

Impedir a alteração de um determinado campo;

Outros.

Entidade

Definindo a(s) tabela(s)

Definindo os campos do registro

Definindo as validações

Page 14: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

12

Definir quais os processos e atualizações devem ser executados quando um

registro é criado, alterado ou eliminado. A integridade pode ser para:

Atualizar campos calculados da tabela (ex. valor total);

Eliminar tabelas filhas;

Outros.

O DBO fornece ao client, quando solicitado, um registro com os valores

iniciais definidos na tabela. Algumas vezes para determinar o valor inicial de

um campo é necessário realizar um calculo devendo isto ser especificado.

Estes cálculos são necessários, por exemplo, quando o valor inicial é:

Determinado por um valor de outra tabela. Exemplo: Alíquota de imposto

inicial de um item é a alíquota da família do item;

Determinado a partir de um cálculo envolvendo várias tabelas.

O DBO é a forma do client ter acesso aos dados que estão na base de dados.

Por este motivo o DBO deverá determinar quais registros poderão ser

acessados pelo client (segurança) e fornecer meios de acesso que tenham boa

performance.

As constraints são restrições de acesso aos registros e podemos classificá-las

em 4 tipos principais:

Security (Segurança)

Dependendo de quem é o usuário que está logado no sistema, ele poderá ter

acesso a apenas alguns registros da tabela. Ex: Um representante de vendas só

poderá ver os pedidos dele.

Deve ser indicado como será determinada a faixa de registros com base no

usuário. Essa determinação poderá ser direta, comparando o código do usuário

logado a um campo do registro, ou indireta através de uma tabela auxiliar que

determine para cada usuário a faixa de registro que ele tem acesso.

Exemplos:

Direta: Pedido.Representante = <usuário_logado>

Indireta: Titulo.Empresa = <usuário_logado> em Empresa_Usuario

Definindo a integridade

Valores iniciais calculados

Constraints (Restrições)

Page 15: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 2 Concepção do DBO 13

Importante: A constraint de segurança deve ser utilizada em todas as queries.

Range (Faixa)

Permite que o usuário selecione valor inicial e final para um determinado

campo reduzindo com isso os registros em que será possível navegar. Essa

constraint é normalmente utilizada por programas de Zoom, e os campos são

os mesmos das classificações do DBO.

Um bom método para determinar as constraints de range é criar uma para cada

classificação (by) que o DBO terá.

Parent or Foreing Key (Pai ou chave estrangeira)

O DBO poderá ter relacionamento com outros DBOs sendo este filho ou a

tabela chave estrangeira daquele. Este tipo de constraint é usado para que

sejam selecionados apenas os registros correspondentes ao DBO pai. Elas

poderão ser constraints de range com valor inicial e final, ou de igualdade

utilizando apenas o código da chave do pai. A escolha entre range e igualdade

deve ser feita no momento da implementação considerando que:

Como range pode já ter sido definida como uma de range em função da

classificação, reduzindo assim o número de métodos de constraint;

Como igualdade pode-se conseguir uma melhor performance pela melhor

utilização dos índices.

Miscelaneous (Diversos)

Podemos ter outros tipos de constraints que permitem reduzir o número de

registros selecionados no banco e, portanto, melhorar a performance tanto na

comunicação "DBO DB" como "Client DBO". Esse tipo de

constraints são normalmente as que permitem realizar filtros nos registros, ou

seja, selecionar registros através de campos lógicos ou indicadores que estão

na tabela. São utilizados também em programas de Zoom e escolhidos pela

seleção de toggle-boxes ( [x] ).

Uma técnica para tornar estas constraints mais flexíveis é fazer um método,

que recebe um valor lógico, para cada toggle, ou seja, para cada valor possível

do campo indicador ou lógico.

Page 16: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

14

Os registros poderão ser retornados pelo DBO em várias ordenações

diferentes, e são estas ordenações e seus respectivos campos que devem ser

determinados nesta etapa. Devem ser determinadas também quais as

constraints que se aplicam a cada ordenação, pois podemos ter várias

constraints para o DBO, porém cada order poderá utilizar apenas algumas.

Cada ordenação definida terá pelo menos uma query correspondente no DBO,

podendo ter mais de uma para que se obtenha melhor performance de acordo

com os valores determinados para as constraints da query.

Para estas definições, devemos levar em conta as seguintes considerações:

Order: Haverá sempre uma classificação pela chave única e uma pela

chave primária, quando estes não são o mesmo. As outras classificações

devem fazer sentido em um programa de Zoom (por nome, por descrição,

por <tabela_pai>) e preferencialmente possuir índice com estes campos;

Constraints da Order: Para cada order deve ser aplicada a constraint que

tem os mesmos campos da order. Normalmente deverão ser aplicadas

também as constraints de Parent, cuidando para não prejudicar a

performance pelo mal uso dos índices da tabela. As demais constraints

deverão ser incluídas apenas se não prejudicarem o uso do índice, sendo

que as de filtro costumam ser resolvidas no próprio DBO (client) e não no

BD (server).

Queries: Para cada order haverá uma query, porém o uso de várias

constraints em uma única query pode comprometer a eficácia do índice.

Neste caso pode-se, na implementação do método OpenQuery, ter de fato

várias queries e através do teste dos valores de constraint abrir aquela que

melhor utiliza o índice. Na definição do DBO é importante indicar se o

programador deverá considerar ou não a necessidade de implementar

várias queries.

Métodos de negócio são aqueles que realizam uma ação específica para aquela

entidade, ou DBO, e geralmente são cálculos ou validações específicas como,

por exemplo, a análise de crédito do cliente. O nome de um método de negócio

deve ser em português e seguir a estrutura Verbo + Substantivo (ex:

VerificaCredito).

Estes métodos devem preferencialmente trabalhar apenas com um único

registro do DBO, ou seja, com o registro que foi posicionado com os

constraints e a query, pois desta forma será respeitada a segurança imposta

pela constraint de segurança.

Orders (Classificações)

Definindo métodos de negócio

Page 17: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 2 Concepção do DBO 15

No caso do método trabalhar com vários registros, inclusive recebendo-os via

parâmetro, deve-se utilizar a constraint de segurança no próprio método.

Assim como os métodos padrão, os métodos de negócio só podem ser

executados se o usuário tiver permissão para executar o tipo de função que ele

realiza. As funções padrão são: Navigation, Create, Update e Delete, sendo

que é extremamente aconselhável que uma das 3 últimas seja utilizada pelo

método de negócio, de acordo com o que o método realiza. É possível também

definir uma nova função de segurança para o método, no entanto isso deve ser

feito apenas em último caso, pois aumenta a complexidade de administração

da segurança do sistema.

Portanto, para cada método de negócio deve ser definido o seu nome, os seus

parâmetros, a lógica que ele deve executar e a função de segurança que ele

deve obedecer.

Neste exemplo com uma tabela de pedidos de venda (ORDER) é possível

verificar cada uma das etapas de definição do DBO. Para tornar este exemplo

claro e prático, além das definições é apresentado também o código

correspondente a elas.

INFORMAÇÕES PRELIMINARES

Tabela.: ORDER

Campo Tipo Observação

Order-Num Integer Chave única

Cust-Num Integer Chave estrangeira da

tabela Customer

Sales-Rep Character Nome do Representante

Status Integer Situação. Admite os

seguintes valores:

1 = Open

2 = Calculated

3 = Delivered

ENTIDADE

ORDER

Exemplo de DBO de entidade

Page 18: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

16

A entidade é a própria tabela.

TABELA

ORDER

CAMPOS

LIKE ORDER

STATUS-DESC Baseado no valor de Status: 1 = Open; 2 = Calculated;

3 = Delivered.

Todos os campos da tabela mais o campo status-desc que é calculado.

VALIDAÇÕES

Campo Validação

Order-Num Maior que zero; Não pode ser

alterado.

Cust-Num Deve existir na tabela ou DBO de

Customer

Sales-Rep

Status Apenas valores de 1 a 3.

INTEGRIDADE

Sales-Rep é sempre o usuário logado.

Nota: Está sendo assumido, para tornar mais simples o exemplo, que o usuário

logado é sempre um representante (Sales-Rep).

VALORES INICIAIS

Campo Calculo do valor inicial

Page 19: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 2 Concepção do DBO 17

Cust-Num Buscar o cliente principal do

representante na tabela Sales-Rep.

CONSTRAINTS

Tipo Campos Implementação

Security Sales-Rep =

usuário logado

/* Main Block */

{svc/autentic/autentic.i

&vUserName=cSalesRep)

Range Order-Num

Cust-Num

SetConstraintOrder (INPUT

iOrderNumStart, INPUT iOrderNumFinish)

SetConstraintCustomer (INPUT

iCustNumStart, INPUT iCustNumFinish)

Parent /

Foreing Key

Cust-Num SetConstraintCustomer (INPUT

iCustNumStart, INPUT iCustNumFinish)

Miscelaneous Status SetConstraintStatusOpen (INPUT

lStatusOpen) /* YES / NO */

SetConstraintStatusCalculated (INPUT

lStatusCalculated) /* YES / NO */

SetConstraintStatusDelivered (INPUT

lStatusDelivered) /* YES / NO */

Obs.: É utilizado um método para cada

situação para que seja possível ter

várias combinações.

ORDERS

Order Campos Constraints

Implementação (Query)

ByOrder Order-num Sales-Rep (Security)

Order-num (Range)

Cust-num (Parent)

Status (Miscelaneous)

Page 20: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

18

OpenQuerybyOrder:

OPEN QUERY qr{&TableName}

FOR EACH Order NO-LOCK

WHERE Order.Sales-Rep = cSales-Rep

AND Order.Order-Num >= iOrderStart

AND Order.Order-Num <= iOrderFinish

AND Order.Cust-Num >= iCustNumStart

AND Order.Cust-Num <= iCustNumFinish

AND ( lStatusOpen AND Order.Status = 1

OR lStatusCalculated AND Order.Status = 2

OR lStatusDelivered AND Order.Status = 3)

BY Order.Order-Num.

ByCustomer Cust-num Sales-Rep (Security)

Cust-num (Range)

Status (Miscelaneous)

OpenQuerybyCustomer:

OPEN QUERY qr{&TableName}

FOR EACH Order NO-LOCK

WHERE Order.Sales-Rep = cSales-Rep

AND Order.Cust-Num >= iCustNumStart

AND Order.Cust-Num <= iCustNumFinish

AND ( lStatusOpen AND Order.Status = 1

OR lStatusCalculated AND Order.Status = 2

OR lStatusDelivered AND Order.Status = 3)

BY Order.Cust-Num.

ByStatus Status Sales-Rep (Security)

Status (Miscelaneous)

OpenQuerybyStatus:

OPEN QUERY qr{&TableName}

FOR EACH Order NO-LOCK

WHERE Order.Sales-Rep = cSales-Rep

AND ( lStatusOpen AND Order.Status = 1

OR lStatusCalculated AND Order.Status = 2

OR lStatusDelivered AND Order.Status = 3)

BY Order.Status.

Nota: A constraint de security é obrigatória em todas as queries.

MÉTODOS DE NEGÓCIO

Método Parâmetros

Função Segurança

Lógica

Page 21: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 2 Concepção do DBO 19

CalculateOrder Nenhum

Update

Verificar se o pedido tem Status = 1 (Open)

Calcular o valor total do pedido somando o valor total de cada item

Somar o valor do pedido ao valor total de pedidos do representante em

SalesRep

Alterar o Status para 2 (Calculated)

DBOs X APIs

Tecnicamente, o DBO é um programa Progress que é executado de forma

persistente e que tem métodos que são executados. A API é um programa

Progress que é executado diretamente, recebendo e devolvendo parâmetros, e

que executa uma função específica.

Os DBOs devem utilizar as APIs que já existem atualmente no produto.

Programas de

InterfaceDBO API

Observe neste diagrama que as APIs podem ser acessadas pelos DBOs.

Qual a função do DBO e da API

No DBO temos os métodos de navegação e também os métodos com regras de

negócio. Se houver alguma API, o DBO deve reutilizá-la, conforme diagrama

acima. Neste caso, a lógica de negócio deve estar na API. Isto evita a

duplicação de código.

O DBO tem por função ser a nossa interface com outros produtos. É a nossa

camada de negócio.

Page 22: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

20

Como ficam as APIs existentes atualmente

Devem ser aproveitadas pelos DBOs que estão sendo construídos. Ou seja,

devem ser chamadas pelos DBOs. Se houver algum outro programa que use a

API, ela deve ser mantida.

Quando criar API ou DBO

Se for um novo desenvolvimento (módulo ou funcionalidade) devem ser

construídos somente DBOs. Nos módulos já existentes devem ser escritos

DBOs que utilizem as APIs já existentes, ou seja, o DBO vai ter os métodos

básicos mais métodos que façam a chamada à API.

Normalmente, as APIs são programas mais complexos que tem um

processamento mais longo e que, talvez, possam até ser executados em outro

equipamento via RPC ou RPW.

Outro critério, a ser levado em consideração, é não deixar o código do DBO (e

consequentemente o .r) muito grande.

Page 23: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 3 Como construir o DBO 21

CAPÍTULO 3

Como construir o DBO

Neste capítulo estão informações para que o desenvolvedor possa construir um

DBO de forma que possa ser reutilizado. Por exemplo: quais os métodos

obrigatórios, qual a assinatura dos métodos e várias outras situações que

devem ser observadas no desenvolvimento do DBO.

Acesso a Banco de Dados

Os acessos a base de dados pelo DBO, devem estar relacionados à tabela

principal do DBO. Por exemplo: para buscar algum valor da tabela conta

contábil, deve usar o DBO específico da mesma e não replicar este acesso em

DBOs de outras tabelas.

Pode-se acessar outras tabelas dentro do DBO desde que estejam no mesmo

aplicativo. Esta é a única exceção. Do contrário o DBO somente acessa sua

tabela principal.

Arquitetura do DBO

Um DBO é constituído das seguintes seções:

Definições

No início do DBO defini-se:

&DBOName Nome do DBO

&DBOVersion Versão do DBO

&DBOCustomFunctions Nome das funções customizadas

Descrição

Page 24: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

22

&TableName Nome da tabela principal do programa

&TableLabel Desc./Label da tabela principal do programa

&QueryName Nome da query principal do programa

Objetos de trabalho

Temp-table RowObject: Esta é uma Temp-table de comunicação. Cada DBO

deve definir uma temp-table para troca de dados com os programas que o estão

utilizando. Normalmente, esta temp-table é definida como a tabela principal do

DBO (LIKE <TableName>).

Temp-table RowErrors: Esta é a temp-table padrão de erros do DBO. Quando

for necessário retornar algum erro, deve-se usar esta temp-table que pode

conter um ou mais erros.

Esta temp-table é definida automaticamente para o DBO. E possui a definição

a seguir:

Campo Tipo Descrição

ErrorSequence Integer Indica a seqüência do erro ErrorNumber Integer Contém o número do erro ErrorDescription Character Contém a descrição do erro ErrorParameters Character Contém os parâmetros do erro ErrorType Character Indica o tipo do erro ErrorHelp Character Contém o help do erro ErrorSubType Character Indica o sub-tipo do erro

Métodos Básicos

Procedures internas padrão do DBO que contém o comportamento básico

esperado de um DBO.

Métodos de Negócio

Os métodos de negócio são definidos pelo analista, para atendimento de

funções específicas relacionadas ao objeto que está se trabalhando.

No DBO os métodos de negócio são procedures internas criadas pelo

desenvolvedor. As regras para criação destes métodos estão descritas a seguir:

Este método deve agir preferencialmente sobre o registro corrente e não

num conjunto de registros. Assim, o programa chamador tem mais

flexibilidade em controlar a operação. Por exemplo: um DBO da tabela

item pode ter um cálculo. Esta lógica estaria num método que atuaria

Page 25: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 3 Como construir o DBO 23

somente no registro corrente. Para processar novo item deve-se posicionar

no próximo (getNext);

Este método deve ser uma procedure interna e deve ter um comentário em

seguida, explicando o que faz o método. Esta descrição deve ser mais que

uma característica técnica, ou seja, deve ajudar ao programador identificar

o que faz o método;

O nome do método deve ter como base: verbo + substantivo(s) + sujeito.

A primeira palavra deve estar em minúsculo e as outras devem ter a

primeira letra em maiúsculo (mesmo padrão adotado na linguagem java).

Além disso, o nome deve estar na língua portuguesa. Desta forma, deve

ficar mais bem documentado do que se trata o método;

Exemplo: calculaMedia, insereOrder, salvaCustomer, etc.

O método deve retornar valores em parâmetros ou temp-tables de saída

(output param). Deve ser utilizado ‘return-value’ para indica se o método

foi processado com sucesso (OK/NOK). Quando ocorrem erros, estes

devem ser inclusos na temp-table RowErrors, se necessário.

Override de Métodos

Em muitos casos faz-se necessário a customização de métodos básicos, tais

como: createRecord, deleteRecord, updateRecord etc, a fim de facilitar este

tipo de customização foi desenvolvida a técnica de Override de Métodos.

Esta técnica executa dois outros métodos definidos pelo desenvolvedor a partir

dos métodos básicos (a seguir está listada uma tabela com os métodos básicos

que possuem override).

A tabela a seguir indica quais os métodos básicos que possuem override e

quais os parâmetros a serem definidos:

Método Parâmetro(s)

getFirst não há

getLast não há

getNext não há

getPrev não há

repositionRecord INPUT pRowid AS ROWID

createRecord* não há

Page 26: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

24

Método Parâmetro(s)

deleteRecord* não há

updateRecord* não há

getRecord não há

setRecord não há

newRecord não há

copyBuffer2TT* não há

copyTT2Buffer não há

getRowid INPUT-OUTPUT pRowid AS ROWID

getBatchRawRecords** não há

getBatchRawRecordsPrev** não há

getBatchRecords** não há

getBatchRecordsPrev** não há

*Nestes métodos, caso o retorno da procedure customizada seja "NOK" a

transação pode ser desfeita.

**Nestes métodos os pontos de override compreendem apenas a transferência

de cada registro individualmente para a temp-table auxiliar.

Além disso a procedure de override definida pelo desenvolvedor deve seguir a

regra abaixo de nomenclatura:

<before/after><nome-do-método-básico>

Exemplo: Para customizar o método createRecord, deve-se definir as

procedures a seguir conforme a necessidade.

PROCEDURE beforecreateRecord :

/*--------------------------------------------------------------

Purpose: Override do método createRecord (before)

Parameters:

Notes:

--------------------------------------------------------------*/

RETURN "OK":U.

END PROCEDURE.

PROCEDURE aftercreateRecord :

/*--------------------------------------------------------------

Purpose: Override do método createRecord (after)

Parameters:

Notes:

Page 27: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 3 Como construir o DBO 25

--------------------------------------------------------------*/

RETURN "OK":U.

END PROCEDURE.

Neste exemplo, a primeira procedure (beforecreateRecord) é executada antes

do código principal do método createRecord, e a segunda procedure

(aftercreateRecord) é executada após o código principal do método

createRecord.

Além disso, nestes procedures deve-se utilizar o comando RETURN "OK":U

para indicar que o método principal não deve ser cancelado, e o comando

RETURN "NOK":U para indicar que o método principal deve ser cancelado.

Construção do DBO

Para o desenvolvimento do DBO deve ser utilizado o UIB (AppBuilder,

quando utilizado versão 9) do Progress.

Para criação de um DBO o desenvolvedor deve seguir os seguintes passos

(estaremos construindo como exemplo um DBO de manutenção na tabela

Customer da base de dados Sports do Progress):

Criar programa e include de DBO a partir do template

O template do programa é o DBO Program, o template do include é o DBO

Temp-Table. Opta-se por estes templates ao criar-se um novo objeto no UIB

(AppBuilder, quando utilizado versão 9).

Observação: O identificador :T no inícios de alguns comentários, é usado para

a tradução dos fontes dos templates para outros idiomas. Este identificador não

afeta em nada a funcionalidade do programa.

Acertar os preprocessadores padrão

DBO Program:

DBOName: Este preprocessador recebe o nome do programa DBO;

DBOVersion: Este preprocessador recebe a versão do programa DBO;

DBOCustomFunctions: Este preprocessador recebe o nome das funções

customizadas (definidas pelo desenvolvedor), separadas por " , " (vírgula).

Este preprocessador é utilizado nos includes padrão do DBO;

Page 28: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

26

TableName: Este preprocessador recebe a tabela principal do programa.

Este preprocessador é utilizado nos includes padrão do DBO;

TableLabel: Este preprocessador recebe a descrição (label) da tabela

principal do programa. Este preprocessador é utilizado nos includes padrão

do DBO;

QueryName: Este preprocessador recebe o nome da query principal do

programa. Este preprocessador é utilizado nos includes padrão do DBO.

Exemplo: Temos no início do programa o código a seguir.

/* ********************** Definitions *********************** */

/*--- Diretrizes de definição ---*/

&GLOBAL-DEFINE DBOName boxx9999

&GLOBAL-DEFINE DBOVersion 1.00.00.000

&GLOBAL-DEFINE DBOCustomFunctions

&GLOBAL-DEFINE TableName Customer

&GLOBAL-DEFINE TableLabel Customer

&GLOBAL-DEFINE QueryName qr{&TableName}

Nota: Caso seja definido que na utilização do DBO será permitido criar

registros fora da query aberta, deve ser incluído o preprocessador

NewRecordOffQuery. Lembrando que com a inclusão deste preprocessador

não será apresentado erro de reposicionamento de registros na query.

&GLOBAL-DEFINE NewRecordOffQuery YES

Definição da temp-table de comunicação

Colocar o nome correto do include com a temp-table de comunicação do

programa. Este include deve estar no mesmo diretório do DBO e recebe como

parâmetro o nome da temp-table de comunicação, como padrão RowObject.

Só é alterada a terminação (de “.p” para “.i”).

Exemplo: A chamada ao include de definição da temp-table RowObject.

/*--- Include com definição da temp-table RowObject ---*/

{xxbo/boxx999x.i RowObject}

Page 29: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 3 Como construir o DBO 27

Definição da Query

A definição da query padrão está no include method/dboqry.i. Porém, havendo

a necessidade de customizar a definição da query, deve-se retirar a chamada ao

include e definir manualmente a query (lembrando de utilizar o preprocessor

{&QueryName} para defini-la).

Exemplo: A chamada ao include de definição da query {&QueryName}.

/*--- Include com definição da query para tabela {&TableName} ---*/

/*--- Em caso de necessidade de alteração da definição da query,

pode ser retirada a chamada ao include a seguir e em seu lugar

deve ser feita a definição manual da query ---*/

{method/dboqry.i}

Neste caso, a definição da query não foi customizada. Porém, a seguir está um

exemplo no qual a definição da query foi alterada:

Exemplo: Customização da definição da query {&QueryName}.

/*--- Include com definição da query para tabela {&TableName} ---*/

/*--- Em caso de necessidade de alteração da definição da query,

pode ser retirada a chamada ao include a seguir e em seu lugar

deve ser feita a definição manual da query ---*/

DEFINE QUERY {&QueryName}

FOR Customer FIELDS (Cust-Num Name) SCROLLING.

Mesmo quando a definição da query for alterada, deve-se sempre utilizar uma

única tabela e, também, utilizar a opção SCROLLING.

Observação: Para os casos onde é utilizado banco de dados Oracle deve-se

verificar o capítulo de Técnicas / Melhorar Performance em Bancos Oracle.

Definição das Aberturas de Query e setConstraint

Pode haver uma relação entre setConstraint<Description> e

openQuery<Description>, pois quem vai usar o DBO pode chamar openQuery

após setConstraint. Assim, podemos ter setConstraint e openQuery isolados

para navegações e seleções específicas.

Vale salientar que para realizar a abertura da query deve ser utilizado o método

openQueryStatic, passando como parâmetro a descrição da query a ser aberta.

A seguir são descritas as situações previstas:

Para a navegação padrão de uma tabela (sem constraints e sem outras

classificações):

Exemplo:

Page 30: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

28

PROCEDURE setConstraintMain:

RETURN "OK":U.

END PROCEDURE.

PROCEDURE openQueryMain:

OPEN QUERY {&QueryName} FOR EACH {&TableName} NO-LOCK.

RETURN "OK":U.

END PROCEDURE.

Quem usar esta versão do DBO vai chamar openQueryStatic(INPUT

"Main":U).

Para criar uma nova classificação para query, exemplo: por nome:

Exemplo:

PROCEDURE setContraintMain:

RETURN "OK":U.

END PROCEDURE.

PROCEDURE setConstraintByName:

RETURN "OK":U.

END PROCEDURE.

PROCEDURE openQueryMain:

OPEN QUERY {&QueryName} FOR EACH {&TableName} NO-LOCK.

RETURN "OK":U.

END PROCEDURE.

PROCEDURE openQueryByName:

OPEN QUERY {&QueryName} FOR EACH {&TableName} NO-LOCK

BY Customer.Name.

RETURN "OK":U.

END PROCEDURE.

Neste caso, o desenvolvedor vai ter opção de executar

openQueryStatic(INPUT "Main":U) ou openQueryStatic("ByName":U) e

então, navegar por código (índice primário) ou por nome (By customer.name).

Constraints para toda tabela.

Exemplo:

DEFINE VARIABLE cSalesRep LIKE Customer.Sales-Rep NO-UNDO.

PROCEDURE setConstraintMain:

DEFINE INPUT PARAMETER pSalesRep LIKE Customer.Sales-Rep NO-UNDO.

ASSIGN cSalesRep = pSalesRep.

RETURN "OK":U.

END PROCEDURE.

PROCEDURE setConstraintByName:

DEFINE INPUT PARAMETER pSalesRep LIKE Customer.Sales-Rep NO-UNDO.

Page 31: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 3 Como construir o DBO 29

ASSIGN cSalesRep = pSalesRep.

RETURN "OK":U.

END PROCEDURE.

PROCEDURE openQueryMain:

OPEN QUERY {&QueryName} FOR EACH {&TableName} NO-LOCK

WHERE Customer.Sales-Rep = cSalesRep.

RETURN "OK":U.

END PROCEDURE.

PROCEDURE openQueryByName:

OPEN QUERY {&QueryName FOR EACH {&TableName} NO-LOCK

WHERE Customer.Sales-Rep = cSalesRep

BY {&TableName}.Name.

RETURN "OK":U.

END PROCEDURE.

Neste caso, está sendo feita uma seleção por representante (sales-rep). Este

DBO deve estar preparado para navegar somente nos registros de Customer de

um determinado sales-rep que foi informado ao chamar as procedures

setConstraintMain e setConstraintByName. Elas apenas armazenam o

parâmetro recebido na variável que vai ser usada pela openQueryStatic.

Constraints específicos para uma query

Exemplo:

DEFINE VARIABLE cSalesRep LIKE Customer.Sales-Rep NO-UNDO.

DEFINE VARIABLE deCreditLimit LIKE Customer.Credit-Limit NO-UNDO.

PROCEDURE setConstraintMain:

DEFINE INPUT PARAMETER pSalesRep LIKE Customer.Sales-Rep NO-UNDO.

ASSIGN cSalesRep = pSalesRep.

RETURN "OK":U.

END PROCEDURE.

PROCEDURE setConstraintByName:

DEFINE INPUT PARAMETER pSalesRep

LIKE Customer.Sales-Rep NO-UNDO.

DEFINE INPUT PARAMETER pCreditLimit

LIKE Customer.Credit-Limit NO-UNDO.

ASSIGN cSalesRep = pSalesRep

deCreditLimit = pCreditLimit.

RETURN "OK":U.

END PROCEDURE.

PROCEDURE openQueryMain:

OPEN QUERY {&QueryName} FOR EACH {&TableName} NO-LOCK

WHERE Customer.Sales-Rep = cSalesRep.

RETURN "OK":U.

END PROCEDURE.

Page 32: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

30

PROCEDURE openQueryByName:

OPEN QUERY {&QueryName FOR EACH {&TableName} NO-LOCK

WHERE Customer.Sales-Rep = cSalesRep AND

Customer.Credit-Limit >= deCreditLimit

BY {&TableName}.Name.

RETURN "OK":U.

END PROCEDURE.

Neste caso, a query ByName além da Constraint referente ao sales-rep temos a

restrição do credit-limit (só mostra os registros maiores que determinado

crédito). Neste caso, somente a query ByName é afetada

(openQueryStatic(INPUT "ByName":U)). Se for utilizada

openQueryStatic(INPUT "Main":U) não deve haver esta verificação do credit-

limit.

Observação:

Ao realizar a construção dos métodos de openQuery e setConstraint,

normalmente, é mantido um relacionamento 1 – 1. Então é aconselhado que ao

alterar-se uma ou mais restrições de um openQuery seja criado um novo

método de abertura.

Isto é devido ao fato de não impedir o correto funcionamento das interfaces

que fazem uso do antigo método de abertura. Além disso pode-se optar pela

criação de valores iniciais para as restrições para que as antigas interfaces

continuem a funcionar com as novas restrições do openQuery.

Criação do método goToKey

Para o índice único que melhor pode ser utilizado para localizar o registro

diretamente deve ser criado um método no DBO que receba os campos,

execute o find e posicione no registro, através do método repositionRecord. Se

não for encontrado insere uma mensagem de erro na temp-table RowErrors,

através da include method/svc/errors/inserr.i, e retorna um flag "NOK":U.

Exemplo:

PROCEDURE goToKey:

/*---------------------------------------------------------------

Purpose: Reposiciona registro através de índice único

Parameters:

Notes:

----------------------------------------------------------------*/

DEFINE INPUT PARAMETER pCustNum LIKE Customer.Cust-Num NO-UNDO.

FIND bfCustomer WHERE bfCustomer.Cust-Num = pCustNum

NO-LOCK NO-ERROR.

Page 33: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 3 Como construir o DBO 31

IF NOT AVAILABLE bfCustomer THEN DO:

{method/svc/errors/inserr.i

&ErrorNumber=""

&ErrorType=""

&ErrorSubType= "ERROR"

&ErrorParameters="''"}

RETURN "NOK":U.

END.

RUN repositionRecord IN THIS-PROCEDURE (INPUT ROWID(bfCustomer)).

IF RETURN-VALUE = "NOK":U THEN

RETURN "NOK":U.

RETURN "OK":U.

END PROCEDURE.

Criação do método linkTo<Description>

Quando existe a necessidade de comunicação entre DBOs, seja através do

client ou do próprio DBO, deve-se utilizar o método linkTo<Description>.

Este deve receber o handle do DBO Pai e executar o método getKey neste

DBO, a fim de receber os valores dos campos do índice único do DBO Pai.

Após receber o retorno destes campos, o DBO Filho então, pode executar um

método do tipo setConstraint para setar uma restrição de abertura para a query.

A nomenclatura deste método consiste em utilizar os termos linkTo +

<Descrição que identifique o DBO Pai>.

Exemplo:

Exemplo:

DEFINE VARIABLE iCustNum LIKE Customer.Cust-Num NO-UNDO.

PROCEDURE linkToItem:

/*---------------------------------------------------------------

Purpose: Recebe handle do DBO Item e execute método getKey

Parameters: recebe handle de um DBO

Notes:

----------------------------------------------------------------*/

DEFINE INPUT PARAMETER pHandle AS HANDLE NO-UNDO.

RUN getKey IN pHandle (OUTPUT iCustNum).

RUN setConstraintCustomer IN THIS-PROCEDURE (INPUT iCustNum).

RETURN "OK":U.

END PROCEDURE.

Obs: O uso do método getKey está descrito a seguir.

Page 34: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

32

Criação do método getKey

Deve ser utilizado em conjunto com o método linkTo<Description>.

Para o índice único deve ser criado um método no DBO que retorna os valores

dos campos do registro corrente.

Exemplo:

PROCEDURE getKey:

/*---------------------------------------------------------------

Purpose: Retorna valores dos campos do índice único

Parameters: retorna cust-num

Notes:

----------------------------------------------------------------*/

DEFINE OUTPUT PARAMETER pCustNum LIKE Customer.Cust-Num NO-UNDO.

IF AVAILABLE Customer THEN

ASSIGN pCustNum = Customer.Cust-Num.

ELSE

ASSIGN pCustNum = ?.

RETURN "OK":U.

END PROCEDURE.

Fazer validações comuns ao create e update do registro

No método validateRecord devem ser feitas todas as validações pertinentes ao

DBO. Mas para identificar qual o tipo de validação a ser executa deve-se

utilizar o parâmetro pType.

Caso exista algum erro deve-se criar uma mensagem de erro padrão na temp-

table RowErrors, através da include method/svc/errors/inserr.i.

As validações devem ser feitas preferencialmente sobre os campos da temp-

table RowObject.

Exemplo:

PROCEDURE validateRecord:

/*---------------------------------------------------------

Purpose: Valida temp-table RowObject

Parameters: recebe o tipo de validação

----------------------------------------------------------*/

DEFINE INPUT PARAMETER pType AS CHARACTER NO-UNDO.

IF pType = "Create":U OR pType = "Update":U THEN DO:

IF RowObject.Name = "":U THEN

{method/svc/errors/inserr.i

&ErrorNumber=""

&ErrorType=""

&ErrorSubType="ERROR"

&ErrorParameters="''"}

Page 35: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 3 Como construir o DBO 33

IF RowObject.Credit-Limit < 0 THEN

{method/svc/errors/inserr.i

&ErrorNumber=""

&ErrorType=""

&ErrorSubType="ERROR"

&ErrorParameters="''"}

END.

IF CAN-FIND(FIRST RowErrors

WHERE RowErrors.ErrorSubType = "ERROR":U) THEN

RETURN "NOK":U.

RETURN "OK":U.

END PROCEDURE.

Verificar ocorrência de chave duplicada ou outras validações referentes somente a criação de registros

Antes de proceder a criação do registro, deve-se verificar se existe chave

duplicada no método validateRecord. Em caso de chave duplicada ou outro

erro qualquer, deve-se inseri-lo na temp-table RowErrors e retornar "NOK":U.

Exemplo:

/*---------------------------------------------------------

Purpose: Valida temp-table RowObject

Parameters: recebe o tipo de validação

Notes:

----------------------------------------------------------*/

DEFINE INPUT PARAMETER pType AS CHARACTER NO-UNDO.

IF pType = "Create":U THEN DO:

IF CAN-FIND(Customer

WHERE Customer.Cust-Num = RowObject.Cust-Num) THEN

{method/svc/errors/inserr.i

&ErrorNumber=""

&ErrorType=""

&ErrorSubType="ERROR"

&ErrorParameters="''"}

END.

IF pType = "Create":U OR pType = "Update":U THEN DO:

IF RowObject.Cust-Num <= 0 THEN

{method/svc/errors/inserr.i

&ErrorNumber=""

&ErrorType=""

&ErrorSubType="ERROR"

&ErrorParameters="''"}

END.

IF CAN-FIND(FIRST RowErrors

WHERE RowErrors.ErrorSubType = "ERROR":U) THEN

Page 36: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

34

RETURN "NOK":U.

RETURN "OK":U.

END PROCEDURE.

Vale salientar, que existindo a necessidade de realizar validações específicas

para a alteração/eliminação de registros deve ser utilizado o método

validateRecord, porém deve-se verificar o valor do parâmetro pType a fim de

identificar qual o tipo de validação a ser executada.

Criação de erros

Quando o desenvolvedor possui a necessidade da inclusão de erros na temp-

table RowErrors, deve ser utilizado o include method/svc/errors/inserr.i.

O include method/svc/errors/inserr.i é utilizado para realizar a inclusão de

erros Progress ou erros de Produto, e ainda contempla a possibilidade de

inclusão de erros manuais. Para inclusão de Erros Progress e de Produto,

recebe os parâmetros a seguir:

ErrorNumber: número do erro, quando o erro for do tipo Outros;

ErrorType: tipo do erro, podendo ter o valor Progress, Outros, EMS

ou HR (qualquer valor pode ser utilizado nesta descrição);

ErroSubType: sub-tipo do erro, podendo ter o valor Error,

Information ou Warning; o registro incluso somente é considerado

um erro quando seu sub-tipo é Error, caso seja Information ou

Warning, o procedimento continuará;

ErrorParameters: parâmetros do erro, quando o erro for do tipo

Outros estes parâmetros irão ser utilizados na chamadas das

mensagens padrão do Produto.

Exemplo: Inclusão de erros do produto.

{method/svc/errors/inserr.i

&ErrorNumber="1"

&ErrorType="EMS"

&ErrorSubType="ERROR"

&ErrorParameters="'Customer'"}

Este exemplo traz um erro do produto EMS, e recebe parâmetros “Customer”,

sendo assim, na interface pode-se executar a mensagem padrão do produto

para o erro 1, e passar para a mensagem o parâmetro “Customer”, além disso o

sub-tipo do erro indica ERROR, então o procedimento será abortado.

Page 37: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 3 Como construir o DBO 35

{method/svc/errors/inserr.i

&ErrorNumber="32"

&ErrorType="HR"

&ErrorSubType="ERROR"

&ErrorParameters="'Order~~~~ ' + STRING(TODAY)"}

{method/svc/errors/inserr.i

&ErrorNumber="42"

&ErrorType="HR"

&ErrorSubType="WARNING"

&ErrorParameters="'Order~~~~Customer'"}

Nestes exemplos temos erros de produto, onde o segundo exemplo traz um

sub-tipo WARNING, sendo assim, a interface poderá tratar e mostrar a

mensagem de erro ao usuário, mas o procedimento não será abortado.

Exemplo: Inclusão de erros Progress.

CREATE Customer NO-ERROR.

IF ERROR-STATUS:ERROR THEN

{method/svc/errors/inserr.i

&ErrorType="PROGRESS"

&ErrorSubType="ERROR"}

DELETE Customer NO-ERROR.

IF ERROR-STATUS:ERROR THEN

{method/svc/errors/inserr.i

&ErrorType="PROGRESS"

&ErrorSubType="ERROR"}

O include pode ser utilizado para realizar a inclusão de erros manuais, ou seja

todos as informações referentes ao erro são informadas pelo desenvolvedor.

Desta forma o include recebe os parâmetros a seguir:

ErrorNumber: número do erro, quando o erro for do tipo Outros;

ErrorType: tipo do erro, podendo ter o valor Outros (qualquer valor

pode ser utilizado nesta descrição);

ErrorSubType: sub-tipo do erro, podendo ter o valor Error,

Information ou Warning; o registro incluso somente é considerado

um erro quando seu sub-tipo é Error, caso seja Information ou

Warning, o procedimento continuará;

ErrorDescription: descrição do erro, na descrição os parâmetros já

devem estar substituídos;

Page 38: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

36

ErrorHelp: help do erro, no help os parâmetros já devem estar

substituídos;

ErrorParameters: parâmetros do erro, quando o erro for do tipo

Outros.

Quando utilizar o parâmetro ErrorDescription, deve-se utilizar o

ErrorSubType.

Exemplo: Inclusão de erros do produto.

IF Customer.Cust-Num <= 0 THEN

{method/svc/errors/inserr.i

&ErrorNumber="112"

&ErrorType="EMS"

&ErrorSubType="ERROR"

&ErrorDescription="Valor inválido para o Cust-Num"

&ErrorHelp="Informe valor maior que 0 para o Cust-Num"}

DELETE Customer NO-ERROR.

IF ERROR-STATUS:ERROR THEN

{method/svc/errors/inserr.i

&ErrorNumber="12"

&ErrorType="EMS"

&ErrorSubType="ERROR"

&ErrorDescription="Erro ao eliminar registro"}

Note-se que a utilização do parâmetro ErroDescription deve ser feita quando o

erro a ser notificado não for um erro já cadastrado no Produto.

Definição das Aberturas de Query e setConstraint com Join entre Tabelas

Quando for necessário fazer uma query em um DBO e esta query possui como

restrição (constraint) um conjunto de registros de outra tabela, ou seja, é uma

construção EACH, EACH, deve ser criado um DBO exclusivo para cada

query. A nomenclatura padrão para estes DBOs é boxx999Qyy.p, onde xx999

é o dump-name da tabela filha e yy é um número de 01 à 99. As diferenças na

construção desta DBO em relação às DBOs normais são:

Definição da Query: deve ser definida manualmente, pois terá mais de

uma tabela;

Definição das Aberturas de Query e setConstraint: nos métodos

openQuery o comando OPEN QUERY utilizará mais de uma tabela no

FOR EACH pois a query foi definida com mais tabelas; as queries deverão

Page 39: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 3 Como construir o DBO 37

utilizar sempre o mesmo conjunto de tabelas e seguir a mesma seqüência;

se for necessário criar uma query com tabelas diferentes é necessário criar

um novo "DBO de Join" pois cada um suporta apenas uma única definição

de query que é onde se definem as tabelas e sua ordem de encadeamento;

pode haver um ou mais métodos setConstraint, dependendo do número de

campos utilizados nos WHERE do Open Query; a diferença neste caso é

que os campos do setConstraint são utilizados para restrições de várias

tabelas;

gotoKey e getKey: normal, lembrando apenas que se aplicam a tabela

filha;

linkTo<parent>: não construir;

Validações: não precisam ser construídas pois o DBO é apenas para

leitura.

Criação do método setSecurityConstraint

Este método é usado para definir a parte obrigatória da clausula WHERE que é

montada no uso de Query Dinâmica. É através da Security Constraint que se

controla a quais registros o cliente do DBO tem acesso, geralmente baseado no

usuário logado.

Este é um método opcional. Se não informado, o client do DBO poderá

navegar em todos os registros da tabela do DBO.

Para o índice único deve ser criado um método no DBO que retorna os valores

dos campos do registro corrente.

Exemplo:

PROCEDURE getSecurityConstraint:

/*---------------------------------------------------------------

Purpose: Retorna o conteúdo da SecurityConstraint para ser usado na

QueryDinamica

Parameters: pSecurityConstraint

Notes:

------------------------------------------------------------------*/

DEFINE OUTPUT PARAM pSecurityConstraint AS CHAR NO-UNDO.

ASSIGN pSecurityConstraint = "customer.cust-num >= 2":U.

RETURN "OK":U.

END PROCEDURE.

Page 40: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

38

XML no DBO

O DBO pode atuar como um produtor (Producer) de mensagens XML, bem

como um receptor (Receiver) delas.

O DBO vai produzir mensagens XML quando um registro for incluído,

alterado ou eliminado através de seus métodos padrão. A mensagem será

enviada ao serviço de Message Broker (ver adiante Serviço de Message

Broker)

O DBO vai receber mensagens através do método receiveMessage as quais

vão disparar ações de inclusão, alteração, eliminação e leitura da base de

dados. Neste caso o DBO não utiliza o serviço de Message Broker.

Os dois comportamentos podem ser ativados separadamente, apesar disso ser

raro. Para ativá-lo, deve-se informar um conjunto de pré-processadores

conforme visto a seguir.

Informar os pré-processadores para XML Producer

DBO Program:

XMLProducer: Informar apenas YES para ativar todo o código de envio

de mensagens nos métodos padrão. Obs: É necessário que o serviço de

Message Broker esteja configurado também;

XMLTopic: Tópico da Mensagem enviada ao Message Broker, geralmente

o nome da tabela;

XMLTableName: Nome da tabela que deve ser usado como TAG no

XML;

XMLTableNameMult: Nome da tabela no plural. Usado para agrupar

vários registros da tabela;

XMLPublicFields: Lista dos campos (c1,c2) que podem ser enviados via

XML. Geralmente ficam fora desta lista os campos de especialização da

tabela;

XMLKeyFields: Lista dos campos chave da tabela (c1,c2). Campos que

são enviados sempre;

XMLSender: Sigla do aplicativo ao qual pertence o DBO;

Page 41: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 3 Como construir o DBO 39

XMLExcludeFields: Lista de campos a serem excluídos do XML. Deve ser

informado apenas se XMLPublicFields = "".

Exemplo:

/* ********************** Definitions *********************** */

&GLOBAL-DEFINE XMLProducer YES

&GLOBAL-DEFINE XMLTopic CUSTOMER

&GLOBAL-DEFINE XMLTableName CUSTOMER

&GLOBAL-DEFINE XMLTableNameMult CUSTOMERS

&GLOBAL-DEFINE XMLPublicFields

&GLOBAL-DEFINE XMLKeyFields CUST-NUM

&GLOBAL-DEFINE XMLSender SPO

&GLOBAL-DEFINE XMLExcludeFields

Informar os pré-processadores para XML Receiver

DBO Program:

XMLReceiver: DBO atua como receiver de mensagens enviadas pelo

Message Broker (método receiveMessage);

KeyField1, KeyField2: Informar os campos da chave da tabela quando o

Progress não conseguir resolver find {&TableName} OF RowObject,

gerando o erro “** More than one index found for <table> OF <table> --

use WHERE, not OF. (446)”. Isso geralmente acontece em tabelas que não

tem índice único ou que tem mais de um índice único.

Exemplo:

/* ********************** Definitions *********************** */

&GLOBAL-DEFINE XMLReceiver YES

&GLOBAL-DEFINE KeyField1 CUST-NUM

Nota: Provisoriamente é necessário setar o pré-processador DYNAMIC-

QUERY-ENABLED para ativar os métodos de query dinâmica. Após o

período de beta-teste. Ele estará disponível a todos os DBOs.

Page 42: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

40

Utilizando Serviços no DBO

O que são serviços? Nada mais são do que programas/procedures internas que

podem estar disponíveis para o DBO conforme a configuração feita para o

Produto.

Os serviços padrão disponíveis ao DBO são:

Implementações conforme tipo de Banco de Dados;

Customização para Parceiros/Clientes;

Erros do Produto;

Tratamento de erros Progress;

Segurança para o programa DBO;

Segurança aos métodos do programa DBO.

Estes serviços são criados e manutenidos por uma equipe de administração do

produto.

A utilização de alguns destes serviços pode ser feita diretamente pelo

desenvolvedor.

Serviço de Banco

O serviço de Banco pode ser utilizado pelo desenvolvedor para realizar

implementações específicas para um banco de dados.

O uso deste é feito através do preprocessador DBType, que possui o tipo de

banco de dados utilizado pelo DBO.

Exemplo: Impedir que o comando GET LAST seja utilizado quando o banco

não for Progress.

PROCEDURE afterNewRecord:

&IF "{&DBType}":U = "PROGRESS":U &THEN

GET LAST {&QueryName} NO-LOCK.

&ENDIF

END PROCEDURE.

Nesse exemplo foi exposto uma maneira do desenvolvedor impedir que o

comando GET LAST seja utilizado quando o banco de dados não for Progress,

através do uso do preprocessador DBType.

Page 43: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 3 Como construir o DBO 41

Serviço de Autenticação

O serviço de Autenticação pode ser utilizado pelo desenvolvedor a fim de

obter o valor de algumas variáveis de contexto.

O uso deste é feito através do include method/svc/autentic/autentic.i que

recebe os parâmetros a seguir:

Parâmetro Tipo Descrição

vUserAccessType Integer Contém o tipo de acesso do usuário corrente vUserEnterprise Integer Contém o código da empresa do usuário

corrente vUserName Character Contém o código do usuário corrente vUserCountryTax Integer Contém o código do imposto do país do

usuário corrente vUserGroupSecurityList Character Contém a lista dos grupos de segurança do

usuário vHRProgramSecurity Handle Handle do programa de segurança do produto

HR

Exemplo: Setar automaticamente uma constraint com o valor do usuário

corrente e da empresa do usuário corrente.

/* Definitions --- */

DEFINE VARIABLE iUserEnterprise AS INTEGER NO-UNDO.

DEFINE VARIABLE cUserName AS CHARACTER NO-UNDO.

/* Main Block --- */

{method/svc/autentic/autentic.i

&vUserEnterprise="iUserEnterprise"

&vUserName="cUserName"}

RUN setConstraintSecurity IN THIS-PROCEDURE

(INPUT iUserEnterprise,

INPUT cUserName).

Nesse exemplo foi utilizado o serviço de autenticação para setar

automaticamente um constraint que indica o usuário corrente.

Serviço de Customização

O serviço de Customização pode ser utilizado pelo desenvolvedor para incluir

novos pontos para que Clientes/Parceiros possam customizar o processamento

do DBO.

Para os DBOs existem dois pontos pré-definidos nos métodos createRecord,

updateRecord e deleteRecord. Estes pontos são executados no início e no final

Page 44: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

42

do método e, ainda, estão dentro da transação do método, permitindo que a

customização possa cancelar a transação.

Quando o desenvolvedor analisar que um método específico deve possuir um

ponto para customização, deve utilizar o include method/svc/custom/custom.i.

Além disso, o desenvolvedor deve verificar se o método pode ser cancelado.

A utilização do include é simples, bastando o desenvolvedor informar o valor

do parâmetro &Event, que indica o nome do evento de customização.

Aconselha-se que a definição do include seja feita nos pontos inicial e final do

método que se deseja customizar. E a nomenclatura para o parâmetro Event

deve ser <before/after><nome-do-método>.

Exemplo: Inclusão de pontos de customização para o método calculateOrder.

PROCEDURE calculateOrder:

{method/svc/custom/custom.i &Event="beforeCalculateOrder"}

...

{method/svc/custom/custom.i &Event="afterCalculateOrder"}

END PROCEDURE.

Nesse exemplo foram inclusos dois pontos para customização. Estes pontos

não permitem que o customizador cancele o método.

Caso o desenvolvedor opte por definir os pontos de customização com opção

de cancelamento, deve ser tratado o RETURN-VALUE após a chamada ao

include e, ainda, a variável lCustomExecuted a fim de identificar se o

problema de customização foi executado.

Exemplo: Inclusão de pontos de customização para o método calculateOrder e

tratamento do retorno.

PROCEDURE calculateOrder:

DO TRANSACTION:

{method/svc/custom/custom.i &Event="beforeCalculateOrder"}

IF lCustomExecuted AND RETURN-VALUE = "NOK":U THEN

UNDO, RETURN "NOK":U.

...

{method/svc/custom/custom.i &Event="afterCalculateOrder"}

IF lCustomExecuted AND RETURN-VALUE = "NOK":U THEN

UNDO, RETURN "NOK":U.

END.

END PROCEDURE.

Page 45: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 3 Como construir o DBO 43

Serviço de Segurança

O serviço de Segurança divide-se em dois estilos: segurança para o DBO, feita

automaticamente, e segurança para método.

Somente a segurança de métodos pode ser utilizada pelo desenvolvedor. O uso

deste é feito através do include method/svc/security/permit.i que recebe o

parâmetro &Method, que contém o nome do método ou um nome que

identifique um grupo de métodos.

Os métodos de navegação (getFirst, getPrev, getNext, getLast e

repositionRecord) e de update (createRecord, deleteRecord e updateRecord) já

possuem segurança padrão definida com os nomes de Navigation, Create,

Delete e Update.

Exemplo: Implementação de segurança para o método calculateOrder.

/* Definitions --- */

&GLOBAL-DEFINE DBOCustomFunctions calculateOrder

PROCEDURE calculateOrder:

{method/svc/permit/permit.i &Method="calculateOrder"}

...

END PROCEDURE.

Quando é utilizado a segurança de métodos, deve-se preencher o

preprocessador DBOCustomFunctions com os valores passados para o

parâmetro &Method, separados por vírgula.

Além disso, a chamada ao include deve ser feita fora da transação do método,

pois o include somente faz o cancelamento do método, através do comando

RETURN "NOK":U.

E, ainda, pode-se utilizar os valores Navigation, Create, Delete ou Update para

a passagem de parâmetro.

Redução do Tamanho do DBO

Para evitar que o programa fonte do DBO fique muito grande e gere um

executável também grande. Deve-se procurar fazer algumas otimizações. Se

tivermos um executável muito grande poderemos perder performance ao

executar o programa (por causa do tempo de carga).

Page 46: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

44

Uso de sub-programas

O método do DBO pode estar codificado em sub-programas evitando um fonte

muito grande e reduzindo o executável. O analista deve levar em consideração

também a necessidade de utilização do método. Por exemplo: o método

createRecord deve ser bastante usado num programa de digitação. Ao

contrário de um método de cálculo que deve ser utilizado em funções

específicas.

Por exemplo: Um método de cálculo sem sub-programa:

PROCEDURE calculateAlgumaCoisa:

FOR EACH table:

ASSIGN ...

END.

END PROCEDURE.

Utilizando sub-programa para otimizar o DBO:

PROCEDURE calculateAlgumaCoisa:

RUN xxbo/boxx999x.p (<parameters>).

END PROCEDURE.

Assim, a lógica deste método deve estar neste sub-programa que somente

deve ser carregado para memória quando o método for chamado evitando

assim demora no tempo de carga do DBO;

O analista deve levar em consideração a passagem de parâmetros e que

este sub-programa tenha código considerável para ser um sub-programa

(como sugestão no mínimo 60 linhas);

Os sub-programas construídos devem seguir as regras existentes para

DBOs, ou seja, devem receber parâmetros via temp-table e realizar o

retorno de erros da mesma forma. Não podem usar variáveis globais e nem

fazer interação com a tela.

Considerações Gerais

Recomenda-se que o nível de transação (Progress) fique limitado ao método.

Cuidando-se para não transformar todo o DBO em uma única transação

(afetando assim o escopo e bloqueio de registro).

Por exemplo: os métodos createRecord, updateRecord e deleteRecord

constituem-se em 3 (três) transações separadas. E seus métodos override estão

neste mesma transação.

Controle de Transação

Page 47: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 3 Como construir o DBO 45

Alertamos para o fato de que as transações dos DBOs podem ser afetadas pelas

transações dos programas que utilizam os DBOs.

As regras de negócio devem estar em DBOs e APIs. Não se deve utilizar

Triggers para regras de negócio. Os Triggers podem vir a ser usados para

processos técnicos, mas isto é uma definição da equipe de apoio ao

desenvolvimento.

As regras de negócio existentes atualmente devem ser transferidos

gradualmente para DBOs e APIs.

Triggers

Page 48: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

46

CAPÍTULO 4

Convertendo BO 1.1 para DBO 2.0

Este capítulo é destinado ao desenvolvedor que utiliza DBO 1.1 e deseja

convertê-lo para DBO 2.0.

Para converter um DBO 1.1 devem ser seguidos os seguintes passos:

Criar um novo DBO 2.0;

Transferir lógicas dos métodos básicos do DBO 1.1 para o DBO 2.0;

Mas, antes de detalhar estes passos, é importante saber como fazer a relação

entre os métodos antigos e os novos métodos.

A seguir são detalhados os passos:

Relação entre métodos

A maior parte dos métodos básicos possuem métodos que são correspondentes

no novo DBO, sendo assim descreve-se a seguinte relação:

compareVersion -

Não há método correspondente no novo DBO;

endMethod e startMethod -

Estes métodos eram utilizados para execução de EPCs, porém a execução

de EPCs no novo DBO é feita de forma automática. Sendo assim, não há

método correspondente no novo DBO;

findRowidShow -

Deve-se executar primeiramente o método emptyRowObject e logo após o

método repositionRecord;

Page 49: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 4 Convertendo BO 1.1 para DBO 2.0 47

findRowid -

Deve-se executar o método repositionRecord;

getCurrent -

Deve-se executar o método getRecord;

findFirst -

Deve-se executar o método getFirst. O novo DBO somente trabalha com

query;

finLast -

Deve-se executar o método getLast. O novo DBO somente trabalha com

query;

findNext -

Deve-se executar o método getNext. O novo DBO somente trabalha com

query;

findPrev -

Deve-se executar o método getPrev. O novo DBO somente trabalha com

query;

getRowid -

Continua existindo no novo DBO;

setCurrent -

Deve-se executar o método _copyBuffer2TT. Porém, este método é

somente para uso interno dos includes padrão;

prevBrowseNavigation -

Não há método correspondente no novo DBO;

serverSendRows -

Deve-se executar o método getBatchRecords;

validateCreate -

Deve-se primeiramente executar o método createRecord e logo após o

getRowid;

validateDelete -

Page 50: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

48

Deve-se primeiramente executar o método repositionRecord, após o

deleteRecord e por último getRowid;

validateUpdate -

Deve-se primeiramente executar o método repositionRecord, após o

setRecord e por último updateRecord;

openQuery -

Deve-se executar o método openQueryStatic. Porém, o novo método

utiliza strings ao invés de números e desta forma deve-se controlar isto

através de um método proxy definido pelo desenvolvedor.

Criar o novo DBO

Este passo está detalhado no item 'Construindo o DBO'.

Transferir lógicas dos métodos básicos do DBO 1.1 para o DBO 2.0

No antigo DBO, grande parte dos métodos básicos eram codificados pelo

próprio desenvolvedor. Porém, no novo DBO grande parte dos métodos

básicos são definidos em includes padrão.

A seguir, está descrito como deve ser feita a transferência dos métodos:

openQuery

Este método deve ser subdividido em novos métodos, conforme exemplo a

seguir:

Método antigo:

PROCEDURE openQuery:

DEFINE INPUT PARAMETER i-abertura AS INTEGER NO-UNDO.

CASE i-abertura:

WHEN 1 THEN

OPEN QUERY {&Query-Name} FOR EACH Customer NO-LOCK.

WHEN 2 THEN

OPEN QUERY {&Query-Name} FOR EACH Customer NO-LOCK BY

Customer.Name.

END CASE.

Page 51: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 4 Convertendo BO 1.1 para DBO 2.0 49

ASSIGN l-query = true

i-bo-query = i-abertura.

END PROCEDURE.

Método novo:

PROCEDURE openQueryMain:

OPEN QUERY {&Query-Name} FOR EACH Customer NO-LOCK.

END PROCEDURE.

PROCEDURE openQueryByName:

OPEN QUERY {&Query-Name} FOR EACH Customer NO-LOCK BY

Customer.Name.

END PROCEDURE.

Nesta conversão, o método openQuery foi substituído por 2 (dois) outros

métodos. E ainda, para realizar a abertura da query deve-se utilizar o método

genérico openQueryStatic passando como parâmetro a descrição da query.

Conforme exemplo a seguir:

RUN openQueryStatic IN THIS-PROCEDURE (INPUT "Main":U).

ou

RUN openQueryStatic IN THIS-PROCEDURE (INPUT "ByName":U).

Vale salientar que os métodos setConstraint devem ter seus nomes alterados a

fim de possuírem nomenclatura semelhante aos métodos

openQuery<Description> associados. Conforme exemplo a seguir:

PROCEDURE openQueryByName:

...

END PROCEDURE.

PROCEDURE setConstraintByName:

...

END PROCEDURE.

validateCreate

Este método foi dividido em novos métodos, sendo 1 (um) deles definido

dentro do DBO e outro em include padrão.

Page 52: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

50

Neste método, a parte responsável pelas validações específicas à criação

devem ser transferidas para o método beforecreateRecord, as validações

análogas à criação e alteração devem ser transferidas para o método

validateRecord. E ainda, caso ocorra algum erro nas validações, ao final deve

ser retornado um flag "NOK" através do comando RETURN-VALUE.

Quanto aos erros ocorridos, estes devem ser cadastrados na temp-table

RowErrors através da include method/svc/errors/inserr.i.

Estes procedimentos são demonstrados através do exemplo a seguir:

Método antigo:

PROCEDURE validateCreate:

DEFINE INPUT PARAMETER TABLE FOR RowObject.

DEFINE OUTPUT PARAMETER TABLE FOR tt-bo-erro.

DEFINE OUTPUT PARAMETER r-chave AS ROWID NO-UNDO.

FOR EACH tt-bo-erro:

DELETE tt-bo-erro.

END.

IF CAN-FIND(FIRST Customer WHERE Customer.Cust-Num =

RowObject.Cust-Num)

THEN DO:

ASSIGN i-seq-erro = i-seq-erro + 1.

RUN utp/ut-msgs.p (INPUT "MSG":U, INPUT 9999, INPUT "":U).

CREATE tt-bo-erro.

ASSIGN tt-bo-erro.i-sequen = i-seq-erro

tt-bo-erro.cd-erro = 9999

tt-bo-erro.mensagem = RETURN-VALUE.

END.

IF RowObject.Cust-Num <= 0 THEN DO:

ASSIGN i-seq-erro = i-seq-erro + 1.

RUN utp/ut-msgs.p (INPUT "MSG":U, INPUT 9999, INPUT "":U).

CREATE tt-bo-erro.

ASSIGN tt-bo-erro.i-sequen = i-seq-erro

tt-bo-erro.cd-erro = 9999

tt-bo-erro.mensagem = RETURN-VALUE.

END.

RUN validateFields IN THIS-PROCEDURE.

FIND FIRST tt-bo-erro NO-ERROR.

IF NOT AVAILABLE tt-bo-erro THEN DO:

RUN executeCreate IN THIS-PROCEDURE.

ASSIGN r-chave = TO-ROWID(RETURN-VALUE).

END.

END PROCEDURE.

Page 53: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 4 Convertendo BO 1.1 para DBO 2.0 51

OBSERVAÇÃO: O utilitário UTP/UT-MSGS.P era utilizado em

SmartObjects, porém, não deverá ser utilizado em DBOs, conforme

conceito da tecnologia de DBOs.

Método novo:

Toda a lógica responsável pela criação dos novos registros foi passada para o

método createRecord, que é um método básico ao qual o desenvolvedor não

tem acesso. Este método é responsável pela execução do método

validateRecord e de seus métodos override.

Neste caso é demonstrado somente a transferência das validações. Parte do

código que o desenvolvedor possui acesso.

PROCEDURE validateRecord:

IF RowObject.Cust-Num <= 0 THEN DO:

{method/svc/errors/inserr.i

&ErrorNumber="9999"

&ErrorType="EMS"

&ErroSubType="ERRO"

&ErrorParameters="''"}

END.

IF CAN-FIND(FIRST RowErrors) THEN

RETURN "NOK":U.

RETURN "OK":U.

END PROCEDURE.

PROCEDURE beforecreateRecord:

IF CAN-FIND(FIRST Customer WHERE Customer.Cust-Num =

RowObject.Cust-Num)

THEN DO:

{method/svc/errors/inserr.i

&ErrorNumber="9999"

&ErrorType="EMS"

&ErroSubType="ERRO"

&ErrorParameters="''"}

END.

IF CAN-FIND(FIRST RowErrors) THEN

RETURN "NOK":U.

RETURN "OK":U.

END PROCEDURE.

Nesta conversão, o método validateCreate foi substituído por 2 (dois) outros

métodos definidos pelo usuário e 1 (um) definido em include padrão. E ainda,

para realizar a criação de registro deve-se utilizar o método createRecord.

Conforme exemplo a seguir:

Page 54: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

52

RUN setRecord IN THIS-PROCEDURE (INPUT TABLE RowObject).

RUN createRecord IN THIS-PROCEDURE.

validateUpdate

Este método foi dividido em novos métodos, sendo 1 (um) deles definido

dentro do DBO e outro em include padrão.

Neste método, a parte responsável pelas validações específicas à alteração

devem ser transferidas para o método beforeUpdateRecord; as validações

análogas à criação e alteração devem ser transferidas para o método

validateRecord. E ainda, caso ocorra algum erro nas validações, ao final deve

ser retornado um flag "NOK":U através do comando RETURN-VALUE.

Quanto aos erros ocorridos, estes devem ser cadastrados na temp-table

RowErrors através da include method/svc/errors/inserr.i.

Estes procedimentos são demonstrados através do exemplo a seguir:

Método antigo:

PROCEDURE validateUpdate:

DEFINE INPUT PARAMETER TABLE FOR RowObject.

DEFINE INPUT PARAMETER r-chave AS ROWID NO-UNDO.

DEFINE OUTPUT PARAMETER TABLE FOR tt-bo-erro.

FOR EACH tt-bo-erro:

DELETE tt-bo-erro.

END.

RUN validateFields IN THIS-PROCEDURE.

FIND FIRST tt-bo-erro NO-ERROR.

IF NOT AVAILABLE tt-bo-erro THEN DO:

FIND {&Table-Name} WHERE ROWID({&Table-Name}) = r-chave

EXCLUSIVE-LOCK NO-ERROR.

IF AVAILABLE {&Table-Name} THEN

RUN executeUpdate IN THIS-PROCEDURE.

END.

END PROCEDURE.

Método novo:

Toda a lógica responsável pela alteração de registros foi passada para o

método updateRecord, ao qual o desenvolvedor não tem acesso. Este método é

responsável pela execução do método validateRecord e de seus métodos

override.

Nesta conversão, o método validateUpdate foi substituído por 1 (um) método

definido pelo usuário e 1 (um) definido em include padrão. E ainda, para

Page 55: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 4 Convertendo BO 1.1 para DBO 2.0 53

realizar a alteração de registro deve-se utilizar o método updateRecord.

Conforme exemplo a seguir:

/* Pode-se utilizar 1 (um) dos métodos de navegação: getFirst, getLast,

getNext, getPrev ou repositionRecord, conforme a implementação */

RUN repositionRecord IN THIS-PROCEDURE (INPUT r-Rowid).

RUN setRecord IN THIS-PROCEDURE (INPUT TABLE RowObject).

RUN updateRecord IN THIS-PROCEDURE.

validateDelete

Este método foi subdividido em novos métodos, sendo 1 (um) deles definido

dentro do DBO e outro em include padrão.

Neste método, a parte responsável pelas validações específicas à eliminação

devem ser transferidas para o método beforeDeleteRecord. E ainda, caso

ocorra algum erro na validação, ao final deve ser retornado um flag "NOK":U

através do comando RETURN-VALUE.

Quanto aos erros ocorridos, estes devem ser cadastrados na temp-table

RowErrors através da include method/svc/errors/inserr.i.

Método antigo:

PROCEDURE validateDelete:

DEFINE INPUT-OUTPUT PARAMETER r-chave AS ROWID NO-UNDO.

DEFINE OUTPUT PARAMETER TABLE FOR tt-bo-erro.

FIND {&TABLE-NAME} WHERE ROWID({&TABLE-NAME}) = r-chave

EXCLUSIVE-LOCK NO-ERROR.

IF AVAILABLE {&TABLE-NAME} THEN

RUN executeDelete.

IF l-query THEN

GET NEXT {&QUERY-NAME} NO-LOCK NO-WAIT.

ELSE

FIND NEXT {&TABLE-NAME} NO-LOCK NO-ERROR.

IF NOT AVAILABLE {&TABLE-NAME} THEN DO:

IF l-query THEN

GET PREV {&QUERY-NAME} NO-LOCK NO-WAIT.

ELSE

FIND PREV {&TABLE-NAME} NO-LOCK NO-ERROR.

END.

ASSIGN r-chave = ROWID({&TABLE-NAME}).

END PROCEDURE.

Método novo:

Page 56: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

54

Toda a lógica responsável pela eliminação de registros foi passado o método

deleteRecord, que é um método básico que o desenvolvedor não tem acesso.

Porém, este método é responsável pela execução de seus métodos override.

Nesta conversão, o método validateDelete foi substituído por 1 (um) método

definido pelo usuário e 1 (um) definido em include padrão. E ainda, para

realizar a eliminação de registro deve-se utilizar o método deleteRecord.

Conforme exemplo a seguir:

/* Pode-se utilizar 1 (um) dos métodos de navegação: getFirst,

getLast, getNext, getPrev ou repositionRecord, conforme a

implementação */

RUN repositionRecord IN THIS-PROCEDURE (INPUT r-Rowid).

RUN deleteRecord IN THIS-PROCEDURE.

validateFields

Este método foi substituído pelo método validateRecord, que é definido pelo

desenvolvedor.

Neste método, estão as validações análogas aos métodos de createRecord e

updateRecord. E ainda, caso ocorra algum erro na validação, ao final deve ser

retornado um flag "NOK":U, através do comando RETURN-VALUE, ou um

flag "OK":U caso não ocorre nenhum erro.

Quanto aos erros ocorridos, estes devem ser cadastrados na temp-table

RowErrors através da include method/svc/errors/inserr.i.

Estes procedimentos são demonstrados através do exemplo a seguir:

Método antigo:

PROCEDURE validateFields:

FIND FIRST RowObject NO-ERROR.

IF RowObject.Cust-Num <= 0 THEN DO:

ASSIGN i-seq-erro = i-seq-erro + 1.

RUN utp/ut-msgs.p (INPUT "MSG":U, INPUT 9999, INPUT "":U).

CREATE tt-bo-erro.

ASSIGN tt-bo-erro.i-sequen = i-seq-erro

tt-bo-erro.cd-erro = 999

tt-bo-erro.mensagem = RETURN-VALUE.

END.

IF RowObject.Name = "":U OR RowObject.Name = ? THEN DO:

ASSIGN i-seq-erro = i-seq-erro + 1.

RUN utp/ut-msgs.p (INPUT "MSG":U, INPUT 9999, INPUT "":U).

Page 57: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 4 Convertendo BO 1.1 para DBO 2.0 55

CREATE tt-bo-erro.

ASSIGN tt-bo-erro.i-sequen = i-seq-erro

tt-bo-erro.cd-erro = 999

tt-bo-erro.mensagem = RETURN-VALUE.

END.

END PROCEDURE.

OBSERVAÇÃO: O utilitário UTP/UT-MSGS.P era utilizado em

SmartObjects, porém, não deverá ser utilizado em DBOs, conforme

conceito da tecnologia de DBOs.

Método novo:

PROCEDURE validateRecord:

IF RowObject.Cust-Num <= 0 THEN

{method/svc/errors/inserr.i

&ErrorNumber="9999"

&ErrorType="EMS"

&ErroSubType="ERRO"

&ErrorParameters="''"}

IF RowObject.Name = "":U OR RowObject.Name = ? THEN

{method/svc/errors/inserr.i

&ErrorNumber="9999"

&ErrorType="EMS"

&ErroSubType="ERRO"

&ErrorParameters="''"}

IF CAN-FIND(FIRST RowObject) THEN

RETURN "NOK":U.

RETURN "OK":U.

END PROCEDURE.

Nesta conversão, o método validateFields foi substituído pelo método

validateRecord. E ainda, a gravação dos erros é feita através da include

method/svc/errors/inserr.i e ao final do processo é retornada a flag que indica

a existência de erros ou não.

Vale salientar que este método é executado internamente, não havendo

necessidade do client executá-lo.

Page 58: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características
Page 59: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

57

CAPÍTULO 5

Convertendo SmartObjects para DBO 2.0

Este capítulo é destinado ao desenvolvedor que utiliza SmartObjects e deseja

convertê-los para DBOs 2.0.

Para converter um SmartObject devem ser seguidos os seguintes passos:

Criar um novo DBO 2.0;

Transferir lógicas dos métodos dos SmartObjects para o DBO 2.0.

A seguir são detalhados os passos:

Criar o novo DBO

Este passo está detalhado no item 'Construindo o DBO'.

Transferir lógicas dos métodos dos SmartObjects para o DBO 2.0

Quando se trabalha com SmartObjects, a lógica de navegação, leitura,

consulta, alteração, etc. está em diferentes programas. Por exemplo: a lógica

de navegação está na SmartQuery, a lógica de gravação está em várias

SmartViewers, etc.

Mas ao utilizar DBOs toda a lógica de tratamento de registro encontra-se no

DBO. Através disto, basta o desenvolvedor transferir as lógicas dos

SmartObjects para os DBOs, conforme descrito a seguir:

SmartQuery

Toda a lógica de abertura de query deve ser transferida para os métodos

openQuery<Description>. Além disso, caso a SmartQuery faça uso de mais de

Definição

Page 60: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

58

uma tabela, isto deve ser substituído pelo uso do método

setConstraint<Description> e linkTo<Description>.

E, ainda, todas as restrições impostas à abertura da query, também devem ser

transferidas para seus respectivos métodos setConstraint<Description>.

A seguir, um exemplo, no qual a SmartQuery possuía a tabela Customer e a

tabela SalesRep, como tabela estrangeira.

DEFINE VARIABLE cSales-Rep LIKE Customer.Sales-Rep NO-UNDO.

PROCEDURE openQueryMain:

IF cSales-Rep = "" THEN

OPEN QUERY {&QueryName}

FOR EACH Customer NO-LOCK.

ELSE

OPEN QUERY {&QueryName}

FOR EACH Customer

WHERE Customer.Sales-Rep = cSales-Rep

NO-LOCK.

END PROCEDURE.

PROCEDURE openQueryByName:

IF cSales-Rep = "" THEN

OPEN QUERY {&QueryName}

FOR EACH Customer NO-LOCK BY Customer.Name.

ELSE

OPEN QUERY {&QueryName}

FOR EACH Customer

WHERE Customer.Sales-Rep = cSales-Rep

NO-LOCK BY Customer.Name.

END PROCEDURE.

PROCEDURE openQuerySalesRep:

OPEN QUERY {&QueryName}

FOR EACH Customer

WHERE Customer.Sales-Rep = cSales-Rep

NO-LOCK.

END PROCEDURE.

PROCEDURE setConstraintSalesRep:

DEFINE INPUT PARAMETER pSales-Rep LIKE Customer.Sales-Rep NO-

UNDO.

ASSIGN cSales-Rep = pSales-Rep.

RETURN "OK":U.

END PROCEDURE.

PROCEDURE linkToSalesRep:

DEFINE INPUT PARAMETER pHandle AS HANDLE NO-UNDO.

DEFINE VARIABLE cSalesAux LIKE Customer.Sales-Rep NO-UNDO.

Page 61: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 5 Convertendo SmartObjects para DBO 2.0 59

RUN getKey IN pHandle (OUTPUT cSalesAux).

RUN setConstraintSalesRep IN THIS-PROCEDURE (INPUT cSalesAux).

END PROCEDURE.

Neste exemplo, foram definidos 3 (três) métodos de abertura de query, pois o

DBO normalmente é único por tabela. Sendo assim, criou-se os métodos

setConstraintSalesRep e linkToSalesRep.

Estes métodos serão utilizados para fazer a comunicação entre um DBO Pai

(SalesRep) e um DBO Filho (Customer), porém o DBO Filho também terá

opções de aberturas independente do DBO Pai.

SmartViewer

Toda a lógica de gravação da viewer deve ser transferida para os métodos

before/afterCreateRecord ou before/afterUpdateRecord.

A seguir, um exemplo, no qual a SmartViewer fazia a gravação automática do

campo cust-num no momento de criação do registro.

Método Antigo:

DEFINE BUFFER bfCustomer FOR Customer.

PROCEDURE local-create-record:

DEFINE VARIABLE iCust-Num AS INTEGER NO-UNDO.

FIND LAST bfCustomer NO-LOCK NO-ERROR.

IF AVAILABLE bfCustomer THEN

ASSIGN iCust-Num = bfCustomer.Cust-Num + 1.

ELSE

ASSIGN iCust-Num = 1.

RUN dispatch IN THIS-PROCEDURE ("create-record":U).

IF RETURN-VALUE = "ADM-ERROR":U THEN

RETURN "ADM-ERROR":U.

ASSIGN Customer.Cust-Num = iCust-Num.

END PROCEDURE.

Método Novo:

DEFINE BUFFER bfCustomer FOR Customer.

PROCEDURE beforeCreateRecord:

DEFINE VARIABLE iCust-Num AS INTEGER NO-UNDO.

FIND LAST bfCustomer NO-LOCK NO-ERROR.

IF AVAILABLE bfCustomer THEN

ASSIGN iCust-Num = bfCustomer.Cust-Num + 1.

ELSE

ASSIGN iCust-Num = 1.

Page 62: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

60

ASSIGN RowObject.Cust-Num = iCust-Num.

RETURN "OK":U.

END PROCEDURE.

Neste exemplo, foi definido o método beforeCreateRecord para realizar a

atualização do campo cust-num. Vale salientar que somente será atualizado

este campo se for feita uma criação.

A seguir, um exemplo, no qual são feitas atualizações comuns a criação e

alteração de registro da tabela Customer:

Método Antigo:

PROCEDURE local-assign-record:

RUN dispatch IN THIS-PROCEDURE ("assign-record":U).

IF RETURN-VALUE = "ADM-ERROR":U THEN

RETURN "ADM-ERROR":U.

ASSIGN Customer.Credit-Limit = Customer.Credit-Limit * 1.10.

END PROCEDURE.

Método Novo:

PROCEDURE before_copyTT2Buffer:

ASSIGN RowObject.Credit-Limit = RowObject.Credit-Limit *

1.10.

RETURN "OK":U.

END PROCEDURE.

Neste exemplo, criou-se o método before_copyTT2Buffer. O qual é executado

antes da transferência dos dados da temp-table RowObject para a tabela

principal do DBO.

A seguir, um exemplo, no qual são feitas validações de criação de registro:

Método Antigo:

PROCEDURE local-assign-record:

DEFINE VARIABLE iCust-Num AS INTEGER NO-UNDO.

ASSIGN iCust-Num = INTEGER(Customer.Cust-Num:SCREEN-VALUE

IN FRAME {&FRAME-NAME}).

IF adm-new-record THEN

IF CAN-FIND(Customer WHERE Customer.Cust-Num = iCustNum)

THEN DO:

RUN utp/ut-msgs.p (INPUT "SHOW":U,

INPUT <ErrorNumber>

INPUT <ErrorParameters>).

RETURN "ADM-ERROR":U.

END.

Page 63: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 5 Convertendo SmartObjects para DBO 2.0 61

RUN dispatch IN THIS-PROCEDURE ("assign-record":U).

IF RETURN-VALUE = "ADM-ERROR":U THEN

RETURN "ADM-ERROR":U.

END PROCEDURE.

OBSERVAÇÃO: O utilitário UTP/UT-MSGS.P era utilizado em

SmartObjects, porém, não deverá ser utilizado em DBOs, conforme

conceito da tecnologia de DBOs.

Método Novo:

PROCEDURE beforeCreateRecord:

IF CAN-FIND(Customer WHERE Customer.Cust-Num =

RowObject.Cust-Num) THEN DO:

{method/svc/errors/inserr.i

&ErrorNumber="9999"

&ErrorType="EMS"

&ErroSubType="ERRO"

&ErrorParameters="''"}

RETURN "NOK":U.

END.

RETURN "OK":U.

END PROCEDURE.

Neste exemplo, foi definido o método beforeCreateRecord para realizar a

validação de registro duplicado. Vale salientar que somente será executada

esta validação quando for feita a criação de registros.

A seguir, um exemplo, no qual são feitas validações comuns à criação e

alteração de registro:

Método Antigo:

PROCEDURE pi-validate:

{include/i-vldfrm.i}

IF Customer.Name = "":U THEN DO:

{include/i-vldprg.i}

RUN utp/ut-msgs.p (INPUT "SHOW":U,

INPUT <ErrorNumber>,

INPUT <ErrorParameters>).

APPLY "ENTRY":U TO Customer.Name IN FRAME {&FRAME-NAME}.

RETURN "ADM-ERROR":U.

END.

END PROCEDURE.

Page 64: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

62

OBSERVAÇÃO: O utilitário UTP/UT-MSGS.P era utilizado em

SmartObjects, porém, não deverá ser utilizado em DBOs, conforme

conceito da tecnologia de DBOs.

Método Novo:

PROCEDURE validateRecord:

IF RowObject.Name = "":U THEN

{method/svc/errors/inserr.i

&ErrorNumber="9999"

&ErrorType="EMS"

&ErroSubType="ERROR"

&ErrorParameters="''"}

IF CAN-FIND(FIRST RowErrors) THEN

RETURN "NOK":U.

RETURN "OK":U.

END PROCEDURE.

Neste exemplo, foi definido o método validateRecord para realizar a validação

sobre o campo name. Vale salientar que este método será executado tanto na

criação como na alteração de registros.

A seguir, um exemplo, no qual são feitas validações de eliminação de registro:

Método Antigo:

PROCEDURE local-delete-record:

IF CAN-FIND(FIRST Order OF Customer) THEN DO:

RUN utp/ut-msgs.p (INPUT "SHOW":U,

INPUT <ErrorNumber>,

INPUT <ErrorParameters>).

RETURN "ADM-ERROR":U.

END.

RUN dispatch IN THIS-PROCEDURE ("delete-record":U).

END PROCEDURE.

OBSERVAÇÃO: O utilitário UTP/UT-MSGS.P era utilizado em

SmartObjects, porém, não deverá ser utilizado em DBOs, conforme

conceito da tecnologia de DBOs.

Método Novo:

PROCEDURE beforeDeleteRecord:

IF CAN-FIND(FIRST Order OF RowObject) THEN

{method/svc/errors/inserr.i

&ErrorNumber="9999"

Page 65: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 5 Convertendo SmartObjects para DBO 2.0 63

&ErrorType="EMS"

&ErroSubType="ERRO"

&ErrorParameters="''"}

IF CAN-FIND(FIRST RowErrors) THEN

RETURN "NOK":U.

RETURN "OK":U.

END PROCEDURE.

Neste exemplo, foi definido o método beforeDeleteRecord para realizar a

validação a fim de verificar se o registro pode ser eliminado.

Triggers de Dicionário

Quando utilizada uma trigger de create, toda a lógica deve ser transferida para

o método beforeCreateRecord.

A seguir, um exemplo, no qual são setados valores automaticamente para a

tabela Customer:

Método Antigo:

TRIGGER PROCEDURE FOR create OF customer.

ASSIGN Customer.Cust-Num = NEXT-VALUE(next-cust-num).

Método Novo:

DEFINE BUFFER bfCustomer FOR Customer.

PROCEDURE beforeCreateRecord:

FIND LAST bfCustomer NO-LOCK NO-ERROR.

IF AVAILABLE bfCustomer THEN

ASSIGN RowObject.Cust-Num = bfCustomer.Cust-Num + 1.

ELSE

ASSIGN RowObject.Cust-Num = 1.

RETURN "OK":U.

END PROCEDURE.

Neste exemplo, foi criado o método beforeCreateRecord para realizar a

gravação automática do campo cust-num, no momento de criação do registro.

Quando utilizada uma trigger de delete, toda a lógica de validação deve ser

transferida para o método beforeDeleteRecord e a lógica de eliminação em

cascata deve ser transferida para o método afterDeleteRecord.

A seguir, um exemplo, no qual é feita a eliminação em cascata de registros:

Método Antigo:

TRIGGER PROCEDURE FOR delete OF customer.

FOR EACH Order OF Customer:

Page 66: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

64

DELETE Order.

END.

Método Novo:

PROCEDURE afterDeleteRecord:

FOR EACH Order OF RowObject:

DELETE Order.

END.

RETURN "OK":U.

END PROCEDURE.

Neste exemplo, foi criado o método afterDeleteRecord para realizar a

eliminação em cascata da tabela Order.

Quando utilizado uma trigger de write, toda a lógica de validação deve ser

transferida para o método validateRecord (quando estas forem comuns à

criação e alteração) ou beforeUpdateRecord (quando estas forem pertinentes à

alteração) .

A lógica de atualização deve ser transferida para o método

before_copyTT2Buffer (quando estas forem comuns à criação e alteração) ou

para o método beforeUpdateRecord (quando estas foram pertinentes à

alteração) ou para o método afterUpdateRecord (quando estas foram

atualizações em cascata).

A seguir, um exemplo, no qual são feitas validações comuns à criação e

alteração; atualizações automáticas de campos da tabela customer;

atualizações em cascata de outras tabelas:

Método Antigo:

TRIGGER PROCEDURE FOR write OF customer OLD BUFFER oldcustomer.

IF Customer.Name = "":U THEN DO:

RUN utp/ut-msgs.p (INPUT "SHOW":U,

INPUT <ErrorNumber>,

INPUT <ErrorParameters>).

RETURN ERROR.

END.

IF Customer.Address2 = "":U THEN

ASSIGN Customer.Address2 = Customer.Address.

IF Customer.Cust-Num <> oldCustomer.Cust-Num THEN

FOR EACH Order OF oldCustomer:

ASSIGN Order.Cust-Num = Customer.Cust-Num.

END.

END.

Page 67: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 5 Convertendo SmartObjects para DBO 2.0 65

OBSERVAÇÃO: O utilitário UTP/UT-MSGS.P era utilizado em

SmartObjects, porém, não deverá ser utilizado em DBOs, conforme

conceito da tecnologia de DBOs.

Método Novo:

PROCEDURE validateRecord:

IF RowObject.Name = "":U THEN

{method/svc/errors/inserr.i

&ErrorNumber="9999"

&ErrorType="EMS"

&ErroSubType="ERRO"

&ErrorParameters="''"}

IF CAN-FIND(FIRST RowErrors) THEN

RETURN "NOK":U.

RETURN "OK":U.

END PROCEDURE.

PROCEDURE before_copyTT2Buffer:

IF RowObject.Address2 = "":U THEN

ASSIGN RowObject.Address2 = RowObject.Adress.

RETURN "OK":U.

END PROCEDURE.

PROCEDURE beforeUpdateRecord:

IF RowObject.Cust-Num <> Customer.Cust-Num THEN

FOR EACH Order OF Customer:

ASSIGN Order.Cust-Num = RowObject.Cust-Num.

END.

END PROCEDURE.

Neste exemplo, foi criado o método validateRecord para realizar validações

comuns à criação e alteração de registro. E ainda, o método

before_copyTT2Buffer para realizar atualizações comuns à criação e alteração.

E, além disso, o método beforeUpdateRecord para realizar atualizações em

cascata pertinentes à alteração.

Observação: Ao retirar as lógicas de negócio das triggers de dicionário, deve-

se manter as chamadas de UPCs nas triggers.

SmartBrowse

Os SmartBrowses devem ser analisados conforme sua funcionalidade.

Caso o SmartBrowse seja utilizado para navegação, deve-se seguir as mesmas

regras sugeridas para SmartQuery. Mas, caso o SmartBrowse seja utilizado

Page 68: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

66

para update (inclusão/alteração/exclusão) deve-se seguir as mesmas regras

sugeridas para SmartViewer.

Page 69: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

67

CAPÍTULO 6

Serviços Padrão

Neste capítulo estão informações para que o administrador possa definir os

serviços padrão para o DBO, a fim de permitir que o desenvolvedor possa

utilizá-los de forma segura, integra, rápida e eficiente.

O que são serviços? Nada mais são, do que programas/procedures internas que

podem estar disponíveis para o DBO conforme a configuração feita para o

Produto.

Os serviços padrão disponíveis ao DBO são:

Implementações conforme tipo de Banco de Dados;

Customização para Parceiros/Clientes;

Erros do Produto;

Tratamento de erros Progress;

Segurança para o programa DBO;

Segurança aos métodos do programa DBO.

Estes serviços são criados e manutenidos por uma equipe de administração do

produto.

A configuração destes serviços é feito no include dboconfig/svcdesfs.i.

Conforme código a seguir:

/*--- Com base no {&DBType} serão executados procedimentos para

corrigir deficiências do produto PROGRESS, quando utilizar

banco de dados não PROGRESS ---*/

&GLOBAL-DEFINE DBType <tipo-do-banco-de-dados>

Introdução

Definição

Page 70: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

68

/*--- Com base no {&SOAutentic} será executado o programa que irá

verificar a autenticidade de DBOs e, ainda, retornará o

usuário corrente, através de método específico ---*/

&GLOBAL-DEFINE SOAutentic <nome-do-programa>

/*--- Com base no {&SOCustom} será executado o programa que irá

verificar quais programas de customização devem ser

executados ---*/

&GLOBAL-DEFINE SOCustom <nome-do-programa>

/*--- Com base no {&SOErrors} será executado o programa que

retorna informações sobre os erros de Produto, tais como:

texto e help ---*/

&GLOBAL-DEFINE SOErrors <nome-do-programa>

/*--- Com base no {&SOSecurity} será executado o programa que irá

verificar a segurança de DBOs e, ainda, retornará a lista

de métodos disponíveis para execução ---*/

&GLOBAL-DEFINE SOSecurity <nome-do-programa>

Serviço de Banco

Este serviço é definido através do preprocessador {&DBType} que contém o

tipo de banco de dados do produto.

Através deste preprocessador são executados lógicas/métodos alternativos a

fim de corrigir deficiências do produto Progress quando utiliza banco de dados

não Progress. Algumas destas implementações já estão feitas dentro dos

includes padrão do DBO.

Exemplo: Definindo valor para o preprocessador {&DBType}.

&GLOBAL-DEFINE DBType ORACLE

Serviço de Customização

Este serviço é definido através do preprocessador {&SOCustom} que contém

o nome do programa responsável pelos programas de customização do DBO.

Através deste preprocessador é executado o programa de tratamento de

customizações.

Além disso, este serviço é usado internamente nos métodos createRecord,

updateRecord e deleteRecord. Nestes métodos é executado o Serviço de

Customização no ponto inicial e final do método. Mas o desenvolvedor pode

optar por incluir manualmente a chamada ao Serviço de Customização.

Page 71: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 6 Serviços Padrão 69

O programa de serviço de customização é executado persistente, e deve

possuir um método chamado publish, para realizar o tratamento de

customizações do produto, com a definição de parâmetros a seguir:

DEFINE INPUT PARAMETER pEvent AS CHARACTER NO-UNDO.

DEFINE INPUT PARAMETER pDBOHandle AS HANDLE NO-UNDO.

O código de implementação para chamada ao programa de Serviço de

Customização está definida no include method/svc/custom/custom.i. E, ainda,

caso exista a necessidade de definição de métodos auxiliares ou variáveis deve

ser feito no include method/svc/custom/customdefs.i. A seguir, está o código

padrão destes includes.

Include: method/svc/custom/customdefs.i

DEFINE NEW GLOBAL SHARED VARIABLE hSOCustom AS HANDLE NO-UNDO.

Include: methos/svc/custom/custom.i

&IF "{&SOCustom}":U <> "":U &THEN

IF NOT VALID-HANDLE(hSOCustom) OR

hSOCustom:FILE-NAME <> "{&SOCustom}":U THEN

RUN {&SOCustom} PERSISTENT SET hSOCustom.

RUN publish IN hSOCustom (INPUT "{&Event}":U,

INPUT THIS-PROCEDURE:HANDLE).

ASSIGN lCustomExecuted = YES.

&ELSE

ASSIGN lCustomExecuted = NO.

&ENDIF

A implementação dentro do programa DBO é feita da seguinte maneira:

{method/svc/custom/custom.i

&Event="<EventName>"}

Serviço de Erros

Este serviço é definido através do preprocessador {&SOError} que contém o

nome do programa responsável por retornar informações sobre mensagens de

erro do Produto e tratamento de mensagens de erro Progress.

Através deste preprocessador é executado o programa de tratamento de erros

do produto e erros Progress.

O programa de serviço de erros é executado persistente, e deve possuir um

método chamado getMessageInformation, para realizar o tratamento de erros

do produto, com a definição de parâmetros a seguir:

Page 72: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

70

DEFINE INPUT PARAMETER pErrorNumber AS INTEGER NO-UNDO.

DEFINE INPUT PARAMETER pErrorParameters AS CHARACTER NO-UNDO.

DEFINE OUTPUT PARAMETER pErrorDescription AS CHARACTER NO-UNDO.

DEFINE OUTPUT PARAMETER pErrorHelp AS CHARACTER NO-UNDO.

E deve possuir um método chamado getMessagePSCInformation, para realizar

o tratamento de erros Progress, com a definição de parâmetros a seguir:

DEFINE INPUT PARAMETER pErrorNumber AS INTEGER NO-UNDO.

DEFINE OUTPUT PARAMETER pErrorDescription AS CHARACTER NO-UNDO.

DEFINE OUTPUT PARAMETER pErrorHelp AS CHARACTER NO-UNDO.

O código de implementação para chamada ao programa de Serviço de Erros,

quando utilizado para tratamento de erros do produto, está definida no include

method/svc/errors/errors.i. E, ainda, caso exista a necessidade de definição de

métodos auxiliares ou variáveis deve ser feito no include

method/svc/errors/errdefs.i. A seguir, está o código padrão destes includes.

Include: method/svc/errors/errdefs.i

DEFINE NEW GLOBAL SHARED VARIABLE hSOErrors AS HANDLE NO-UNDO.

Include: methos/svc/errors/errors.i

&IF "{&SOErrors}":U <> "":U &THEN

IF NOT VALID-HANDLE(hSOErrors) THEN

RUN {&SOErrors} PERSISTENT SET hSOErrors.

RUN getMessageInformation IN hSOErrors

(INPUT {&ErrorNumber},

INPUT {&ErrorParameters},

OUTPUT {&vErrorDescrption},

OUTPUT {&vErrorHelp}).

&ENDIF

A implementação dentro do programa DBO é feita da seguinte maneira:

DEFINE VARIABLE cErrorDescription AS CHARACTER NO-UNDO.

DEFINE VARIABLE cErrorHelp AS CHARACTER NO-UNDO.

{method/svc/errors/errors.i

&ErrorNumber="<ErrorNumber>"

&ErrorParameters="<ErrorParameters>"

&vErrorDescription="cErrorDescription"

&vErrorHelp="cErrorHelp"}

Quando utilizado o programa de Serviço de Erros, para tratamento de erros

Progress, o código de implementação está definido no include

method/svc/errors/errorspsc.i. E, ainda, caso exista a necessidade de definição

de métodos auxiliares ou variáveis deve ser feito no include

method/svc/errors/errdefs.i. A seguir, está o código padrão destes includes.

Include: method/svc/errors/errdefs.i

Page 73: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 6 Serviços Padrão 71

DEFINE NEW GLOBAL SHARED VARIABLE hSOErrors AS HANDLE NO-UNDO.

Include: methos/svc/errors/errorspsc.i

&IF "{&SOErrors}":U <> "":U &THEN

IF NOT VALID-HANDLE(hSOErrors) THEN

RUN {&SOErrors} PERSISTENT SET hSOErrors.

RUN getMessagePSCInformation IN hSOErrors

(INPUT {&ErrorNumber},

OUTPUT {&vErrorDescription},

OUTPUT {&vErrorHelp}).

&ENDIF

A implementação dentro do programa DBO é feita da seguinte maneira:

DEFINE VARIABLE cErrorDescription AS CHARACTER NO-UNDO.

DEFINE VARIABLE cErrorHelp AS CHARACTER NO-UNDO.

{method/svc/errors/errorspsc.i

&ErrorNumber="<ErrorNumber>"

&vErrorDescription="cErrorDescription"

&vErrorHelp="cErrorHelp"}

Para incluir erros na RowErrors a partir de uma api deve-se utilizar a include

method/svc/errors/inserrapi.i, com os mesmos preprocessadores da

method/svc/errors/inserr.i, porém com um preprocessador a mais: &Handledbo

– Este preprocessador deve receber a variável que contém o handle do dbo

onde serão criados os erros.

{method/svc/errors/inserrapi.i &Handledbo="h-bo"

&ErrorNumber=1

&ErrorType="EMS"

&ErrorSubType="Error"

&ErrorDescription="Estado utilizado por

customer"}

Serviço de Segurança

Este serviço é definido através do preprocessador {&SOSecurity} que contém

o nome do programa responsável por verificar a segurança do DBO.

Além disso, este serviço é usado internamente nos includes padrões. Nesses, é

feita a verificação de segurança do programa DBO e caso não tenha permissão

de execução é executado automaticamente o método destroy.

Page 74: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

72

O programa de Segurança é executado persistent, e deve possuir um método

chamado verifySecurity com a definição de parâmetros a seguir:

DEFINE INPUT PARAMETER pDBOName AS CHARACTER NO-UNDO.

DEFINE INPUT PARAMETER pDBOHandle AS HANDLE NO-UNDO.

DEFINE OUTPUT PARAMETER pFunctionsPermited AS CHARACTER NO-UNDO.

DEFINE OUTPUT PARAMETER pVerifyOK AS LOGICAL NO-UNDO.

O código de implementação para a chamada ao programa de Serviço de

Segurança está definido no include method/svc/security/security.i. E, ainda,

caso exista a necessidade de definição de métodos auxiliares ou variáveis deve

ser feito no include method/svc/security/sctrdefs.i. A seguir, está o código

padrão destes includes.

Include: method/svc/security/sctrdefs.i

DEFINE NEW GLOBAL SHARED VARIABLE hSOSecurity AS HANDLE NO-UNDO.

DEFINE VARIABLE lSecurityOK AS LOGICAL NO-UNDO.

DEFINE VARIABLE cFunctionsPermited AS CHARACTER NO-UNDO.

Include: method/svc/security/security.i

&IF "{&SOSecurity}":U <> "":U &THEN

IF NOT VALID-HANDLE(hSOSecurity) THEN

RUN {&SOSecurity} PERSISTENT SET hSOSecurity.

RUN verifySecurity IN hSOSecurity

(INPUT THIS-PROCEDURE:FILE-NAME,

INPUT THIS-PROCEDURE:HANDLE,

OUTPUT cFunctionsPermited,

OUTPUT lSecurityOK).

IF NOT lSecurityOK THEN

RUN destroy IN THIS-PROCEDURE.

&ENDIF

A implementação dentro do programa DBO deve ser feita da seguinte maneira:

{method/svc/security/security.i}

Também, existe o Serviço de Segurança para verificar permissão de execução

de métodos. Esta subdivisão é usada automaticamente pelos includes padrão.

Porém, o desenvolvedor pode utilizar este serviço quando houver a

necessidade de implementar segurança para métodos específicos.

O código de implementação para a chamada ao método de Verificação de

Permissão de Execução de Métodos está definido no include

method/svc/security/permit.i. A seguir, está o código padrão deste include:

Include: methos/svc/security/permit.i

&IF "{&SOSecurity}":U <> "":U &THEN

RUN _canRunMethod IN THIS-PROCEDURE (INPUT "{&Method}":U).

Page 75: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 6 Serviços Padrão 73

IF RETURN-VALUE = "NOK":U THEN DO:

/* Falta de permissão para execução de método */

RUN setRowErrors IN THIS-PROCEDURE (INPUT 1,

INPUT "INTERNAL":U,

INPUT "":U).

RETURN "NOK":U.

END.

&ENDIF

Vale salientar mais uma característica deste serviço:

Quando for criado um novo método, pelo desenvolvedor, e houver a

necessidade de segurança deve ser passado como parâmetro ao include o

nome do método, ou pode-se simplesmente passar para um termo genérico

que identifique um grupo de métodos. Além disso, essa identificação deve

ser inclusa no pré-processador DBOCustomFunctions, que encontra-se na

sessão Definitions.

A implementação dentro do programa DBO deve ser feita da seguinte maneira:

{method/svc/security/permit.i &Method="<MethodName/FuncionName>"}

Serviço de Message Broker

Este serviço é definido através do preprocessador {&SOMessageBroker} que

contém o nome do programa que atua como Message Broker.

O Message Broker é responsável por encaminhar as mensagens XML geradas

pelo DBO quando um registro é incluído, alterado ou eliminado através dos

métodos createRecord(), updateRecord() e deleteRecord() respectivamente. O

serviço de Message Broker só é usado nos DBOs que tiverem o pré-

processador {&XMLProducer} definido.

O Message Broker pode retornar uma mensagem que será ignorada pelo DBO,

exceto se esta for uma mensagem de erro. Neste caso os erros retornados pelo

Message Broker são adicionados a lista de erros do DBO e toda a transação é

desfeita.

O Message Broker deve disponibilizar os seguintes métodos:

sendMessage

Realiza o envio da mensagem.

Sintaxe:

Page 76: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

74

RUN sendMessage IN <handle Message Broker>

(INPUT pSendindMessage X-DOCUMENT,

OUTPUT pReturnMessage X-DOCUMENT).

Parâmetros:

pSendingMessage: Mensagem que deve ser enviado pelo Message Broker

a destinatários pré-definidos.

pReturnMessage: Mensagem de retorno indicando sucesso ou erro no

envio da mensagem.

Formato da mensagem XML requerida por pSendingMessage:

<DATASUL-MESSAGE>

<TOPIC>

<MODE>

</DATASUL-MESSAGE>

Parâmetros da mensagem XML de pSendingMessage:

<TOPIC>: Indica o assunto a que se refere a mensagem. Através deste o

Message Broker poderá determinar o destino da mensagem.

<MODE>: Indica se a mensagem deve ser enviada de forma síncrona (SYNC)

ou assíncrona (ASYNC). Se não indicado este parâmetro o Message Broker

deve definir o tratamento que será dado a mensagem.

getSendMode

Indica as formas de envio que serão utilizadas pelo Message Broker para uma

mensagem com o tópico informado.

Sintaxe:

RUN getsendMode IN <handle Message Broker>

(INPUT pTopic CHAR,

OUTPUT pSendMode CHAR).

Parâmetros:

pTopic: Tópico para o qual deseja-se saber os modos de envio.

pSendMode: Forma de envio da mensagem:

“”: Não existe assinatura para o tópico;

Page 77: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 6 Serviços Padrão 75

SYNC: Todos os assinantes são síncronos;

ASYNC: Todos os assinantes são assíncronos;

SYNC, ASYNC: Existem assinantes síncronos e assíncronos.

Contexto de Sessão WEB no DBO

É possível de dentro de uma DBO quando se está trabalhando com WEB,

buscar informações do contexto de sessão. Este conteúdo de sessão está

disponível nas seguintes variáveis:

Variável Retorna Contexto de sessão

bo_v_ind_perfil_usuario Char Usuar_mestre.indPerfilUsuario

bo_v_cod_ext_perfil_usuario Char Usuar_mestre.codExtPerfilUsuario

bo_v_cod_pais_empres_usuar Char empresa.pais

bo_v_pais_impto_usuario Char pais.cod-internacional-pais

bo_v_cod_empres_usuar Char Usuar_univ.cod_empresa

bo_v_cod_usuar_corren_criptog Char v_cod_usuar_corren_criptog

bo_v_ind_tip_usuar Char Usuar_mestre.ind_tip_usuar

bo_v_cod_idiom_usuar Char Usuar_mestre.cod_idiom_orig

bo_v_cod_grp_usuar_lst Char Usuar_grp_usuar.cod_grp_usuar

bo_v_cod_usuar_corren Char v_cod_usuario

bo_v_cod_aplicat_dtsul_corren Char v_cod_aplicat_dtsul_corren

bo_v_cod_modul_dtsul_corren Char v_cod_modul_dtsul_corren

Para a utilização destas variáveis, não é necessário nenhuma definição prévia

no DBO, bastando apenas se referenciar à variável desejada.

No exemplo abaixo, demonstra-se como fazer uma referência tanto no

ambiente GUI como no ambiente WEB:

Page 78: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

76

IF SESSION:CLIENT-TYPE = "webspeed" THEN DO:

IF bo_v_pais_impto_usuário <> “” THEN

RUN programa.p.

END.

ELSE DO:

IF i-pais-impto-usuario <> “” THEN

RUN programa.p.

END.

Lembramos que em caso de GUI o sistema utiliza a UT-GLOB para a geração

de variáveis globais.

Page 79: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 7 Técnicas 77

CAPÍTULO 7

Técnicas

Melhorar Performance em Bancos Oracle

Esta técnica apresenta uma alternativa para a melhoria da performance das

DBO´s em ambientes com banco de dados Oracle.

Inserir o pré-processador CHANGE-QUERY-TO-FIND como TRUE;

&GLOBAL-DEFINE CHANGE-QUERY-TO-FIND TRUE

A definição dos comandos de navegação é efetuada pelo desenvolvedor.

Tais métodos devem iniciar por um dos seguintes prefixos: findFirst,

findLast, findNext e findPrev; seguido pelo nome da query existente no

programa.

Assim, para um DBO que possui duas queries, deverão existir dois pares

para cada um dos métodos citados anteriormente. Por exemplo:

O DBO adbo/boad029.p possui duas queries (duas aberturas de queries),

chamadas Main e EmpresaEstab. Assim, deverão ser criados os seguintes

métodos de navegação:

findFirstMain / findLastMain / findNextMain / findPrevMain

findFirstEmpresaEstab / findLastEmpresaEstab /

findNextEmpresaEstab / findPrevEmpresaEstab

E o conteúdo destes métodos será o seguinte:

Objetivo

Implementação

Page 80: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

78

findFirstMain:

FIND FIRST {&TableName} NO-LOCK

WHERE {&TableName}.ep-codigo = i-empresa NO-ERROR.

findLastMain:

FIND LAST {&TableName} NO-LOCK

WHERE {&TableName}.ep-codigo = i-empresa NO-ERROR.

findNextMain:

FIND NEXT {&TableName} NO-LOCK

WHERE {&TableName}.ep-codigo = i-empresa NO-ERROR.

findPrevMain:

FIND PREV {&TableName} NO-LOCK

WHERE {&TableName}.ep-codigo = i-empresa NO-ERROR.

findFirstEmpresaEstab:

FIND FIRST {&TableName} NO-LOCK

WHERE {&TableName}.ep-codigo = i-empresa AND

{&TableName}.cod-estabel = c-cod-estab NO-ERROR.

findLastEmpresaEstab:

FIND LAST {&TableName} NO-LOCK

WHERE {&TableName}.ep-codigo = i-empresa AND

{&TableName}.cod-estabel = c-cod-estab NO-ERROR.

findNextEmpresaEstab:

FIND NEXT {&TableName} NO-LOCK

WHERE {&TableName}.ep-codigo = i-empresa AND

{&TableName}.cod-estabel = c-cod-estab NO-ERROR.

findPrevEmpresaEstab:

FIND PREV {&TableName} NO-LOCK

WHERE {&TableName}.ep-codigo = i-empresa AND

{&TableName}.cod-estabel = c-cod-estab NO-ERROR.

Page 81: Manual de Técnicas · 2015-10-21 · dados para uma tabela do banco de dados. Introdução Definição . 6 WEB GUI CHUI Java BO Database Interface Lógica Dados As características

CAPÍTULO 7 Técnicas 79

O motivo para a criação de tantos métodos de navegação é que, caso tenha

sido utilizada a abertura de query Main, devesse fazer a navegação através

de FINDs seguindo as restrições de aberturas dessa query. Da mesma

forma para a outra opção de abertura de query, chamada EmpresaEstab.

Então, sempre que o usuário utilizar um dos métodos de navegação, a

execução será encaminhada para o método findXXXQueryName

correspondente.