14 Kasım 2012 Çarşamba

Delphi ‘de Web servisleri ve SOAP Uygulamaları


Giriş
Web Servisleri Internet üzerinden yayınlanan ve çağrılabilen bağımsız modüler uygulamalardır. Web servisleri sağlanan hizmetleri açıklamak için iyi tanımlanmış ara yüzler sağlar. Istemci gözatıcılar için Web sayfaları üreten Web sunucusu uygulamalarının aksine, Web Servisleri doğrudan insan etkileşimi için tasarlanmış değildirAksine, bunlara istemci uygulamaları tarafından programlama yoluyla erişilir.

Web servisleri istemci ve sunucu arasında serbest bir bağlantı sağlamak için tasarlanmıştırYanisunucu uygulamalarının istemcileri belirli bir platform ya da bir programlama dili kullanma ihtiyacı duymaz. 
Dilin doğal tarzında, arayüz tanımlamaya ek olarak çoklu iletişim mekanizması da tasarlamaya izin verir.
Web servisleri, SOAP (Basit Nesne Erişim Protokolü) kullanarak çalışmak üzere tasarlanmıştır. SOAP merkezi olmayan, dağıtılmış bir ortamda bilgi değişimi için standart hafif bir protokoldür. Uzak yordam çağrıları kodlamak için XML kullanır ve genellikle bir iletişim protokolü olarak HTTP kullanır. SOAP hakkında daha fazla bilgi için, http://www.w3.org/TR/SOAP/  adresindeki SOAP spesifikasyonuna bakın.

Not: Web servislerini destekleyen bileşenler(componentler) SOAP ve HTTP kullanacak şekilde inşa edilmiş olmalarına rağmen,frameworkun(çerçevenin)diğer kodlama ve iletişim protokollerini kullanacak şekilde genişletilecek kadar yeterince geneldir.
Delphi SOAP tabanlı Web Servis uygulamalarını (sunucu) size inşa etmenize izin vermesi yanında , özel bileşenler ve sihirbazlar size web servisleri için istemciler inşa etmenize ya SOAP ya da  belge birebir stili kullanıarak size izin verir . Belge birebir stili .Net Web Hizmetlerinde kullanılır.
Web servis  uygulamaları arayüzlerde ne bulunduğu bilgisini ve bunları WSDL (Web Service Definition Language-web servisi tanmlama dili) kullanarak nasıl çağırılacağı bilgisini yayınlar.  Sunucu tarafında, uygulamanız bir Web servisinizi tanımlayan bir WSDL dokümanı yayınlayabilir.  İstemci tarafında, bir sihirbaz veya komut satırı yardımcı programı , ihtiyacınız olan bağlantı bilgisini ve ara yüz tanımlarını size sunarak bir yayınlanmış WSDL dökümanı ithal edebilir.  Zaten uygulamak istediğiniz Web sunucusunu  tanımlayan WSDL belgesi varsa WSDL belgesi alırken, siz de sunucu taraflı kodu oluşturabilirsiniz
 ve SOAP istemci ve sunucu taraflı program yazabilirsiniz.
SOAP  Demosunu İnşa Edelim
Bu konuda çok detaya girmeden sunucu ve istemci yazılımını yazmak faydalı olacaktır Biri server uygulaması ve diğeri client tarafı uygulaması olmak üzere iki uygulama hazırlayacağız. Bunun için .groupproj uzantılı grup oluşturup bu dosyada, bu iki exe yi barındırmak dizayn açısından bize kolaylık sağlayacaktır.
Server tarafı
Uzak bağlantıların erişip çalıştıracağı, uzak fonksiyonları server tarafında barındıryoruz. Bunun için Delphi 2009 ve sonrası için direkt File > New > Other > Delphi Projects > Web Services > SOAP Server Application seçilir Şekillerdeki adımlar sıra ile yapılır.






Şekil -4 teki code generation kısmını işaretlerseniz otomatikman örnek yordamlar ve 3 adet delphi uniti oluşuyor.

Bu diyolagtaki seçeneklerin açıklması aşağıda verilmiştir.
Madde
Açıklama
Service name (Servis Adı)
İstemcilere göstermek istediğiniz web servisin çağırılabilir arayüzünün adını girin. Bu ad ara yüz adı olarak kullanılır. Aynı zamanda uygulama sınıfı adını oluşturmak için kullanılır. Bu nedenle, örneğin, MyWebService  yazarsanız wizard MyWebService adlı çağırılabilir arayüz oluşturur ve uygulama sınıfı  TMyWebServiceImpl olarak adlandırılır.
Unit identifier (Birim tanımlayıcı)
 Wizardın oluşturacağı ve uygulama sınıfı ve arayüzü içeren unitin adını girin.
Generate comments (yorumları oluştur)
İsteğe bağlı. Wizard tarafından oluşturulmuş unite kodun ne yaptığını anlatan yorumları ekler. Kullanıcılara kolaylık olsun anlaşılır olsun diye konmuş bu seçenek.
Generate sample methods (Basit yordamlar oluştur.)
İsteğe bağlı. Wizard tarafından oluşturulmuş unite, örnek kod ekler.  Bu kodu kullanabileceğiniz gibi uygulama sınıfı ve çağrılabilir ara yüzün uygulanması ve tanımlanması için bir kılavuz olarak kullanabilirsiniz.
Service activation model (Servis aktivasyonu modeli)
Drop-down listeden istediğiniz aktivasyon modelini seçin.
  • Per Request Seçeneği uygulamanız için aldığı her isteğe(request) karşı cevap vermek için uygumla sınıfınızın yeni örneğini oluşturur. İstek(request)         işlendikten sonra bu örnek istek(request) boşaltılır.
  • Global Object Tüm istekleri(request) işlemek için kullanacağınız uygulama sınıfının bir tek örneğini oluşturur.


Bunlardan WebModuleUnit1.pas uniti SOAP bileşenlerinin bulunduğu unittir.  Web servisi için gereken bir dağıtıcı ve bir çağırıcı (invoker): çığırılabilen (invokable) arabirimleri ve bunları uygulayan sınıflara ek olarak, sunucu iki bileşen gerekir. (Soap.WebBrokerSOAP.THTTPSoapDispatcher) gelen SOAP mesajları alır ve invoker onları aktarır. Invoker (Soap.SOAPHTTPPasInv.THTTPSoapPascalInvoker), SOAP mesaj yorumlaması onu çağıran invokable arabirimi tanımlar, çağrı yürütür ve cevap mesajı toplanır.

Not: THTTPSoapDispatcher ve THTTPSoapPascalInvoker bir SOAP isteği içeren HTTP mesajları yanıtlamak için tasarlanmıştır. Temel mimarisi farklı dispatcher ve invoker bileşenlerinin ikame ederek diğer protokolleri destekler, ve yeterince geneldir.
Sonra HTTP isteği mesajı SOAP eylem başlığında bu arabirimleri tanımlamak iletileri işlemek için otomatik invokable arayüzler ve uygulama sınıfları, dağıtıcı ve çağırıcıya (invoker) kayıt olur.

Web servisleri de bir yayıncı (Soap.WSDLPub.TWSDLHTMLPublish) içerir. Yayıncılar uygulamasında Web sevislerini aramak için açıklayıcı WSDL dokümanları oluşturarak gelen istemci isteklerine yanıt verir. Bu uygulama müşterilerine Web servisi tanımlayan WSDL belgeleri yayımlamayı sağlar. WSDL yayıncı hakkında bilgi için, bir Web servisi uygulaması için WSDL Belgeler oluşturur.


Tüm bunları yaptıktan ve açıkladıktan sonra bu hazır oluşan projeye bir de ADO bağlantısı ekleyelim. Bu WebModuleUnit1.pas unitinde eklediğimiz  ADOConnection1 componenti ile olsun.  Ki databaseden veri okumayı da öğrenmiş olalım. ADOConnection1.ConnectionStringi  webde açılacak databasein adına passwordune göre değiştirilmelidir..


Tüm bunlar sonucunda DemoSoapWebServer.dll oluşacaktır. Bu dll web hosta konacak web server olan dll.dir. 

Burada default olarak  WSDLHTMLPublish1 de http://localhost/ demosoap/ DemoSoapWebServer.dll /wsdl olarak tanımlanmıştır. DemoSoapWebServer.dll programı compile edildikten sonra  C:\inetpub\wwwroot\ demosoap klasörüne yüklenmelidir.Ama siz localhost yerine sitenizde de yayınlyabilirsiniz.

Ayrıca iis.exe çalıştırılıp bu dll in kaydı yapılmalıdır. Bunun için Denetim Masasından Yönetimsel Araçları seçip Internet Information Services (IIS) Yöneticisini çalıştırın. Şekil 5 teki gibi sanal dizin ekleyin.Ve şekil 6 da gösterildiği gibi uygulmaya dönüştürün.


iis de ISAPI ve CGI kısıtlamaları ve  iis de handeler mapping (işleyici eşlemeleri) bölümünden tanım yapılamalıdır. Bunlar aşağıda şekil 7,8-9 gösterilmiştir.





 

Eğer iis 7.0 ve üstü ise demosoap sanal dizinin altındaki web.config aşağıdaki gibi değiştirilmelidir. En azından handlers tagı.

<configuration>
    <system.webServer>
        <directoryBrowse enabled="false" /> 
      <handlers accessPolicy="Read, Write, Execute,Source, Script">
           <add name="IDemoSoapWebServer" path="DemoSoapWebServer.dll" verb="*" modules="IsapiModule" scriptProcessor="C:\inetpub\wwwroot\demosoap\DemoSoapWebServer.dll" resourceType="File" allowPathInfo="true" requireAccess="Execute" />

  </handlers>
    </system.webServer>
</configuration>

Tüm bunlar bittikten sonra internet göz atıcınızı açıp adres çubuğuna
http://localhost/demosoap/DemoSoapWebServer.dll/wsdl/ yazıp enter basın şekil 10 daki görüntü karşınıza çıkacaktır. Ekrandaki butona tıklanıp admin kaydı yapılmalı
Bunların görüntüsü de şekil 10-a-b-c de verilmiştir.





Sonrada IDemoSoapWebservisi yazan tarafı tıklanıp explorerdan save as ile C:\Users\aysen\Documents\IDemoSoapWebServisi.wsdl saklanmalıdır. Eğer netten yayınlanacak servisin olduğu yere Şekil 11 deki gibi kopyalanır. kopyalanır.




Client Tarafı Uygulama Projesinin Oluşturulması

Bu herhangi platformda olabilir. Ama yine Delphi’de gösterdik. Daha sonra bu grupa sağ tıklayıp new Project ile çıkan diyolagtan VCL Forms Application ekleyerek yeni projeyi DemoSoapClient.dpr olarak adlandırarak ekleyim. Sonra Şekil -12 de gösterildiği gibi File > New > Other > Delphi Projects > Web Services >WSDL Importer i seçelim. Sonra şekil 13 te gösterildiği gibi publish ettiğimiz .wsdl uzantılı dosyanın yolunu buradaki yazım kutucuğuna yazalım ve  User Name ve passworde windowsta admin hakkına sahip tanımlı kullanıcının user name ve passwordunu yazalım.  Böylelikle servisin tanımlı olduğu unit otomatikman oluşacaktır.





 Daha sonra ana formumuza tool paletteden bir HTTPRIO componenti ekleyelim. Bunun WSDLLocation özelliğne wsdl dökümanın yolunu yazalım. Şekil 14 de gösterilen HTTPWebNode özelliğin altındaki password ve username windows hesaplarında tanımlı olan
Kullanıcı adı ve passworunu yazıp,port ve service özelliklerinden ilgili port ve servisi seçelim.
Böylelikle web servisini kullanıma açmış oluruz.





İki adet butondan echoDouble uzak makinadaki echoDouble  fonksiyonu çağırır diğeri ise DB den veri okumayı gösteriyor.

procedure TForm2.BitBtn1Click(Sender: TObject);
var
GelenSayi:Double;
begin
GelenSayi := (HTTPRIO1 as IDemoSoapWebServisi).echoDouble(5);
MessageDlg(FloatToStr(GelenSayi),mtWarning,[mbOk],0);
end;

procedure TForm2.BitBtn2Click(Sender: TObject);
var
DBVeriPersonel:TMyEmployee;
begin
//web serverdaki veri tabanından veri okuyor.
DBVeriPersonel:= (HTTPRIO1 as IDemoSoapWebServisi).DBveriOku(1);
MessageDlg(DBVeriPersonel.FirstName+' '+DBVeriPersonel.LastName,mtWarning,[mbOk],0);

end;

 Kodları aşağıdaki linkten çekebilirsiniz.Kodları indir

16 yorum:

Sadettin POLAT dedi ki...

Makale icin tesekkurler , bu konuda belkide ilk turkce makaledir. Bircok kisiye faydasi olacagina eminim.

Web servise birden fazla client ayni anda baglanti kuracagi icin tek bir connection isimizi gorecek mi yoksa daha farkli bir connection mantigi mi kullanmaliyiz ?

Biz kendi uygulamamizda her istek icin bir tane data module crate edip , veritabanina connection acip islem yapiyorduk. bunun dogrusu nasil olmalidir ?

aysenlik dedi ki...

Ben teşekkür ederim.
Buradaki örnek ve benzerleri için tek connection ve data module yeterli. Sizin uygulumanın özel bir durumu mu var her istek için ayrı data module create ediyorsunuz? Bilemem ama geçmişte başka bir projemde karşılaştığım bir problem vardı 5 sene önce falandı. Server tarafındaki projenin DemoSoapWebServisiImpl.pas unitine

function TDemoSoapWebServisi.DBveriOku(const Numara: Double):


yordamının altındaki

with (GetSoapWebModule as TWebModule1) do begin
...
end;

bloğunu kullanınca düzelmişti. Bunu bir deneyin bakalım ne olacak.

Sadettin POLAT dedi ki...

Bizdeki web servis veritabanina insert ve update islemleri de yapiyordu. Kendi denemelerimizde insert ve update islemlerinde bir sorun olmadi fakat web servisi production ortamina deploy ettigimizde IIS 'in belli belirsiz bir sekilde coktugunu tespit ettik. Ardindan ufak bir test uygulamasi ile 50 adet thread ile servisi call ettigimizde bu hatanin olustugunu gorduk. Sanirim veritabanina yapilan insert ve updatelerde birden fazla client ayni connection uzerinden islem yapmak istediginde olaylar karisiyor. oncelikle veritabani sunucusu olmak uzere iis in cokmesine kadar giden bir surec yasiyorduk.

Bizim kullandigimiz veritabani firebird idi , belki Ado + Sql server kullansak daha farkli sonuc alabilirdik ama sonrasinda internetten arastirdigimiz orneklerde Dr. Bob ' un makalesinde her client icin ayri bir datamodule olusturmak suretiyle her istek icin bir Connection olusturarak izolasyon sagladigini gorduk. simdilik servisin calismasi bu sekilde ve bir problem yok.

Tabi her istek icin connection acmak biraz pahali bir islem. Bunun daha efektif ve performansli bir yontemi varsa ogrenmek isterim.

aysenlik dedi ki...
Bu yorum yazar tarafından silindi.
aysenlik dedi ki...

iis 7 ve daha önce de 2000 NT nin iis'de db connectionı olan uygulama geliştirmiştim . ADO ve MS SQL kullanmıştım ve uygulamada bol bol insert update vardı.

Ado connetion ile ilgilgi kodu aşağıda yazdığım kodun içinden yazınca hiç bir problem yaşamadım.
with (GetSoapWebModule as TWebModule1) do begin
...
end;

İsterseniz mevcut projenize dokunmadan basit bir proje yazıp böyle deneyin. Büyük bir ihtimalle problem çıkmayacaktır.
Çünkü o zamanlar Dr.Bob'un sitesine ben de bakmıştım ve orada bu blok yoktu. Sanırım tartışma forumlarından bu bloğu kullanma önerisi aldım ve hiç bir problemim kalmadı. Denemeye değer...

İyi Çalışmalar

Serkan BOZOĞLU dedi ki...

ile > New > Other > Delphi Projects > Web Services >WSDL Importer
yaparken uzak sunucu adresini yazdığımda unable to load hatası veriyor
ozaktaki web server a bağlanmam için yardımcı olabilirmisiniz.

mehmet dedi ki...

tesekkürler

Unknown dedi ki...

Ben daha önce Web servisleri ile uygulama geliştirdim (İTS). Şu anda üzerinde çalıştığım yeni bir uygulama var.(HKS) Ancak bu uygulama henüz test aşamasında ve bu siteye güvenlik sertifikası almamışlar. Bu yüzden HTTPReqResp komutu çağrıldığında geriye sertifika hatası mesajı dönüyor.
Oysa SoapUI kullanarak siteye XML formatında bilgi gönderip, XML formatında cevap alabiliyorum.
Delphi7 ile bu sorunu nasıl geçebilirim ? Bilginiz varsa yardım ederseniz memnun olurum.
Teşekkürler.
Hasan ERZİK.

aysenlik dedi ki...

Bazı durumlarda uzak sunucuya kullanıcı adı ve şifre ile girmeniz gerekebilir . Bunu tespit edin önce
İyi Çalışmalar

Unknown dedi ki...

Sorunumu çözdüm. İTS'de sistemin göz ardı ettiği SOAP string'i HKS'de doğru girilmesi gerekiyormuş. Ancak şimdi başka bir sorunum var. Geri cevap olarak dönen XML şeması içindeki Türkçe harfler bozuk çıkıyor. Ne yapsam düzeltemedim...

Unknown dedi ki...

Onu da çözdüm.
UTF8Decode(XMLdosyası);
komutu halletti..

Namiq dedi ki...

Təşəkkürlər! Bu sahədə çalışıb fikirlərinizi bizimlə paylaşırşırsız!

Unknown dedi ki...

Merhaba,
Öncelikle yazınız için teşekkürler.Size sormak istediğim bir soru olacak.C# üzerinde yazılmış bir web servisden bize bir dataset dönüyor.Delphi üzerinde servise bağlandık fakat bu dönen dataseti delphide bir dataGrid üzerinde nasıl gösterebiliriz?
Teşekkürler iyi çalışmalar

Unknown dedi ki...

Ayşe hanım delphide yeni sayılırım ama veritabanına artık veri ekleyip silebiliyorum. Ben server deki tabloya veri ekleyip silmek istiyorum. 1.hangi db yi kullan malıyım? 2. Bunu nasıl yapacağım :)? Yani hep örneklerde basit text mesaj göndermeyle karşılaştım. Veri tabanına toplu bilgi nasıl gönderilir. Bu konuda aydınlatıcı bir yazınız olurmu en basitinden clientte tel rehberine yazdığım numara serverde gözüksün. Bir diğer konu client ip port vs ile server ip port vs bunlar her defasında manuel mi yazılıyo ip nin static veya dinamic olması sorun olmazmı.

aysenlik dedi ki...

mssql kullanın statik ip kullanın

Unknown dedi ki...

Ayşen Hanım Merhaba,

web servis konusunda yeni sayılırım bu yüzden yardımcı olmanız dileyerek sorularım olacak, kodunuzu çalıştırdığım zaman "---------------------------
Error
---------------------------
Cannot run project unless a host application is defined. Use the Run|Parameters... dialog box.
---------------------------
OK
---------------------------" şeklinde bir hata alıyorum,
2. bir soru "Provider=SQLOLEDB.1;Persist Security Info=True;User ID=sa;Initial Catalog=DEMODB;Data Source=http:\\www.localhost.com" kısmında yer alan "http:\\www.localhost.com" kısmına genelde ip giriyorduk buradaki mantık nedir ?

ALLAH GÜZEL İSİMLERİ(ESMAÜL HÜSNA) VE KAİNAT VE KORONA VİRÜSÜNÜN HAYIRLI TARAFLARI

Kuranı kerimde Bakara 180 de"En güzel isimler Allah’ındır; bu güzel isimlerle O’na dua edin, O’nun isimleri hakkında doğru inançtan sap...