software‎ > ‎módulos‎ > ‎web framework‎ > ‎

perguntas frequentes


Como obter uma hierarquia de classes em um script automático de upgrade?

postado em 30 de jul de 2012 11:54 por Usuário desconhecido   [ 30 de jul de 2012 11:58 atualizado‎(s)‎ ]

    No escopo de um script de upgrade, o acesso às variáveis globais "connection" e "database" não são permitidos pois podem causar confusão sobre qual base de fato está sendo acessada. Por isso temos as propriedades "target" e "source" dentro de "UpgradeScript" que nos permitem fazer esses acessos, referenciando a conexão alvo e a conexão origem respectivamente.
    Devemos ter em mente que "upgrades" podem envolver 2 ou 3 bases. Ora uma base atualiza outra diretamente a partir de si mesma, ora uma base atualiza outra usando uma terceira como origem. E também que remotamente não é permitida a utilização dos métodos e propriedades associadas ao cache. Nesse cenário fica claro que não existe uma certeza de onde o script de "upgrade" será executado, e que não podemos pegar a hierarquia de classes utilizando o método (depreciado) "getChildren" por que este utiliza cache local.
    O Framework disponibiliza através do método uwl.classes.getRemoteChildren que utiliza internamente não o cache, mas o banco de dados para fornecer a informação.
    Mais informações, favor entrar em contato com o time Engine.

    

Como ocultar botões?

postado em 21 de dez de 2011 10:45 por Usuário desconhecido

Começo dizendo que, de uma forma geral, não é saudável alterar comportamentos e mesmo layout das telas de produtos UNUM. É importante ressaltar que, em casos de defeitos causados por estas alterações e apesar de ser uma tela de um produto UNUM, o cliente responderá como se fosse custom, pois de fato houve uma customização. Em outras palavras, é importante ficar claro que o cliente terá o ônus do ajuste sobre problemas desta natureza. 

Existe ainda dois detalhes importantes. O botão Mostrar Chaves está passando para a infra-estrutura das grades, ou seja, deixará de ser um botão clássico e, portanto, não poderemos desligá-lo conforme a explicação abaixo. 

Bem, feita a parte política, vamos à técnica! :) 

Posso iniciar dizendo que temos botões em dois contextos, um no Processo (1) e outro na Grade (2). 

1 - Caso o botão seja definido no processo, sua visibilidade só poderá ser desligada no próprio script do processo, ou seja, você não poderá fazê-lo caso o processo seja de um produto UNUM). O que você pode fazer é criar um segundo processo como cópia do anterior e redefinir os botões como quiser. Novamente, essa não é uma boa idéia, pois a manutenção e evolução de seu novo processo não estaria sendo feita pelaUNUM. A probabilidade de se ter uma quebra de compatibilidade é muito alta. O ideal é contactar a UNUM e solicitar uma melhoria onde seria criado um ponto de customização para esta necessidade. 

2 - Caso o botão seja de uma Grade e ela tenha sido definida em um x-class, o trabalho fica mais fácil. Vamos tomar um exemplo de uma grade de nome "titulos". Na criação dessa grade, o desenvolvedor informa qual o classKey da grade. Isso é feito através do terceiro parâmetro do método grid. Veja um exemplo: 

this.grid("titulos", ds, classKey);

O classKey informado corresponde à chave da classe onde ficam os arquivos x-class de onde, um deles, definirá a grade "titulos". Posicionando o cursor sobre o classKey, um CTRL+ENTER fará com que uma nova guia IDE seja aberta na classe de definição desta grade. Basta vasculhar os arquivos x-class desta classe e procurar qual x-class implementa a definição da grade. O x-class em questão deve conter algo parecido com isso: 

this.defineGrid( "titulos", function (){ ...

Para redefinir a visibilidade de um botão desta grade, basta então criar um novo x-class que fique ordenado abaixo do x-class onde se encontra a última definição da grade "titulos". Por isso, temos arquivos x-class custom com o nome iniciando com 9900. Essa nomeclatura geralmente garante que este novo arquivo custom ficará ordenado abaixo dos arquivos x-class dos produtos UNUM. Feito isso, basta que, no x-class custom, tenhamos algo do tipo: 

this.defineGrid( "titulos", function (){ inherited(this); this.button("Duplicar").visible = false; ...

Geralmente isso é o suficiente para alterar a visibilidade de um botão. É importantíssimo que a linha "inherited(this);" seja definida, caso contrário não herdaremos o comportamento definido pelo x-class anterior. 

Como localizar os arquivos x-class que definem um cadastro?

postado em 20 de dez de 2011 07:02 por Usuário desconhecido   [ 20 de dez de 2011 07:03 atualizado‎(s)‎ ]

Os cadastros sempre estão relacionados a uma determinada classe de dados. Assim, o primeiro passo é descobrir qual classe está relacionada com o cadastro analisado. Tomando como exemplo o cadastro da classe Fornecedores, basta navegarmos até a classe Fornecedores e teremos a lista "local" dos arquivos x-class que, juntos, irão compor as definições finais deste cadastro.

É importante saber que não são apenas os arquivos x-class de uma única classe que participam da definição do cadastro. A estes arquivos, precisamos somar todos os demais que estão nas classes ascendentes. Isto é necessário devido ao nosso conceito de herança.

Dessa forma, a lista de campos (Fields) de um cadastro pode ser obtida a partir da classe Raiz até a classe em questão, ou seja, Fornecedores. Nesta mesma ordem, ou seja, da classe Raiz até a classe Fornecedores, os arquivos x-class devem ser considerados de cima para baixo em cada classe. Pronto, você tem em mãos, de forma ordenada, o conjunto de arquivos que definem um cadastro. Observe a imagem anexa:



Uma tarefa não tão trivial é, a partir do nome de uma classe, saber como navegar no IDE até esta classe. Esta dificuldade existe porque temos apenas o nome da classe e, em nosso modelo, podemos ter duas ou mais classes com o mesmo nome, desde que não sejam classes irmãs.

Assim, imaginando que possa existir mais de uma classe com o nome "Fornecedores", como fazer para acessar tais classes no IDE? Primeiramente devemos fazermos uma query do tipo:

Select CHAVE from CLASSE where Upper(NOME) = 'FORNECEDORES'

Assim, acabamos de obter a lista das chaves das classes cujo nome é Fornecedores. Copiando cada chave dessas no iDBC SQL, podemos posicionar o curso sobre elas e teclar CTRL+ENTER. Isso fará com que outra guia IDE seja aberta já na classe em questão. Por fim, devemos observar que, caso você não tenha permissão de visão da classe que sofreu o CTRL+ENTER, a nova guia aberta ficará posicionada na classe Raiz.

Estamos com uma melhoria prevista que irá diminuir este trabalho laboroso de saber qual o caminho completo (path) da classe Raiz até a classe do cadastro em questão. Este caminho completo estará disponível no help do próprio processo (interface web).

Como forçar o uso do HTTPS no Web Framework?

postado em 14 de out de 2011 11:37 por Usuário desconhecido   [ atualizado em 2 de ago de 2017 13:49 por Paula Renata Murta Ribeiro ]

Para forçar o uso do HTTPS, você deverá criar um x-class Custom na classe /Configuração/Web Framework/Seguranca, com o seguinte conteúdo: 

this.httpsCapable = true; 
this.serverAddress.push("10.0.0.1"); 

Substitua o "10.0.0.1" pelo endereço IP do seu servidor que possui instalado o certificado SSL. 

Importante: este modo somente pode ser habilitado em servidores com certificados SSL configurados na porta padrão 443 do HTTPS.

Como adicionar uma Política de Segurança e definir Usuários para utilizá-la

postado em 8 de jul de 2011 07:13 por Usuário desconhecido   [ 8 de jul de 2011 07:32 atualizado‎(s)‎ ]

Passo à passo:
  1. Clique em Ir Para > Admin > Segurança > Políticas de segurança > Políticas de usuários.ip
  2. Clique no botão + (Inserir) e muda a visão da grade para o Modo Formulário
  3. Preencha o campo Prioridade colocando uma que se adeque-se à sua necessidade, sendo a mais mais alta a prioritária.
  4. No campo Nome digite um a sua escolha que defina esta política.
  5. Em Aplicações selecione o que os usuários desta política terão acesso, 
    1. O item Acesso Remoto permite a atualização da Base de Dados remotamente.  
  6. Salve e a Política de Usuário está criada.

Após a criação da Política de Segurança o administrador pode adicionar usuários na política desejada de duas formas.

  1. Em  Ir Para > Admin > Segurança > Políticas de segurança > Políticas de usuários.ip
    1. Selecione a permissão desejada e mude para o Modo Formulário
    2. Na grade Grupos ou usuários adicione quem fará parte desta Política (pode ser usuários ou grupos de usuários).
  2. Em  Ir Para > Admin > Segurança > Grupos e usuários > Usuários.ip
    1. Selecione o usuário desejado e mude para o Modo Formulário
    2. No campo Políticas de Seguraça, selecione a política desejada para este usuário.

como contornar o limite de tempo que os browsers impõem para retorno?

postado em 26 de mai de 2011 11:16 por José Luís Prado   [ atualizado em 30 de mai de 2011 14:44 por Usuário desconhecido ]

Alguns navegadores de Internet (web browser) impõem limite de tempo (timeout) para receber a resposta de um processamento realizado no servidor (web server).

Este limite varia de acordo com sistema operacional e o navegador utilizado, mas também pode ser influenciado pela existência de proxies (softwares que realizam caches de conteúdo de internet) explicitamente configurados ou implementados de forma transparente, sem que o usuário saiba da sua existência. Um proxy transparente pode ser um vírus/malware que intercepta todo o tráfego do protocolo http, tentando obter informações privilegiadas num ataque conhecido como "man in the middle". Este tipo de ataque é mais comum do que se imagina.

O limite de tempo também pode ser influenciado por firewalls (softwares que filtram os acessos dos usuários, bloqueando destinos ou conteúdos que não façam parte de uma política pré-definida), que matam conexões após um determinado período de tempo de inatividade. Um software de checagem contra vírus pode estar atuando como firewall de forma transparente, muitas vezes de forma despercebida pelo usuário.

Proxies e firewalls na maioria das vezes limitam o tempo das conexões em 5, 15 e 60 minutos, tempo muitas vezes insuficiente para processamentos mais pesados ocorrendo no servidor Engine. A imposição deste limite de tempo pode provocar erros no uso do Sistema UNUM, como:

Não foi possível conectar-se ao servidor "http://<<enderecoServidor>>". Status: 500.
Aguarde a estabilização da conexão ou entre em contato com o administrador do sistema.

Ou:
Erro detectado:
Mensagem de erro: XML Document is invalid.
Solução: Contact the system administrator.


Para minimizar o problema, certifique-se de que não existem:
  • proxies explicitamente configurados no navegador de Internet que interceptem o tráfego entre o navegador e o servidor utilizado;
  • proxies implícitos (sejam estes bem intencionados ou não) ou firewalls entre o navegador de Internet e o servidor Engine;
  • softwares antí-vírus que estejam funcionando como firewalls transparentes.

Depois destas verificações iniciais, teste vários navegadores de Internet, avaliando qual deles possui maior limite de tempo de resposta. Em testes realizados pela UNUM, observamos que o Google Chrome 11, no Windows XP, consegue manter conexões ativas por mais de 5 horas sem interrupção. Já o Internet Explorer 7, no Windows XP, não consegue manter a conexão por mais de 1 hora.

Mesmo após perdida, uma conexão pode ser acompanhada pelo administrador do sistema UNUM. Para isso, basta acessar o manage através do endereço "http://<<enderecoServidor>>/manage" (será solicitado nome de usuário e senha de acesso) e clicar na opção requests. O agrupamento "HTTP Connections" irá mostrar todas as conexões HTTP ativas no servidor UNUM, permitindo ao administrador avaliar o tempo de execução e usuários com conexões abertas. A página permite ainda abortar a conexão através do botão [Abort].

Como é definida a visibilidade dos campos?

postado em 18 de fev de 2011 18:30 por Usuário desconhecido

A visiblidade de um campo é determinada pelos seguintes passos:
  1. Por padrão, os campos são visíveis;
  2. Se a grade for associada à uma classe de dados, será avaliada a permissão "Campos Visíveis" do usuário. Se o resultado for uma lista vazia, o campo será visível. Caso contrário, ele será visível apenas se estiver contido na lista de campos. A verificação da permissão é realizada inclusive para campos que não existem na classe de dados, como campos calculados e grades detalhes.
  3. O evento defineGrid é executado, permitindo o desenvolvedor ocultar o campo. 
  4. O evento onDefineFields é executado, permitindo o desenvolvedor ocultar o campo. 
Por padrão, o desenvolvedor não pode tornar um campo visível que foi definido como oculto no processo de Permissões. Para isto, ele deverá desativar toda a avaliação de permissões realizada no passo 2 configurando a propriedade validateFieldPermissions da grade com false. Com isto, o desenvolvedor será responsável por validar as permissões manualmente, podendo desconsiderar as regras que desejar.

Qual a ordem de execução dos eventos defineGrid em uma hierarquia de classes?

postado em 18 de fev de 2011 14:17 por Usuário desconhecido   [ 18 de fev de 2011 14:35 atualizado‎(s)‎ ]

Imaginando que temos a seguinte hierarquia de classes:
  • Avó
    • Mãe  
      • Filha
E todas estas classes definem o mesmo evento:

var classKey = this.key;
this.defineGrid("test", function () {
    log.write("Antes do inherited. Classe: " + classKey.nome);
    inherited();
    log.write("Depois do inherited. Classe: " + classKey.nome);
});

Se criarmos uma grade "test" da classe "Filha", iremos observar o seguinte log:

Antes do inherited. Classe: Filha.
Antes do inherited. Classe: Mãe.
Antes do inherited. Classe: Avó.
Depois do inherited. Classe: Avó.
Depois do inherited. Classe: Mãe.
Depois do inherited. Classe: Filha.

Ou seja, a ordem de execução é da classe informada para a grade e em seguida é executada o defineGrid existente nas classes superiores. No entanto, como cada evento costuma invocar o inherited, a ordem de execução dos códigos após o inherited é justamente o contrário. Este é o comportamento desejado, visto que a definição da classe Filha deve ser sobrepor às definições mais genéricas das classes mãe.

Uma observação importante: o defineGrid pode definir o evento onDefineFields para a grade e este evento é executado após todos os defineGrid serem executados. A ordem de execução do onDefineFields é igual a explicada para o defineGrid, no entanto devemos ter atenção que uma propriedade definida no defineGrid de Filha poderá ser sobrescrita pelo evento onDefineFields definido por Mãe. Exemplo:

Se em Filha, tivermos o x-class abaixo:

this.defineGrid("test", function () {
    inherited();
    this.formViewFieldNames = "CampoA";
});

E em Mãe, tivermos o x-class abaixo:

this.defineGrid("test", function () {
    inherited();
    this.onDefineFields(function (grid) {
        grid.formViewFieldNames = "CampoB";
    });
});

Teremos como resultado final o valor "CampoB" em formViewFieldNames, visto que após a execução de todos os defineGrid o valor será "CampoA", mas em seguida são executados os eventos onDefineFields que altera o valor para "CampoB";

É possível exportar os dados de um relatório que não faz uso do SimpleLayout?

postado em 14 de fev de 2011 14:00 por Usuário desconhecido

Sim, desde que o relatório configure o evento onGetDataToExport para indicar quais dados devem ser exportados. Veja aqui um exemplo de como configurar este evento.

Como documentar um Evento (class Event)?

postado em 16 de nov de 2010 06:01 por Usuário desconhecido   [ 29 de nov de 2010 03:43 atualizado‎(s)‎ ]

Um Evento deve ser documentado semelhante à forma como se documentam getter's e setter's. O exemplo abaixo mostra a documentação sugerida. As diferenças estão destacadas em vermelho logo abaixo:

/**
* Event Description.
* @type Event
* @param1 {Type} paramName Description
* @param2 {Type} paramName Description
*/
/*jsdoc FunctionName.prototype.onEventName = function() {} jsdoc*/
/** @private */
FunctionName.prototype._onEventName = null;
/** @private */
FunctionName.prototype.getOnEventName = function (){};
/** @private */
FunctionName.prototype.setOnEventName = function (){};

A documentação acima irá gerar o seguinte resultado (JSDoc):

{Event} onEventName(param1, param2)
Event Description.
Parameters:
param1
Description 1
param2
     Description 2

Disponibilizamos o CodeTemplate (acessível na IDE através do Ctrl+J) de nome: docEvent (Event Documentation) para auxiliar nessa documentação.

1-10 of 14