WebServices

Emerson Facunte

Para explicar de maneira adequada o significado da tecnologia WebServices, é interessante fazer uma breve introdução aos problemas atuais no mundo da tecnologia.

Com o grande avanço de sistemas operacionais, bancos de dados, hardware, software, enfim, todo o tipo de tecnologia que envolve o mundo dos negócios, vêm surgindo a necessidade de compartilhamento de informações entre parceiros comerciais, governo e sociedade, e até mesmo entre departamentos de uma empresa.

Acontece que interligar diferentes plataformas, bancos de dados, operações, entre outros conceitos, é uma tarefa muito complicada e trabalhosa.

Para concluir o conceito de WebServices, vamos imaginar um cenário simples, onde precisamos integrar informações de diferentes departamentos e filiais, que foram desenvolvidos em plataformas diferentes. Um bom exemplo para isso, são os bancos que estão adquirindo outros bancos em todo o mundo, e que utilizam conceitos e plataformas diferentes de trabalho.

A figura 1 ilustra o Banco Facunte, adquirindo outros dois bancos com diferentes tecnologias.


figura 1 Banco com diferentes plataformas

Tecnologias do nosso cenário exemplo

Banco

S.O.

Banco Dados

Terminais

Facunte

Unix

DB2

Terminais Linux

 X

NT

SQL Server

Windows

 Y

Solaris

Oracle

Terminais Linux

Integrar informações de diferentes plataformas não é novidade, e como já foi mencionado é possível, mas muito trabalhoso. A proposta da tecnologia WebServices neste cenário, é o de facilitar a troca de informações, fazendo o Banco Facunte entender e tratar as informações dos Bancos X e Y, independente do banco de dados, sistema operacional, ou outro fator não citado.

Com algumas linhas de programação e um bom planejamento, as informações essenciais serão interligadas facilmente.

Meus amigos, isso é WebServices!

Em resumo, WebServices, é um padrão não-proprietário, que possibilita o processamento distribuído em sistemas heterogêneos.

E acredito que muitos de vocês neste ponto estão ansiosos para produzir o seu primeiro WebService. Antes, devemos conhecer os padrões que fazem parte da tecnologia.

WebService Exemplo

Vamos criar nosso primeiro WebService para aprender melhor seu conceito.

Através das opções File/New..., seção WebServices, selecione a opção SOAP Server Application (figura 2).


figura 2 Nova aplicação WebService

Em seguida selecione a opção CGI para o tipo da aplicação servidora SOAP (figura 3).


figura 3 Tipo da aplicação servidora


Em seguida o Delphi pergunta se deseja criar uma Interface SOAP padrão (figura 4). Em nosso exemplo, vamos criar a tal Interface, a fim de conhecer sua implementação.



figura 4 Criação da Interface


Em seguida (figura 5) devemos informar os dados da nova Interface.

Nos campos Service Name e Unit identifier coloque wsexemplo. Com isso estamos criando uma Interface com o nome wsexemplo, e gravando a unit com o mesmo nome.

Em Code generation selecione as opções Generate Comments e Generate Sample Methods. Com isso estamos gerando exemplos de métodos e comentários.




figura 5 Identificação do serviço


Clique em OK para finaliza.

Vamos gravar nossa aplicação.

Unit WebModule

un_ws1.pas

Unit Implementação WsExemplo

wsexemploImpl.pas

Unit Interface WsExemplo

wsexemploIntf.pas

Projeto

ws1.dpr


Vamos analisar o que o nosso amigo Delphi criou.


figura 6 WebModule1


A figura 6 ilustra nosso WebModule com três componentes no padrão WebService (HTTPSoapDispatcher, HTTPSoapPascalInvoker,WSDLHTMLPublish).

Vejamos sua implementação.

procedure        TWebModule1.WebModule1DefaultHandlerAction(Sender: TObject;
       Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  WSDLHTMLPublish1.ServiceInfo(Sender, Request, Response, Handled);
End; 
A única função do nosso WebModule1,é a criação de um handler para o WebService e publicação do documento WSDL.

Na unit wsexemploIntf estamos definindo a Interface de nossa aplicação.
{Invokable interface Iwsexemplo }

unit wsexemploIntf;
interface

uses InvokeRegistry, Types, XSBuiltIns;

type

TEnumTest = (etNone, etAFew, etSome, etAlot);

TDoubleArray = array of Double;

TMyEmployee = class(TRemotable)
private
FLastName: AnsiString;
FFirstName: AnsiString;
FSalary: Double;
published
property LastName: AnsiString read FLastName write FLastName;
property FirstName: AnsiString read FFirstName write FFirstName;
property Salary: Double read FSalary write FSalary;
end;

{ Invokable interfaces must derive from IInvokable }
Iwsexemplo = interface(IInvokable)
['{A391DC0F-CDA7-4929-97B8-DAECA7C2CF18}']

{ Methods of Invokable interface must not use the default }
{ calling convention; stdcall is recommended }
function echoEnum(const Value: TEnumTest): TEnumTest; stdcall;
function echoDoubleArray(const Value: TDoubleArray): TDoubleArray; stdcall;
function echoMyEmployee(const Value: TMyEmployee): TMyEmployee; stdcall;
function echoDouble(const Value: Double): Double; stdcall;
end;

implementation

initialization
{ Invokable interfaces must be registered }
InvRegistry.RegisterInterface(TypeInfo(Iwsexemplo));

end.

Esta unit na realidade está seguindo as regras da O.O. (Orientação a Objeto), onde definimos uma Interface como base, para que possamos implementar nossas classes. Além disso estamos registrando a Interface no modelo SOAP.

Repare que os métodos criados são apenas exemplos de implementação, que solicitamos previamente, justamente para estudar e analisar.

Na unit wsexemploImpl, temos a implementação da Interface que vimos anteriormente.

Acredito que deu pra perceber, que os métodos apenas retornam os mesmos valores informados.

Para compreender melhor, vamos fazer uma pequena alteração no método echoDouble. Substitua a linha de retorno, pelo código que segue em negrito:

function Twsexemplo.echoDouble(const Value: Double): Double; stdcall;
begin
{ TODO : Implement method echoDouble }
Result := Value * 3;
end;

Perceba que estamos multiplicando por 3, só para quebrar o gelo (Double = Dobro)

Antes de compilar vamos definir o diretório para geração do nosso WebService.

Através das opções Project/Options.../Directories_Conditionals, configure a opção Output Directory, apontando para o o seu diretório cgi-bin (figura 7).


figura 7 Configuração do diretório


Grave novamente a aplicação.

Agora vamos compilar a aplicação.

Vamos executar a aplicação no browser para analisar o seu conteúdo. Lembre-se que para isso você deverá configurar um servidor web, como o Apache, IIS, Xitami, etc.

Digite: http://localhost/cgi-bin/ws1.exe/

A figura 8 ilustra o resultado da primeira fase de nossa aplicação.



figura 8 Aplicação ws1


Repare que temos todos os métodos listados na Interface Iwsexemplo (echoEnum, echoDoubleArray, echoMyEmployee, echoDouble).

O documento gerado está de acordo com o padrão estabelecido pelo W3C-UDDI (órgão responsável pelo padrão WebService).

Clicando no link WSDL da Interface Iwexemplo será apresentado um documento WSDL.

Vamos analisar algumas partes do documento para compreender melhor seu funcionamento.

- <types>
- <xs:schema targetNamespace="urn:wsexemploIntf" xmlns="urn:wsexemploIntf">
- <xs:simpleType name="TEnumTest">
- <xs:restriction base="xs:string">
<xs:enumeration value="etNone" />
<xs:enumeration value="etAFew" />
<xs:enumeration value="etSome" />
<xs:enumeration value="etAlot" />
</xs:restriction>

Passando pelo bloco das definições inicias (<?xml version="1.0"...), chegamos no bloco de definições de tipos e métodos.

Neste bloco são definidos todos os métodos da nossa Interface, com o descritivo completo. Repare que a classe TEnumTest é descrita com perfeição.

No bloco que segue, são descritos os métodos Request e Response da Interface em questão.

- <message name="echoEnum0Request">
<part name="Value" type="ns1:TEnumTest" />
</message>
- <message name="echoEnum0Response">
<part name="return" type="ns1:TEnumTest" />
</message>

A seguir, temos o bloco que define o nome da porta (Port), e as operações Request e Response, descritas no bloco anterior.

- <portType name="Iwsexemplo">
- <operation name="echoEnum">
<input message="tns:echoEnum0Request" />
<output message="tns:echoEnum0Response" />
</operation>

Em seguida temos o bloco que "envelopa" e define a camada de transporte dos métodos.

- <binding name="Iwsexemplobinding" type="tns:Iwsexemplo">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
- <operation name="echoEnum">
<soap:operation soapAction="urn:wsexemploIntf-Iwsexemplo#echoEnum" style="rpc" />
- <input message="tns:echoEnum0Request">
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:wsexemploIntf-Iwsexemplo" />
</input>
- <output message="tns:echoEnum0Response">
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:wsexemploIntf-Iwsexemplo" />
</output>

O último bloco finaliza o documento, declarando o nome do serviço, bem como o nome da porta e a sua camada de transporte.

- <service name="Iwsexemploservice">
- <port name="IwsexemploPort" binding="tns:Iwsexemplobinding">
<soap:address location="http://localhost/delphi/cgi-bin/ws1.exe/soap/Iwsexemplo" />
</port>
</service>
</definitions>

Agora vamos criar uma aplicação cliente para testar nosso primeiro WebService.

Através das opções File/New Application cria uma nova aplicação, e grave os arquivos como segue:

Unit

un_teste_ws1.PAS

Projeto

teste_ws1.DPR

Agora vamos importar a Interface em nossa aplicação. Através das opções File/New.../WebServices (figura 9), selecione a opção WSDL Importer.


figura 9 WSDL importer

Em seguida, como ilustra a figura 10 , digite endereço que segue.

http://localhost/cgi-bin/ws1.exe/wsdl/Iwsexemplo

Este endereço faz a chamada ao documento WSDL da Interface Iwsexemplo.


figura 10 Importação da Interface através do WSDL

Este procedimento está importando toda a Interface para a nossa aplicação. Com isso teremos acesso aos métodos definidos.

É interessante destacar que um WebService poderá ter inúmeras Interfaces, onde poderemos importar apenas as que condizem com a nossa necessidade.

Aperte o botão Next para avançar a avançar à próxima fase.

A figura 11 ilustra a Interface gerada pelo assistente.



figura 11 Interface gerada pelo assistente


Para concluir aperte a tecla Finish.

O assistente gerou uma Unit com toda a Interface implementada.

Grave a Unit com o nome Iwsexemplo1.pas.

O que acabamos de fazer, na realidade, foi a importação de uma Interface para facilitar o uso do WebService.

Agora com o foco na unit un_teste_ws1, insira a unit Iwexemplo1.pas gerada pelo assistente.

implementation
       uses Iwsexemplo1;


Neste ponto iremos configurar o acesso para este formulário.

Insira um objeto do tipo THTTPRIO, e configure as propriedades que seguem, respeitando a seqüência apresentada, caso contrário, uma exceção ocorrerá.

OBJETO

THTTPRio

Objeto

Propriedade

Valor

HTTPRio1

Name

HR1

WSDLLocation

http://localhost/cgi-bin/ ws1.exe/wsdl/Iwsexemplo

Service

Iwsexemploservice

Port

IwsexemploPort

Com isto configuramos o objeto de acesso à Interface, informando a localização do documento WSDL (WSDLLocation), o serviço (Service), e a porta (Port).

Agora insira os objetos que seguem, configurando suas respectivas propriedades.

OBJETO

TEdit

Objeto

Propriedade

Valor

edValor

Name

edValor

Left

32

Text

deixe em branco

Top

24

Width

120


OBJETO

TButton

Objeto

Propriedade

Valor

Button1

Name

Button1

Caption

Calcula

Left

176

Top

24

Width

125


OBJETO

Tlabel

Objeto

Propriedade

Valor

lbResultado

Name

lbResultado

Caption

0

Left

32

Top

64


A figura 12 ilustra o formulário da nossa aplicação.


figura 12 Formulário da aplicação


Agora vamos codificar a aplicação. Insira o código que segue no evento OnClick do objeto Button1.

var
Iexemplo: Iwsexemplo;
begin
Iexemplo:= HR1 as Iwsexemplo;
lbResultado.Caption:=FloattoStr(Iexemplo.echoDouble( StrtoFloat(edValor.Text)));
end;

O código é bastante simples, onde estamos definindo um objeto do tipo Iwsexemplo. Em seguida estamos instanciando o objeto a partir do nosso HTTPRio (HR1), adotando o modelo Iwsexemplo. E por fim, apresentamos o resultado em nosso objeto lbResultado, através da função IExemplo.echoDouble.

O mais importante até aqui, é justamente a compreensão de como conseguimos implementar o WebService em nossa aplicação.

Vamos testar nossa aplicação.

Compile e execute a aplicação, informando um número no campo e pressionando o botão. A figura 13 ilustra nossa aplicação em tempo de execução.


figura 13 Aplicação em tempo de execução


Perceba que a primeira vez que pressionamos o botão, existe um delay, que é justamente o tempo de conexão com o WebService.

Repita a operação, e repare que já não existe mais o delay.

Amigos isto é apenas o começo. Em meu livro Delphi 7 Internet e Banco de Dados, explico através de exemplos práticos todo o poder dos WebServices. Temos WebServices utilizando banco de dados como serviço, e também conexões concorrentes utilizando o protocolo SOAP.

Forte abraço e imenso sucesso a todos !!!


EMERSON FACUNTE

COMENTÁRIOS
Walter Donizete fari - 28/02/2003 - 13:42:45
Emerson sou iniante em delphi p/ internet, ja comprei um livro.. mas não consegui desenvolver os aplicativos de exemplo. D? para vc me passar um pequeno exemplo e mostrando como eu executar.
No exemplo do livro eu fiz , compilei no delphi e criou um arquivo chamado ( Saudacao.dll ) como executar este programa ele no livro pede p/ configurar PWS mas não consegui executar o exemplo....Valeu obrigado eu imprimi este exemplo..Obrigado.
................................................
Emerson Facunte - 06/03/2003 - 14:21:43
Sobre o comentério do amigo Walter Donizete

Olá Walter,

Acredito que você se refere ao livro Delphi 5 Com?rcio Eletrínico. Realmente neste livro apresento técnicas do WebBroker, onde o PWS é fundamental para realização dos testes e exerc?cios.

Se você estiver utilizando Delphi 6 ou superior, crie os exemplos utilizando a op?ão Web App Debugger apenas para executar localmente a aplicação.

Em meu novo livro, Delphi 7 Internet e Banco de Dados, abordo todas as tecnologias de desenvolvimento Internet presentes nesta nova versão (WebBroker, WebSnap, WebServices e o todo poderoso Intraweb)

Forte abraão e sucesso
................................................
S?rgio Rodriguez - 25/04/2003 - 11:07:23
Muito bom seu artigo, ali?s, um dos poucos que consegue exemplificar de maneira clara e objetiva todo o poder dos WebServices.

Parabéns!!!
................................................
Emerson Facunte - 14/05/2003 - 08:52:46
Sobre o comentério do amigo S?rgio Rodriguez

Agradeão imensamente o seu comentério. Realmente o objetivo é esse, exemplificar de maneira clara o poder dos WebServices.

Enjoy the party, friends !!!
................................................
hene - 28/05/2003 - 17:53:43
................................................
hene william (durale - 28/05/2003 - 17:57:15
emerson ja fiz a encomenda do seu livro, devido o desenvolvimento de webservice, estou tendo problemas com aplicação client. ao executar o client em alguma estação o sistema trava, quando rodo no servidor funciona perfeitamente.
o que pode será
................................................
Paulo Roberto - 03/06/2003 - 11:40:13
Facunte, Adquiri o seu livro e o mesmo é um Show!!!
Obrigado por ter escrito este livro! A parte sobre a Intraweb é demais!!!
Parabéns!

P.S. Em testes com a Intraweb com banco de dados, estou testando ADO com Access, ao Executar o programa no Stand Alone Application With Data Module, estou tendo o seguinte erro: CoInitialize não foi chamado
grato,
pro1@globo.com
................................................
Andr? Luiz Duran - 19/06/2003 - 16:12:18
Ola Sr. Emerson Facunte, comprei um livro sobre objetos distribuidos "Sistemas Multicamadas com Delphi" e no final existe um depoimento seu muito interessante, parabens.

O livro mencionado é muito bom, porem estou tendo algumas dificuldades em entender algumas coisas e gostaria de comprar outro livro. Tenho algumas dúvidas:

O seu livro trata do mesmo assunto ?
Qual o nível de dificuldade ?
No livro tem exemplos ?

Obrigado

andrelduran@yahoo.com.br
................................................
Luciana - 24/06/2004 - 10:05:46
Olá, segui passo a passo seu exemplo, mas tenho uma dúvida sobre:
"Vamos executar a aplicação no browser para analisar o seu conte?do. Lembre-se que para isso você deverá configurar um servidor web, como o Apache, IIS, Xitami, etc.

Digite: http://localhost/cgi-bin/ws1.exe/"
Esta parte não consegui entender, como vou configurar este servidor Web. Se puder me ajudar!!!
Obrigada...

................................................
Dalmo Vieira da Silv - 13/08/2004 - 11:34:14
Olá Emerson,

Seu artigo é último, porém, segui passo a passo
as instrucoes para criar o exemplo sobre a
WebServer com Delphe 6 e nao houve a pergunta
se deseja criar a interface. Por qu??

Desde já agradeão.
................................................
Magnun - 20/11/2004 - 14:21:00
Estou com o mesmo problema da Luciana, diretério cgi-bin? tem algum arquivo especial nele para que funcione?
Postei aqui pois na lista ninguém reposndeu.
Obrigado
................................................
O Envio de Comentários está suspenso temporáriamente