terça-feira, 3 de junho de 2014

Try...Catch...

Apagar registros por atualização direta em Genexus é uma aventura. Isso porque esse mecanismo não realiza o tratamento de integridade referencial, e se o registro é utilizado por outro, ocorre um erro/interrupção do programa, que sempre assusta bastante quem o recebe. 

Sempre nesses casos é preferivel utilizar Business Component, mas a atualização direta ainda guarda seus encantos principalmente quando se trata de um melhor desempenho.

Uma forma de evitar que o erro apareça nessa situação é envolve-la em um mecanismo de tentativa de execução, inexistente no Genexus, mas possível pela inclusão do código nativ
o. Alias esta prática é bem interessante e util em muitas ocasiões.

csharp try {
 for each
 where ClienteId = &clienteId
    delete
 endfor


csharp } catch (Exception e) { 
    msg('Nao foi possivel completar a operacao')
csharp }

Nao seria muito bom se houvesse já esse simples recurso de programação disponibilizado no Genexus? Eu acho que sim.

domingo, 1 de junho de 2014

Senhas seguras?

Por mais que se tente proteger informações sempre teremos curiosos com tempo e energia suficientes para espionar, invadir, quebrar o sigilo e pior, encontrar coisas importantes.  Segurança é assunto sério e proteger credenciais de acesso de pessoas, além de outras informações relevantes, deve ser uma meta a ser alcançada, visto que esta é uma das principais vulnerabilidades que estamos sujeitos na web (segundo a OWASP).

Uma estratégia é que pelo menos que os invasores tenham muito trabalho para encontrar as coisas, ou mesmo, que as informações sejam transmitidas encriptadas para confundir e atrasar.

Uma estrategia bastante interessante que ilustra bem essa história de confundir, é quebrar as senhas em pedaços, armazenando-a em locais distintos.  Uma idéia simples, e acredito, bastante eficiente.

Abaixo dois links que tratam desse assunto.


Portanto, chega de quebra-galhos, vamos melhorar a segurança dos nossos sistemas.


terça-feira, 27 de maio de 2014

Dois Recursos Interessantes

De vez em quando vivemos momentos explosivos, normalmente aleatórios no tempo, em situações que muitas vezes não sabemos exatamente a causa, e que quando ocorrem a única solução é correr! Muitas vezes nem isso podemos fazer, principalmente porque a solução está em enfrentar o fogo.

Essas situações podem surgir por meio de mensagens indecifráveis que nunca foram vistas por amigos que gentilmente postam soluções, ou pistas, que trazem um pouco de conforto nessas horas. De vez em quando trago algumas dessas situações aqui, no intuito de ajudar pessoas que talvez estejam enfrentando o mesmo leão, ou algum gatinho similar.

Duas situações recentes relacionadas com WebServices fizeram o fogo consumir bastante a minha paciência:

O Dia em que a Terra Parou ou
The remote server returned an error: (404) Not Found . (-10001) 

A primeira foi mais complexa, os webservices simplesmente deixaram de responder.

Não me pergunte o porque ou como ocorreu, simplesmente os webservices que anteriormente se comunicavam naturalmente, deixaram completamente de responder.  O mais interessante é que ao ser chamado o tal programa respondia de forma clara com o WSDL, indicando que o sujeito estava ali esperando alguém. O programa cliente, no entanto, ao se conectar com o bixo enroscava. E uma mensagem de Not Found aparecia.

Essa situação levou semanas para ser corrigida, muita gente foi envolvida para tentar entender a razão. E aproveito para agradecer ao pessoal da Artech (Pablo e Alex) que ajudaram bastante.

E nas tentativas, nessa altura do campeonato movidas pelo desespero, de mexe aqui, acerta ali, a solução surgiu do nada, e veio meio estranha, e também sem explicação plausível, pelo menos para mim, que era a de renomear o webservice.  Incrível, mas ao renomear o tal programa voltou novamente a funcionar.

Não interprete isso como um firewall ou antivírus, que havia bloqueado o tal programa, porque até isso desligamos para tentar resolver a questão, e não resolveu.  Enfim, não sei até agora o porque disso, mas o sistema voltou a funcionar.

Intestino Preso ou
The operation has timed out(-10001)

A segunda apesar de ter sido resolvida de forma mais rápida, foi mais estranha ainda, principalmente porque tinha uma forte relação com os mesmos webservices que deixaram de responder no primeiro caso.  Dai claro, que a principal suspeita foi sobre os tais webservices, e perdemos novamente um tempinho com a mesma abordagem dessa vez com um pouco mais de experiência, renomeia aqui, mexe ali, reprograma.  Enfim, nada de novo, e ainda não funcionando.

O maior problema é que os programas estavam funcionando, porque pararam novamente?  Sempre quando o sistema vai perdendo, ou perde desempenho ao longo do tempo, uma das causas possíveis pode ser o crescimento do banco de dados, pois um índice errado pode causar lentidão entre outras coisas.

Quase por acaso, claro que após algumas horas, ou dias, tentando entender a coisa, finalmente, um select em uma das tabelas manipuladas pelo tal programa revelou uma surpresa. A mesma estava bloqueada:

select * from sis_apptoken

Msg 1205, Level 13, State 52, Line 1
Transaction (Process ID 142) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.


Enfim, uma luz, agora estava claro, o erro não era no webservice e sim no banco, que por alguma razão estava ficando 'preso'. Isso explicava porque no inicio não estava aparecendo problema, porque poucos dias após a tal tabela ter sido programada, agora tinha 20 mil registros.

Um estudo sobre os processos bloqueados mostrou que o Genexus estava incluindo uma operação de UPDLOCK em um select, não sei o porque ainda, creio que temos um bom tema para um próximo artigo.

(@AV11SIS_AppId char(20))SELECT [SIS_AppId], [SIS_AppTokenValid], [SIS_AppToken] FROM [SIS_AppToken] WITH (UPDLOCK) WHERE [SIS_AppId] = @AV11SIS_AppId ORDER BY [SIS_AppId]


E os Dois Recursos Interessantes

Enfim, nem tudo foi perdido, aprendemos alguma coisa, principalmente dois recursos que podem ajudar bastante no desenvolvimento de webservices, e também para entender um pouco situações iguais a esta.

TCPTRACE:
Este programa permite interceptar a comunicação na chamada de um webservice, permitindo visualizar o que está sendo transmitido para o programa e o que está sendo devolvido. Permite que se aprenda com grande facilidade como uma chamada GET ou POST é formada.  Muito útil, principalmente quando se constrói um cliente para um webservice que tenha sido programada em alguma tecnologia não Genexus.

Basta executar o programa e definir uma porta e host de entrada (o qual o cliente deve enviar a solicitação) e a porta e host alvo (onde está de fato o webservice), formando um bypass (desvio). Para que funcione você deve programar uma porta falsa na chamada, ou seja, digamos que o webservice está em localhost na porta 80, seu programa cliente deverá ser programado para apontar para uma outra porta falsa, digamos 8085.  O TCPTRACE, vai interceptar a chamada nesta porta 8085 e redirecionar para a porta real 80.  Um pequeno trabalho, mas uma grande recompensa.

Você pode tentar usar o Wireshark para fazer isso também, é até mais fácil, mas exige um pouco mais de experiência.

Aqui um pouco mais de informação sobre esse recurso:
  • http://www.pocketsoap.com/tcptrace/
  • http://library.gxtechnical.com/gxdlsp/pub/home.htm?/genexus/internet/technicalpapers/debugcallsoap.htm

LOG
Esse aqui é muito interessante e está oculto nas propriedades do Genexus.  Trata-se de uma opção de gravação de LOG disponibilizada pelo próprio Genexus e que possibilita, entre outras coisas, avaliar as ações dos nossos programas em funcionamento.

Para ligar essa opção vá no Enviroment e observe o valor da propriedade Log Level: o valor 6.All faz com que todas as ações sejam gravadas em um arquivo texto, que deve ser criado na raiz da aplicação com o nome client.log
Não se esqueça de desligar isso ao mandar para o sistema para a produção.


Créditos Foto: http://theonlinephotographer.typepad.com/the_online_photographer/2013/07/dont-try-this-at-your-volcano.html

quinta-feira, 10 de abril de 2014

Eletrônica com Genexus

Genexus incorpora recursos para manipular dispositivos eletrônicos externos? A resposta é não. Mais não fique frustrado, é possível. E foi justamente esse tema que apresentamos no Evento GeneXus Brasil de 2014, e o que me deixou bastante feliz foi o fato de muita gente se interessar por esse assunto. Eu particularmente acreditava que tivéssemos algumas poucas almas perdidas nesta palestra, ou mesmo um punhado de 'nerds' malucos por eletrônica, mas de fato a presença dos participantes surpreendeu, e também me motivou a escrever esse artigo.

Esse tema é bastante especializado então, me desculpem àqueles que não possuem muita intimidade com assuntos eletrônicos, confesso que eu mesmo não entendo muito dos detalhes envolvidos, tanto que tive que recorrer aos universitários (meu filho André), mas como como houve grande comoção e demanda dos presentes na apresentação sobre maiores informações, então afivele seu cinto se segurança e vamos lá.

Incorporando 'Coisas'

A grande questão envolvida aqui é como podemos nos comunicar com dispositivos eletrônicos que se conectam a portas seriais do computador? Genexamente falando não é possível, pois a ferramenta não oferece 'ainda' suporte direto ao hardware. Digo ainda porque em seguida a nossa apresentação tivemos a palestra do Nicolas Jodal que falou muito sobre o tema de sensores e a possível evolução do Genexus Evolution '4' neste sentido, mas ainda nada concreto.

Desta forma precisamos recorrer ao conceito fundamental da ferramenta para entendermos como isso é possível.  Assim sendo, precisamos primeiro compreender que Genexus é um ambiente de desenvolvimento que possui uma linguagem de programação própria, mas o produto gerado pelo Genexus é de fato um programa escrito em uma linguagem nativa (C#, Java, Ruby), desta forma podemos incorporar recursos escritos nas linguagens nativas para 'complementar' aquilo que foi produzido automaticamente, assim como está esquematizado na Figura 1 abaixo.

Figura 1

Desta forma na geração do nosso sistema podemos incluir um código próprio que complemente com recursos aquilo que está 'faltando'.

Mas atenção, gostaria de ressaltar que esta prática deve ser utilizada com cautela, Genexus na maioria dos casos gera um sistema excelente, e isso fere um pouco a filosofia Genexus, uma vez que devemos sempre nos distanciar da tecnologia e trabalhar num modelo de maior nível, justamente por causa dos benefícios proporcionados pelo aspecto multi-plataforma, mas também entendo que sob certas circunstâncias muito especificas, podemos recorrer a esta modalidade, para atender àqueles casos ditos especiais, como por exemplo abrir uma catraca eletrônica após a identificação de uma pessoa, ou obter o peso de uma balança, enfim, temos muitas situações em que essa prática é necessária.

Como Incorporar Objetos Externos?

Para realizar esta proeza é necessário que você produza uma classe (.Net ou Java) compatível com a versão do compilador utilizado para compilar o código produzido pelo Genexus. Atenção, isso não é feito no Genexus, mas em uma ferramenta externa qualquer.

Esta classe deve ser programada para realizar as ações desejadas, como no nosso caso que foi o de ler e escrever coisas na porta serial do computador.

Em seguida, de posse desta DLL ou Class Java, o processo de incorporação é simples bastando importar este objeto para o projeto Genexus, seguindo os seguintes passos:


Figura 2
  1. Copie a DLL ou Class Java na pasta BIN da sua aplicação. Esta pasta pode ser acessada por meio da operação Tools -> Explore Target Environment Directory (no Genexus)
  2. Em seguida execute a operação Tools -> Application Integration -> .Net Assembly Import (ou Java Class Import), conforme apresentado na Figura 2, ao lado.
  3. Informe o local e o nome da DLL na caixa de texto, sendo que o local é o diretório completo até a pasta BIN de sua aplicação.
  4. Figura 3
  5. Clique em avançar, até o passo 3, no qual você deve escolher nesta classe quais os métodos públicos (da classe) que serão importados para o Genexus. Em nossa DLL incluímos os métodos abaixo, conforme podemos observar na Figura 3 ao lado: openPort,closePort,portStatus,GetResponse,SendRequest
  6. Pressione o botão Import para finalizar o processo.
Esta ação criará um External Object na sua kb, que você poderá entender como sendo uma API (Application Programming Interface) para o seu 'hardware'.

Para os interessados em testar este exemplo, disponibilizei a DLL Comunicação Serial que pode ser baixada a partir deste link.  Incluímos inclusive o código C# que a gerou. 

Como Acessar a Porta Serial?

A porta USB em seu computador é na verdade uma porta serial, e pode ser utilizada para conectar dispositivos externos, que agora passam a ser controlados pela DLL através do Genexus. Desta forma podemos incluir microcontroladores (como o Arduino, por exemplo) e sensores.

Figura 4
Um detalhe importante neste processo é a Porta, que é um termo que passará ao seu vocabulário a partir de agora, e que representa o local onde estaremos escrevendo e recebendo informações. Para o computador a porta é montada (definida) na medida que você conecta o dispositivo externo. Por exemplo, ao conectar nosso hardware (Arduíno) com um cabo serial ao computador, a porta montada foi a COM9. Isso foi possível de ver por meio do painel Device Manager do Windows, conforme pode ser visto na Figura 5 abaixo.

Figura 5
Este detalhe pode influenciar o funcionamento da DLL que você poderá baixar para o teste, visto que está programada para que funcione nesta porta COM9. Se em seu computador a porta for diferente desta você deverá alterar o código e compilá-lo novamente com o Visual Studio, alterando o texto da string para a sua porta.

static SerialPort _serialPort = new SerialPort("COM9", 9600, Parity.None, 8, StopBits.One); 

Prometo que estarei trabalhando em uma versão mais inteligente neste código.

Referente ao Arduino, temos aqui um dilema, uma vez que você poderá utilizar outro tipo de dispositivo, e neste caso a situação ficaria específica para cada caso. Mas para que apenas complementemos o exemplo vou incluir aqui um pequeno programa de teste, que deve ser enviado para o microcontrolador.

void setup()
{
   Serial.begin(9600);
}

void loop()
{
  switch(Serial.read())
  {
   case 'X': Serial.println("Ola mamae!");
             break;
   case 'Y': Serial.println("Ola papai!");
             break;
  }
}

Observe que este código se assemelha bastante à linguagem C, portanto é bastante fácil programar este microcontrolador.  No exemplo o que temos é o seguinte, se na porta serial tiver o 'comando' X o controlador responde com a mensagem Ola Mamãe! e se Y a mensagem Ola Papai!

Como Programar no Genexus?

Muito bem, ao chegar neste ponto acredito que você esteja com muita curiosidade para saber aonde vai parar esta história. Confesso que eu também estava muito ansioso para ver o final da operação, e acabei me frustrando porque tudo pareceu tão simples de ser programado, a não ser pelo fato da porta 'travar' com grande frequência. Ou seja, se por alguma razão ocorrer algum travamento do código, a porta ficará também alocada para o processo, gerando a necessidade de, pasmem, reiniciar a máquina. Tive que fazer isso várias vezes até pegar o jeito da coisa.

Para evitar qualquer confusão utilizei o seguinte algoritmo para realizar a operação:

  1. Verificar o status da porta, por meio do método portStatus(), da API.
  2. Se estiver fechada abrir a porta, openPort()
  3. Realizar a operação de envio do comando, SendRequest()
  4. Realizar a leitura da porta para obter o resultado da operação, GetResponse()
  5. Fechar a porta com closePort().
Para testar crie um WebPanel e programe dois botoes, conforme o modelo a seguir.

Figura 6
Ao se pressionar os botões os eventos são executados, cada qual definindo o comando a ser enviado para a porta e uma operação de execução definida no código a seguir.


Event 'Mamae'
&comando = comando.Mamae
do 'Executar'
Endevent

Event 'Papai'
&comando = comando.Papai
do 'Executar'
Endevent

Sub 'Executar'
&continua = false
if not &Serial.portStatus()
&Serial.openPort()
&continua=true
endif

if &continua and not &Comando.IsEmpty()
&Serial.SendRequest(&Comando)
&Resposta = &Serial.GetResponse()
msg(&resposta)
endif

// fecha se abriu
if &Serial.portStatus()
&Serial.closePort()
endif
EndSub

As variáveis foram definidas como indicadas na Figura 7 abaixo.
Figura 7
Sendo que a variável comando foi definida como sendo domínio enumerado com os seguintes valores.
Figura 8

O resultado não poderia ser diferente, ou seja, apresentar o texto enviado pelo controlador conforme o pressionamento dos botões.

Figura 9

Observe que a DLL que importamos é facilmente acessada via Genexus por meio da programação de comandos simples, conforme foram definidos na Classe C#.

&Serial.portStatus()
&Serial.SendRequest(&Comando)

Ou seja, nada diferenciando da programação tradicional da ferramenta.

Conclusões

Por meio deste exemplo, não vou dizer simples, porque esta palavra é meio perigosa ao se conectar mundos tão distintos, é possível verificar que Genexus oferece suporte, de forma elegante por meio dos External Objects, para realizar coisas que vão além da sua capacidade projetada.

Utilizando os recursos de geração de sistemas Web e Smartdevices é possível conciliar esses mundos gerando aplicações muito interessantes.  Portanto, seja bem vindo a esta nova classe de aplicações.

Para finalizar nada mais resta senão agradecer ao meu filho André pelo fato de um dia ter escolhido estudar Engenharia Elétrica (ou Eletricista), pois vou dizer uma coisa, conectar sensores, leds, fiozinhos, plaquinhas, e demais coisas não é tão simples assim. Tem um tal de 'espúrio' que é um bicho difícil de domar. Só um especialista em assuntos 'nerdianos' é capaz de matar a coisa com tanta eficiência. Portanto, valeu, o papai te ama.




PS. Já estava esquecendo, preciso agradecer também ao Rodolfo Robalo e Alejandra Caggiano da Artech, que foram a fonte de inspiração para estudarmos este tema, em sua palestra Las Cronicas de SmartDevices: ..., do Genexus International Meeting de 2011/Uruguay.









Se voce se interessou pela palestra o link é este aqui.
/www.youtube.com/embed/16pEkN6yeo0