Sobre relatos de bugs por clientes

bugs Agradeço a meus clientes quando eles me relatam um bug ou uma falha em algum recurso do sistema. Não porque eu fico feliz com o bug existente e que não fui capaz de prever, mas porque sabendo da sua existência, posso corrigi-lo e outros usuários poderão usar meu software sem esse bug.

É sabido que muitos usuários não informam erros ao desenvolvedor, os motivos são diversos, seja por falta de iniciativa, por preguiça, ou porque a falha não afeta profundamente o trabalho dele, ou porque ele encontra uma outra forma (outra opção) de fazer o que ele pretendia, ou simplesmente condena logo o software de primeira porque há outra opção no concorrente que não tem esse bug.

O fato é que bugs ficam escondidos as vezes por anos e anos sem serem descobertos, por você é claro, os usuários já sabem desses erros eles apenas não relatam ou convivem com eles. É como aquela história : o suporte é igual a marido traído, é o último a saber.

E essa deve ser umas das grandes preocupações de quem desenvolve para muitos usuários e pretende que seu cliente seja fiel e não troque pelo do concorrente.

Como diminuir a existência de bugs não relatados :

Abrir canais de comunicação de todo tipo para que o usuário possa se comunicar com o suporte, entre eles :

– Telefones
– Tela de suporte no próprio sistema
– Chat no site (atendimento on-line)
– Formulário de envio de problemas no site
– Whatsapp
– Página no Facebook
– Fórum no site
– Usar ferramenta de acesso remoto

Aliado a isso ter :
– Paciência na escuta do problema relatado
– Saber ouvir o cliente (dar uma de psicólogo as vezes)
– Não subestimar um erro, erros pequenos podem causar grandes problemas
– Não deixar clientes sem resposta, isso ajuda na sua reputação

Passar a mensagem para seu cliente que você está sempre disponível, pronto para ouvir e corrigir qualquer problema no software, é uma das chaves para a fidelidade.

Cliente satisfeito não sai por aí procurando seu concorrente. E quando o concorrente bate na porta dele querendo vender ele despacha imediatamente. Porque sabe que em qualquer situação você vai atendê-lo.

Essas são apenas algumas dicas das que lembro no momento para que você tenha um negócio de sucesso e principalmente : duradouro na venda de software.

RaptorWS – Versão 1.20

Nova versão 1.20 – Mudança na estrutura Server

Na versão anterior do Raptor,  não era possível logar o contexto da requisição dentro do ServerMethod e nem exibir nenhum Log no form Principal, uma vez que a implementação de cada Server Method estava desconectada ou não tinha acesso aos dados da requisição por exemplo  : qual IP de onde partiu a requisição entre outros dados, não era possível logar essa informação de dentro do ServerMethod, apenas antes de chamá-lo.

Então uma mudança estrutural na construção da parte Server se fez necessária. Foi criada uma Unit HandleContext contendo a classe TServerContext herdada de  de TIdServerContext, onde nela coloquei o o dispatch de métodos REST conforme o tipo e isolei em classe separada os ServerMethods, dessa forma o Core do WebService fica separado  dos ServerMethods de seu negócio.

Essa mudança estrutural permite também que agora você possa ter várias Units ServerMethods separadas com uma responsabilidade única, por exemplo, numa aplicação de Gerenciamento de Escola, poderíamos ter uma unit com ServerMethods para Alunos, outra unit para Professores, outra para Material didático e assim por diante.

Classe TServerContext na Unit HandleContext :TServerContext.jpg

Para essa classe foi atribuída a tarefa de obter os argumentos da requisição e chamar cada operação Rest.

Uma vantagem dessa classe é que estando num nível intermediário e antes da chamada do servermethod, que possa realizar tarefas comuns a todos os ServerMethods, poupando assim  cada ServerMethod de um trabalho repetitivo que seja comum a todos.

Outra vantagem dessa classe é que ela sendo herdada do Contexto da Requisição (TIdServerContext) teríamos todos os dados como IP de onde partiu a conexão, o User Agent, e todos os dados relativos  ao contexto, podendo ser usado para log.

CORS-HEADERS

Outra melhoria foi a adição de CORS-Headers, colaboração de José Benedito, que faz com que o servidor retorne respostas à requisições AJAX CrossDomain.

CORS_HEADERS1

Logando dados do negócio, no ServerMethod

Na tela principal do Server foi adicionado um Log da Aplicação, onde cada ServerMethod loga a operação efetuada, como dados do IP da requisição, Nome do ServerMethod chamado e parâmetros passados ao ServerMethod. Veja o terceiro Memo é o que corresponde ao log da Aplicação (ou do negócio).  Os 2 primeiros referem-se ao servidor.

RaptorWS

A Linha de código que faz a geração de Log é a  “Context.LogBusiness (… ” que pode ser vista em todos os serverMethods :

LogBusiness.jpg

Migração da versão 1.11 para 1.20

Muitas alterações foram feitas nesta versão 1.20, de modo que aqueles que usavam a versão 1.1 teriam muito trabalho para adequar a esta nova estrutura, aqueles que quiserem usar a versão 1.20 tendo já implementado o seus ServerMethods na versão  1.1, baixem a versão 1.20 e tragam o código de cada ServerMethods da versão 1.1 e encaixem no local adequado da versão 1.20.

Download da versão 1.20

DonwloadServer

DonwloadClient

Estudo de Caso – Realizar tarefas comuns a todos os Server methods

Agora vou Exemplificar como Obter o Código do usuário antes da chamada de cada ServerMethod para que possa ser usado por todos os ServerMethods quando necessário, usando a Classe TServerContext.

Supondo que em todos os nossos ServerMethods padronizássemos que o código do usuário fosse passado sempre no 1o. Parâmetro, então poderíamos colocar no CallGETServerMethod antes da chamada de cada ServerMethod, a obtenção do Usuário, aí crio uma classe TUsuario onde preencho o Código do Usuário e passo esse objeto como parâmetro no ServerMethod, veja como ficaria :

CodigoUnico.jpg

Ou se preferir coloque essa implementação comum antes disso, na TServerContext.HandleRequest que é a que chama CallGETServerMethod

ServerMethods com Responsabilidade única

Supondo que num sistema de Gerenciamento de escolas tenhamos ServerMethods agrupados por responsabilidade, um para Alunos e outros para  Professores, colocar todas as responsabilidades numa única classe fica um poço sem fundo, ferindo o princípio SOLID de responsabilidade única que deve ter uma classe, e sacrificando a manutenção futura. Dessa forma você poderia organizar seus server methods em Units Separadas, cada Unit com uma nome de classe distinta  :

foram criadas 2 Units SMAlunos.pas (SM = ServerMethod) e SMProfessores, cada uma com um ServerMethod de nome Consulta. Para facilitar ainda mais coloquei na chamada do navegador o prefixo do nome do objeto, dessa forma o método SMAlunos.Consulta da classe TSMAlunos deverá ser chamado no navegador assim :

http://localhost:8080/SMAlunos.Consulta/fulano

e na CallGetServerMethod instanciaríamos cada classe e chamaremos seu método específico :

RespUnica

Uses :

Uses

Dessa forma podemos organizar os ServerMethods em Units separadas por responsabilidade.

Não é Show ? Espero que gostem e comentem.

Valeu.

Como debugar o Raptor WS

Boa tarde amigos delphianos,

devido a uma dúvida de um usuário do Raptor WS, informando que não conseguia debugar a parte server, estou aqui colocando algumas opções de como debugar o seu web service, Client e Server ao mesmo tempo.

Um dos objetivos desse projeto era que fosse possível implementar um webService numa versão anterior ao Delphi Seattle, por exemplo do XE2 em diante, então a parte server foi feita em XE2 e a parte client feita no Seattle para exemplificar a utilização dos componentes RESTClient que só vieram na versão XE5.

Mas não que isso seja um impedimento para usar em versões mais antigas até, pois é possível que a parte client seja executada até em Delphi 7 mas para isso seria necessária a substituição desses componentes REST por IdHTTP, ou seja seria necessário reescrever a parte Client, que no caso ainda não tive demanda para isso, creio não ser necessário no momento. Se você analisar bem qualquer combinação é possível fazer :

  • XE2 Server x Seattle Client (versão atual disponibilizada no Blog)
  • Seattle Server x Seattle Client (basta abrir o Server no Seattle)
  • D7 Server x XE2 Client
  • D7 Server x D7 Client

 

Para exemplificar um Debug com as 2 partes (Client e Server) rodando no Seattle vamos fazer conforme abaixo :

Há 2 métodos, o primeiro mais complexo e o segundo mais fácil, se você quiser pular o primeiro, fique a vontade e siga logo para o método 2 mais abaixo (mais fácil)

Método 1 : 2 projetos num mesmo grupo de projetos

1 ) Crie uma Pasta chamada RestWebServiceSeattle e copie todos os arquivos da pasta RestWebServiceXE2 para ela.

2) Abra o Projeto RestWebService da pasta RestWebServiceSeattle e clique com o botão direito do mouse no ítem ProjectGroup e Clique em “Add existing Project”, figura abaixo :

 

AddExistingProject

2) Procure o Projeto RestClient e adicione ele ao grupo de projetos

OpenRestClient

3) O Program Manager ficará assim, com 2 Projetos num grupo de Projetos “ProjectGroup1”:

ProgramManager

4 – Agora salve o Grupo de Projetos em alguma pasta, clicando com o botão direito do mouse sobre ele :

SaveProjectGroup

5 – Nomeando o Grupo de Projetos :

SaveProjectGroup2

6- A partir de agora ao invés de abrir projetos separados, abra sempre o Grupo de Projetos :

SaveProjectGroup3

7- Dê um duplo-Clique no projeto RestWebService e ele ficará em negrito, simbolizando que este é o projeto ativo, para compilar e rodar, coloque o breakpoint em algum lugar e execute :

DuploCliqueServer.jpg

8 – Agora dê um duplo Clique no Projeto RestClient para ativá-lo como projeto atual :

DuploCliqueClient

9 – Coloque um Breakpoint em qualquer lugar e o Execute. Irá aparecer a seguinte tela informando que é necessário um passo adicional para debugar 2 projetos ao mesmo tempo :

Confirm

10 – Vá então no menu Project e selecione Compile all Projects

CompileAllProjects

11 – Após isso Execute o RestClient, dê um duplo-Clique no outro Projeto RestWebService para ativá-lo e o execute também pois após essa compilada ele parou de executar.

Não se preocupe se a linha do  Breakpoint ficar verde como abaixo, execute ele desfaça o breakpoint e o faça novamente,

GreenBreakPoint

As linhas podem ficar verdes a qualquer momento, não sei o motivo disso, mas sei que repetindo todo o processo eu consigo reativá-las e rodar.

Devido a tantos passos e problemas que podem ocorrer nesse método, ensino um outro método mais abaixo, mais fácil e sem complicações :

Método 2 : 2 instâncias do Delphi abertas

 

  1. Execute o Delphi e carregue o Projeto RestWebService, coloque um breakpoint onde quiser e execute-o.
  2. Carregue outra instância do Delphi Seattle, E abra o projeto RestClient.NovaInstancia
  3. Coloque um breakpoint onde quiser e execute o projeto

 

Bem mais fácil essa não acham ?  Ensinei o primeiro método para que saibam que existe a possibilidade de com apenas 1 instância se executar e debugar 2 projetos, no entanto não é muito simples, a segunda opção é mais fácil, optem por qual quiserem.

PS : Quando colocar o BreakPoint e o mesmo não parar no local, devem setar o projeto para debug e dar um Build All :

MOdoDebug

Pois se tiver em Release, ele não faz Debug.

Um abraço.

Obs : Caso você não conheça como funciona o framework, veja o Post inicial dele aqui

Rest WebService – Versão 1.11

Algumas mudanças foram implementadas no framework  descritas abaixo:

  1. Recebe requisições de POST e GET de HTML (webforms)
  2. Emite mensagem de erro se o nome do método não for encontrado
  3. Mensagem de erro apenas se o número de argumentos do método for menor que o esperado, se for maior não emite mensagem, isso foi mudado para suportar GETS e POSTS vindo de um navegador em que a lista de parâmetros podem vir com 1 parãmetro a mais que é o botão submit, se caso o programador tiver setado a propriedade name do botão submit na página HTML.
  4. Criado um botão de teste IDhttp.GET e outro IDHttp.Post no RestClient

A maior mudança foi a possibilidade do framework responder a uma requisição GET e POST de um navegador. Na versão anterior só era possível operações (GET/POST/PUT/DELETE) com passagem de parâmetros via URL REST  (ex : http://nomesite:8080/metodo/parametro1/parametroN..)

Uma vez que navegadores não trabalham assim, somente um client que formatasse a URL dessa forma poderia acessar o webservice e passar os parâmetros corretos.

Na nova versão voce pode ter um client HTML fazendo GET via queryString (exemplo :

http://nomesite:8080/metodo?param1=valor1&param2=valor2)

ou fazendo POST normal do navegador.

Veja os exemplos abaixo de HTML GET e POST

Exemplo de Html GET chamando o webservice :

HTMLGET

Exemplo de Html POST chamando o web-service :

HTMLPOST

Dessa forma o framework é capaz de atender tanto Clients Desktop como o Delphi e páginas na internet feitas em HTML, PHP ou outra qualquer. Essa mudança foi feita porque uma pessoa que estava utilizando o framework tinha um formulário HTML fazendo POST no webService e os parâmetros não estavam chegando.

Eis a alteração.

Os fontes do projeto podem ser encontrados aqui :

RestClient-v1.11

RestWebService.v1.11

Obs : Caso você não conheça como funciona o framework, veja o Post inicial dele aqui

TSplitViewXE2 – Componente do Seattle no XE2 e posteriores

Do XE2 ao Seattle

Com a chegada do Delphi X Seattle, novos componentes VCL foram adicionados dando uma cara mais moderna às aplicações, um desses componentes  é o TSplitView que combinado a outros artefatos visuais da VCL permite exibir uma tela no desktop com características que são vistas apenas nas apps mobile.

Essa é a idéia do Windows X, trazer características visuais de apps mobile para o Desktop e fazer com que as aplicações fiquem com aparência mais homogênea independente do dispositivo em que está rodando, isso não é tarefa fácil, mas com o Delphi Seattle  já é possível chegarmos perto desse objetivo.

Objetivo

Para quem tem o Delphi Seattle, não há problema basta carregar o projeto da pasta Samples\Object Pascal\VCL\SplitView e ver como funciona. Mas e quem tem versões anteriores do Delphi, como faz ?

Use o componente TSplitViewXE2, objeto desse artigo, especialmente desenvolvido  para simular o funcionamento do TSplitView que vem no Seattle.

Feito no XE2 mas roda em todas as versões acima e muitas abaixo, possivelmente até no Delphi 7.

TSplitViewXE2

Não há muito o que comentar, pois os fontes estão disponíveis e a utilização é muito simples.

Baixe aqui os fontes do TSplitViewXE2

Até a próxima solução !

 

TAjaxEdit – O Ajax no Delphi Desktop

Evolução da Ampulheta

As técnicas para informar ao usuário que o “sistema está processando” algo e ele deve aguardar, não evoluíram muito no Windows. Desde o Windows 95 existe a Ampulheta e permanece a mesma até hoje. Mudanças somente ocorreram no Windows 8 e 10 com o ActivityIndicator e somente implementado no Delphi Seattle.

Algo mais interessante e até antigo pode ser visto nas páginas da internet, o que convencionou-se chamar de AJAX que é uma requisição assíncrona ao servidor sem que a página seja recarregada, a isso juntou-se a imagem muito comum da animação que é mostrada quando esse processamento ocorre:

ajax-loader5

Essa imagem em nosso projeto é um gif animado carregado num TImage, e você não precisa usar esta, qualquer imagem animada pode ser usada.

TAjaxEdit – Trazendo o Ajax para o Desktop

A proposta aqui é fazer o mesmo efeito do Ajax das páginas da internet para o Desktop e não só no Seattle, mas em todas as versões do Delphi.

Mas não apenas uma imagem girando, vamos combinar ele com um TEdit e simular uma busca incremental a medida que se digita no Edit e ao mesmo tempo em que se mostra a animação enquanto durar a pesquisa no banco.

Uma busca muito comum feita nas  páginas da internet onde o usuário digita parte de um nome e a página   faz uma requisição ajax em modo assíncrono (sem recarregar a página)  e retorna uma lista de nomes que  contém a palavra digitada, o usuário então escolhe a palavra da lista retornada e o sistema preenche o edit.

Detalhes do Projeto

Baixe os fontes do componente

No grupo de projetos temos o componente e um outro projeto que o testa :

TAjaxEditProjeto

  • Abra o grupo de projetos TesteAjaxEdit.groupproj
  • Clique com o botão direito do mouse no AjaxComponents.bpl, compile e Instale (install)

O controle foi instalado (paleta Ferreira Components). Clique 2 vezes no projeto TestaAjaxEdit e o execute.

Digite as 3 letras iniciais de um nome de pessoa e veja o que acontece.

TAjaxEdit

A edição para e chama uma rotina sua onde é feita uma consulta no banco de dados para mostrar todos os nomes que contém as iniciais digitadas e a exibe no grid.

Se a digitação continuar, a busca é refeita.

Configurando o componente

Descrição das propriedades

Propriedade Descrição Valor Default
ActiveOnCaracter Mostra a animação e chama a rotina de processamento somente a partir do número de caracteres digitados e definido aqui. Pelo valor default somente após a digitação de terceiro carácter é ativada a busca. 3
AjaxImage Informa qual o Timage da animação
EnableAjax Habilita ou desabilita o processamento e a imagem True
SecondsToShow Quantos segundos após parar a digitação deve ser exibido a animação e chamada a rotina de processamento (em milissegundos) 1000 (1 segundo)
Evento OnShowAjax Liga a rotina de processamento

Feito no XE2 mas funciona nas versões “pra frente” e  talvez em algumas “pra trás”

É isso pessoal,  não tem mistério agora é só usar,  e aqui finalizo esse artigo,

até a próxima solução !

 

 

Autenticação no RestWebService

Rest WebService Parte III

Neste artigo falo como fazer autenticação no nosso app RestWebService. Para quem não conhece leia o artigo anterior.

Basic authentication no servidor REST

Foi criada uma nova classe TServerParams, onde nela informamos algumas propriedades :

  • HasAuthentication
  • UserName
  • Password

Esta classe é instanciada no Form Main e alimentado essas propriedades, onde HasAuthentication do tipo boolean informa se terá ou não autenticação. UserName e Password deverão ser informados caso HasAuthentication = True.

TServerParam.jpg

No form Create do form main, instanciamos a classe :

InstaciamosTServerParams.jpg

E colocamos pra rodar.

Passando UserName e Password no Client

No caso de um servidor Rest que tenha autenticação e que o Client não tenha especificado o usuário e senha, quando for feita uma requisição aparecerá como retorno o erro 401 do servidor, como não autorizado :

Unauthorized.jpg

Então abrimos o projeto RestClient e colocamos o componente HttpBasicAuthenticator, setando as propriedades UserName e Password com as mesmas que colocamos no RestWebService.

httpBasicAutenticator.jpg

A IDE faz a ligação automática dele aos componentes RestClient que existirem no form.

Basta rodar que sua aplicação Client já estará fornecendo dados de autenticação para o servidor.

Interessante observar o comportamento de um client do tipo Navegador, ao chamar a URL por ele, recebemos um diálogo informando que necessita de autenticação.  Ao fornecer os dados corretos a URL  é chamada novamente com os dados digitados.

Navegador.jpg

Baixe aqui o RestWebService 1.1

Baixe aqui o RestClient 1.1

 

 

Rest WebService em Delphi com Indy (sem datasnap)

Este artigo é uma continuação do anterior, Se você não leu, faça agora para entender o contexto desse.

Objetivo

O objetivo deste projeto é implementar WebServices REST+JSON em Delphi na versão PROFESSIONAL a partir do Delphi XE2 e posteriores :

  • Sem a utilização de Datasnap,
  • Sem outros frameworks externos (free ou não)
  • Apenas utilizando o INDY que vem com o Delphi em todas as
    versões.

Definição de Rest

Segundo a WikiPedia :

O termo REST se referia, originalmente, a um conjunto de princípios de arquitetura (descritos mais abaixo), na atualidade se usa no sentido mais amplo para descrever qualquer interface web simples que utiliza XML e HTTP (ou YAML, JSON, ou texto puro), sem as abstrações adicionais dos protocolos baseados em padrões de trocas de mensagem como o protocolo de serviços Web SOAP

O Web Service apresentado aqui possui várias características de um REST Web Service são elas :

  • Stateless (não guarda estado após a chamada)
  • Representação de recursos através de JSON/XML
  • Provê troca de mensagens entre Requisitante e Requisitado
  • Recursos endereçáveis pela URI

Mas não provê :

  • Cache

Veja os requisitos para ter um Rest Webservice completo

Rest orientado a Atividade X orientado a Recursos

Neste projeto foi adotado a orientação a atividade porém usando elementos da orientação a recursos (operações GET/PUT/POST/DELETE) foi feito um mix do dois conceitos.

A Estrutura do Projeto

O exemplo será um cadastro de alunos (CRUD) bem simples, sem validações, sem checagem de erros, porque o objetivo aqui é somente mostrar as operações REST.

Foi implementado um “mini-framework” de trabalho, ou seja é necessário encaixar os seus novos métodos nos locais adequados dentro da estrutura montada.

ProjManager

Observe que temos um form Principal, uma Unit de Tipos (SysTypes), um unit com rotinas de auxílio (ServerUtils) e a principal onde iremos trabalhar, a ServerMethodsUnit1.pas

Na Unit ServerMethodsUnit1.pas temos a classe TServerMethods1 já com alguns ServerMethods implementados, são eles :

ServerMethod OPERAÇÃO
ConsultaAluno GET
GetListaAlunos GET
AtualizaAluno POST
InsereAluno PUT
ExcluiAluno DELETE

Obs :  Para essa simulação, não estamos usando banco de dados, para facilitar o teste e evitar que se instale servidores de banco de dados ou criar tabelas, usamos arquivo texto e uma stringlist apenas para demonstrar as operações REST.(GET/PUT/POST/DELETE)

Entendendo a estrutura

Para cada operação (GET/PUT/POST/DELETE) temos um método público na classe TServerMethods da unit ServerMethodsUnit1 :

CallMethods

Para inserirmos um novo método em nosso REST webservice precisamos codificar o próprio método, veja abaixo o server method que retorna a lista de alunos cadastrados :

GetListaAlunos.jpg

E depois colocar dentro de CallGETServerMethod, a chamada para ele, seguindo o padrão existente :

CallGetServerMethod.jpg

O Método CallGetServerMethod será chamado pela engine do framework para toda requisição GET vinda de um client qualquer, desde que este client especifique que a operação é um GET.

O método CallGetServerMethod e os seus primos:

  • CallPUTServerMethod
  • CallPOSTServerMethod
  • CallDELETEServerMethod

São rotinas wrappers onde você encaixa a chamada para o Server Method que você criar.

Pelo padrão adotado, primeiro ele testa Argumentos[0] que deverá chegar aqui com o nome do server method, ele testa também a quantidade de argumentos passados para um dado Server Method, caso a quantidade de argumentos passados não seja a que ele espera receber, retorna uma string JSON indicando erro, quem define a quantidade de argumentos é você.

O array Argumentos sempre conterá o nome do método e em seguida os argumentos, portanto exemplificando para um serverMethod que tenha 2 argumentos, teremos Length(Argumentos) = 3

Se a quantidade de argumentos estiver correta, chame o Server Method passando os parâmetros vindos do Array Argumentos.

A cada novo método será necessário codificar apenas esses 2 pontos,

  • o método em si
  • e a chamada dele em um dos métodos abaixo: CallGetServerMethod, CallPUTServerMethod, CallPOSTServerMethod ou CallDELETEServerMethod conforme for a operação desejada.

a complexidade acaba aqui, é só isso que precisa fazer, o resto a engine do framework faz pra você.

O framework nada mais é do que o processamento do evento OnGetCommand e OnCommandOther do idHttpServer cuidando de separar cada operação e argumentos, isso pode ser visto no frmMain da aplicação.

Convenções

Antes de codificar estabelecemos  algumas convenções de URL :

A URL de chamada deve ser no padrão : http://nomedominio:8080/nomedometodo/argumento1/argumento2/argumentoN

  • Onde nomedometodo é o nome do Server Method que que queremos chamar
  • e Argumentos são os parâmetros que desejamos passar, sendo variável esta parte, dependendo do método pode ter nenhum, 1 ou mais parâmetros

Pronto para o teste

Para testar o framework fiz uma aplicação no Delphi Seattle, utilizando as bibliotecas RestClient que se não me engano vieram a partir do XE5.

RestClienApp1

e aqui a tela do  WebService rodando :

RestWebServiceApp

Baixe os fontes do Rest WebService Application

Baixe o RestClient

Considerações sobre o ambiente

Concorrência

Não há restrições neste framework vindos do Componente idHttpServer visto que o mesmo utiliza os limites da máquina para executar as threads, então se sua máquina possui só um pouquinho de memória, pode ter certeza pelo menos umas 100 threads simultâneas serão executadas normalmente.

O que determinará o desempenho será o volume de dados retornado, a complexidade da query e e esforço que o banco faz para executá-la, quantidade de memória, CPU.

Aqueles que quiserem realizar testes de estabilidade e performance fiquem a vontade para fazer e divulgar resultados.

Testes de concorrência

O componente idHttpServer que foi utilizado aqui, implementa MultiThread, cada requisição vinda de um client qualquer, é criada uma thread para processamento. Para realização de testes de concorrência, retire o  TStringList e a gravação em arquivo texto dos métodos e a substitua por banco de dados. A utilização desse artifício aqui foi somente para efeito de demonstração da aplicação, arquivos textos não funcionarão como persistência de  dados numa aplicação multi-threaded a não ser que se implemente sincronização das threads o que também gera atraso na performance.

Tratamento de erros

Num aplicativo servidor não se permite a exibição de mensagens e nem deixar que solte exceções, todas elas devem ser tratadas e guardadas em log se for o caso, se você permitir o sistema soltar uma exceção por um erro qualquer por exemplo numa query, o webservice  vai parar de responder e precisará ser reestartado.

Então faça sempre uso em todos os ServerMethods de Try/Except seguindo a forma abaixo :

Try 
     Try
          // Instruções do Server Method aqui
     Except 
          ON E:Exception Do
              // Adiciona Log em arquivo texto
     End
Finally
    // Libera objetos se tiver algum
End;

Tipos Retornados 

Os tipos retornados são sempre String em JSON padronizando ao máximo o que se espera de um servidor REST.

Atualização da Thread Principal

Os memos criados na tela principal (frmMain) foram usados apenas para teste e demonstração da aplicação, em produção retire a atualização desses memos ou faça a gravação deles em arquivo a cada mudança de data, limpando o memo logo em seguida, Pois um Memo que nunca é limpo irá consumir toda a sua memória.

Versões do Delphi compatíveis 

O RestWebService foi feito no XE2, e devido a versão do Indy ser diferente em versões mais novas do Delphi, foi preciso colocar compilação condicional. Então para as versões XE2, XE7, XE8 e DX Seattle a compilação condicional já foi feita, basta abrir compilar e rodar.

Para que funcione nas versões XE6, XE5, XE4 e XE3 basta replicar a compilação condicional dessas versões e compilar, veja os pontos onde foi usada na Unit ServerUtils  :

UrdDecode.jpg

e na Unit ServerMethodsUnit1 :

UsesServerMethods.jpg

Conclusão

Penso que o objetivo inicial foi atingido, que era ter um webservice REST + JSON utilizando apenas o Indy e o Delphi professional.

O DataSnap é um produto completo, bem pensado, cheio de recursos e CARO !  é um produto para quem quer ter uma vasta gama de opções e funcionalidades a seu dispor.

Para aplicações menores em que os recursos existentes no Datasnap não são tão essenciais, uma aplicação servidora como essa pode resolver e você economizar uma boa grana usando este mini-framework na versão Professional do Delphi pagando apenas 1/3 do valor da versão Enterprise, a que vem com o DataSnap.

E aí gostou ? se gostou, comente !

Veja aqui o próximo artigo : autenticação no servidor REST

Simple Web Service em Delphi sem DataSnap

Esse é o primeiro artigo de uma série.

Para fazer um WebService simples em Delphi não é necessário DataSnap, apenas usar componente específico do Indy.

Não estamos falando aqui de SOAP e nem de REST . (O Rest WebServer virá no próximo post).

Nesse post falo aqui de um simples serviço prestado por um web server através de uma porta específica, sob protocolo HTTP. O Web Service retornará a data e hora do servidor.

O componente que faz a mágica é o idHttpServer, ele possibilita a implementação de um Http Server , como é o Apache e o IIS. Ocorre que não queremos todas as funcionalidades e nem pretendemos fazer um Http Server, precisamos apenas que o serviço escute numa porta e responda as nossas requisições. É o componente ideal para fazermos nosso WebService.

Foi implementado usando Delphi XE2 Professional edition.

Mãos a obra :

  1. Abra um VCL project no seu Delphi
  2. No Main Form Coloque os componentes IdHttpServer
  3. Configure no idHttpServer a propriedade DefaulPort para 8080
  4. Codifique o evento OnCommandGet com as linhas abaixo :

 

procedure TfrmMain.IdHTTPServer1CommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
     // Retorna a Data e hora
     AResponseInfo.ContentText := DateTimeToStr(now);
     AResponseInfo.WriteContent;
end;

Para que a aplicação minimize no Tray e fique “escondida”  :

  1. Arraste o componente TrayIcon
  2. Codifique o evento OnClick
procedure TfrmMain.TrayIcon1Click(Sender: TObject);
begin
     // Minimiza para o Tray
     TrayIcon1.Visible := False;
     Show();
     WindowState := wsNormal;
     Application.BringToFront();
end;

Para mostrar um balão com o nome do sistema ao passar o mouse por cima:

  1. Arraste o componente TApplicationEvents e codifique o evento OnMinimize :
procedure TfrmMain.apl1Minimize(Sender: TObject);
begin
     // Quando minimizado mostra o Balloon
     Self.Hide();
     Self.WindowState := wsMinimized;
     TrayIcon1.Visible := True;
     TrayIcon1.Animate := True;
     TrayIcon1.ShowBalloonHint;
end;

Coloque 2 botões : 1 para ativar o serviço e outro para parar :

procedure TfrmMain.btnAtivarClick(Sender: TObject);
begin
     IdHTTPServer1.Active := True;
end;

procedure TfrmMain.btnPararClick(Sender: TObject);
begin
     IdHTTPServer1.Active := False;
end;

O webservice está pronto.

 

Baixe aqui o Fonte : SimpleWebServer

Rode e Ative o serviço clicando no botão de Ativar,

Para testar vá no seu navegador e digite :

http://localhost:8080

Para testar numa aplicação Delphi Desktop na sua máquina :

Var
   idhttp :TIdHttp;
Begin
    IdHttp.Create;
    Try
        ShowMessage (idhttp.Get ('http://localhost:8080'));
    Finally
        IdHttp.Free;
    End;
End;

Para consumir em PHP faça :

$response = file_get_contents('http://localhost:8080');

Para colocar o webservice no seu site, execute ele na maquina do servidor e chame no navegador :

http://nomedoseusite.com.br:8080

Simples assim.

Demorou 7 minutos pra fazer, porque sou lento.

Aguardem o próximo post :  Rest WebServer sem Datasnap

Até lá.

 

Boas vindas

Relutei bastante para criar esse blog. Primeiro porque dá um certo trabalho manter, atualizar e mesmo fazer os posts. Mas  vi um máxima num fórum que diz “reter conhecimento é promover a ignorância”,  decidi fazer o blog, pois não quero ser promotor da ignorância alheia.(rs)

Tirando a brincadeira de lado, já fui muito ajudado por postagens publicadas na internet, chegou o momento de eu ajudar.

Tentarei colocar aqui um pouco da minha experiência com o Delphi.

Seja bem vindo ao Delphi Solutions Blog

Claudio Ferreira