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 :
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.
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.
A Linha de código que faz a geração de Log é a “Context.LogBusiness (… ” que pode ser vista em todos os serverMethods :
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
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 :
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 :
Uses :
Dessa forma podemos organizar os ServerMethods em Units separadas por responsabilidade.
Não é Show ? Espero que gostem e comentem.
Valeu.
Muito interessante este artigo. Vou implementar um integrador em delphi 2010 com base neste artigo.
CurtirCurtir
Boa tarde Claudio
Voce teria algum exemplo de como enviar e receber datasets em json usando unidac ou outro componente que nao seja o firedac que nao está disponível na versao Professional do Delphi?
CurtirCurtir
Tenho não amigo.
CurtirCurtir
Clap, clap, clap, magnífico.
Encontrei por acaso seu blog e me surpreendi com essa ideia. Se já não estivesse usando o DataSnap REST creio que usaria sua ideia, parabéns pela iniciativa e mais ainda de compartilhar isto.
Legal se conseguir usar compressão de dados como o DataSnap faz utilizando ZLib.
Uma dúvida, é possível utilizar o RaptorWS como módulo do IIS? Como serviço sei que é bem provável que funcione.
Abraços.
CurtirCurtir
Obrigado que bom que gostou. A compressão de dados está prevista como uma melhoria a ser implementada nas próximas versões do produto. Nada complicado só falta mesmo o tempo pra desenvolver. Não conheço o formato do módulo do IIS, preciso estudar para poder fazer essa integração. Coloco na lista para próximas versões.
CurtirCurtir
muito top, gostei bastante, vou tentar implementar em uma aplicação q ja tenho, uso dataSnap, mas vou fazer desta forma com o rest e json, só tenho q ver como vou adaptar no banco de dados, não tem um exemplo com banco de dados?
CurtirCurtir
Olá Afonso, Não tenho exemplo com banco ainda. Mas a questão do Banco de dados é bem simples. Uma vez que o Raptor é Stateless (não guarda estado) ele é semelhante ao Life Cycle “Invocation” do DataSnap ou seja a conexão com o banco é feita em cada método do WebService. Então o fluxo seria assim em cada método : 1 – Conecta com o Banco, 2 – Realiza a Query, 3 – Transforma o resultado em JSON, 4 – Fecha a conexão com o Banco.
Caso ainda não tenha lido dê uma lida nessa página : https://delphisolutions.wordpress.com/2015/12/07/rest-webservice-em-delphi-com-indy-sem-datasnap/
CurtirCurtir
muito obrigado pela resposta, é q estou começando agora nessa parte de dataSnap e Rest, e a parte de dataSnap ja peguei meia pronta e adaptei as minhas necessidades, mas show de bola, estou acompanhando suas postagens. tenho alguns exemplos passando query para json, vou tentar fazer. parabéns.
CurtirCurtir
No Delphi Berlin 10.1 os argumentos em TServerContext estão sempre zerados, e o servidor não consegue responder a nenhuma solitação. Alguma idéia da causa?
function TServerContext.CallGETServerMethod (Argumentos : TArguments) : string;
CurtirCurtir
Acabei de compilar no Berlim 10.1 e funcionou normalmente. Voce precisa formar a URL corretamente passando parâmetros. Por exemplo : http://localhost:8080/ConsultaAluno/fulano
CurtirCurtir
Boa noite Claudio, não sei o que pode ser. Apenas baixei os arquivos tanto client como server, e compilei. E nada. Se pego os executáveis que já estão compilados, funcionam.
Estranho.
CurtirCurtir
Realmente estranho. Experimente compilar e executar em outra máquina, é a única coisa que me vem em mente, pode ser algum bloqueio na máquina em que você usa atualmente..
CurtirCurtir
Boa noite, antes tarde do que mais tarde.
Testei agora no Tokyo e obtive o mesmo erro, e é graças as diretivas de compilação, que no momento do desenvolvimento ainda não existia Berlin e Tokyo, no máximo Seattle.
{$IFDEF VER300} // SEATTLE
Procurei por todo o projeto e ajustei para a minha versão do Delphi, e agora está OK.
Estou respondendo aqui para registrar, pois caso alguém passe por isso não desista facilmente de um projeto tão bacana.
CurtirCurtir
Obrigado Ricardo, seu comentário é valioso para outras pessoas que possam vir a ter o mesmo problema. Assim que eu tiver um tempo vou retomar esse projeto e adicionar muitas funcionalidades.
CurtirCurtir
Achei muito interessante o projeto, vou dar uma olhada no código depois. Você tem ele em algum controlador de versão público, como o github? Fica mais fácil pra mexer com o projeto, eu acho.
CurtirCurtir
Ainda não tenho ele versionado. Assim que tiver um tempo coloco.
CurtirCurtir
Boa Noite…
Parabéns pelo projeto. Vou baixar e testar.
Teria como embutir nele templates html/angular como no DataSnap ?
Ou seja… tenho uma app rodando com angular/php daí queria migrar para Raptorws usando angula embutido. A chamada seria http://localhost:8080/index.html (tela de login) daí por diante… produtos.html
CurtirCurtir
Olá Anderson, com certeza é possível. A mágica é feita apenas substituindo o retorno da cada método do web-service de JSON para html/angular. Estude os exemplos e você vai entender onde mexer. Não é preciso nem mexer no core do framework, basta colocar essa substituição em cada server method. Boa sorte e depois conte pra nós seu caso de sucesso usando o RaptorWS.
CurtirCurtido por 1 pessoa
os arquivos estao corrompidos
CurtirCurtir
resolvido, desculpa, foi meu antivirus
CurtirCurtido por 1 pessoa
Acabei de baixar Marcelo pela página do site e consegui extraí-los normalmente do .rar
CurtirCurtir
Para fechar com chave de ouro, antes da linha abaixo
AResponseInfo.WriteContent;
Adicione os parâmetros abaixo, isso auxilia em muito o cliente que consome o webservice
AResponseInfo.ContentType := ‘application/json’;
AResponseInfo.ContentEncoding := ‘UTF-8’;
CurtirCurtir
Grato Carlos, vou incorporar ao fonte !
CurtirCurtir
Claudio boa tarde.
Há algum tempo conversei contigo sobre estudar o Raptor WS.
Baseado nele, fiz um ws (ainda em desenvolvimento), onde uso a RTTI pra achar os métodos e o firedac na busca de dados, usando um ORM caseiro.
Ficou bem bacana. Obrigado pelo Help.
CurtirCurtir
Lucas fiquei interessado na rotina de achar os métodos via RTTI, para no caso incrementar o Raptor. Caso não tenha objeção em compartilhar pode me enviar no cldmag@gmail.com. Se tiver alguma objeção sem problema algum, fico feliz que a partir do Raptor você tenha conseguido fazer o seu.
CurtirCurtir