Bagian liris.

Bayangkan Anda telah menerapkan atau sedang menerapkan sistem tertentu yang seharusnya dapat diakses dari luar. Itu. ada server tertentu yang perlu Anda komunikasikan. Misalnya server web.

Server ini dapat melakukan banyak tindakan, bekerja dengan database, melakukan beberapa permintaan pihak ketiga ke server lain, melakukan beberapa perhitungan, dll. hidup dan mungkin berkembang sesuai dengan skenario yang diketahuinya (yaitu menurut skenario pengembang). Tidak menarik bagi seseorang untuk berkomunikasi dengan server seperti itu, karena dia mungkin tidak dapat/ingin menyediakan halaman indah dengan gambar dan konten ramah pengguna lainnya. Itu ditulis dan berfungsi untuk berfungsi dan menyediakan data ketika diminta, tanpa khawatir dapat dibaca manusia, klien akan menanganinya sendiri.

Sistem lain, yang mengakses server ini, sudah dapat membuang data yang diterima dari server ini atas kebijakannya sendiri - memproses, mengumpulkan, menerbitkannya ke klien mereka, dll.

Nah, salah satu opsi untuk berkomunikasi dengan server tersebut adalah SOAP. Protokol pertukaran pesan SOAP xml.

Bagian praktis.

Layanan web (ini adalah nama yang disediakan server dan digunakan klien) memungkinkan komunikasi dengan server dengan pesan yang terstruktur dengan jelas. Faktanya adalah layanan web tidak menerima data apa pun. Layanan web akan merespons dengan kesalahan terhadap pesan apa pun yang tidak mematuhi aturan. Omong-omong, kesalahannya juga akan dalam bentuk xml dengan struktur yang jelas (yang tidak benar tentang teks pesan).

WSDL (Bahasa Deskripsi Layanan Web). Aturan pembuatan pesan untuk layanan web juga dijelaskan menggunakan xml dan juga memiliki struktur yang jelas. Itu. Jika layanan web menyediakan kemampuan untuk memanggil suatu metode, itu harus memungkinkan klien mengetahui parameter apa yang digunakan untuk metode ini. Jika layanan web mengharapkan string untuk Metode1 sebagai parameter dan string tersebut harus diberi nama Param1, maka aturan ini akan ditentukan dalam deskripsi layanan web.

Tidak hanya tipe sederhana, tetapi objek dan kumpulan objek juga dapat dilewatkan sebagai parameter. Deskripsi suatu objek bermuara pada deskripsi setiap komponen objek tersebut. Jika suatu objek terdiri dari beberapa bidang, maka setiap bidang dijelaskan, jenisnya, namanya (berapa nilai yang mungkin). Bidang juga bisa bertipe kompleks, dan seterusnya hingga deskripsi tipe diakhiri dengan yang sederhana - string, boolean, angka, tanggal... Namun, beberapa tipe tertentu mungkin berubah menjadi sederhana, penting bagi klien dapat memahami nilai-nilai apa yang dikandungnya.

Untuk klien, cukup mengetahui url layanan web, wsdl akan selalu ada di dekatnya, dari situ Anda bisa mendapatkan gambaran tentang metode dan parameternya yang disediakan layanan web ini.

Apa keuntungan dari semua fitur ini:

  • Di sebagian besar sistem, deskripsi metode dan tipe terjadi secara otomatis. Itu. pemrogram di server hanya perlu mengatakan bahwa metode ini dapat dipanggil melalui layanan web, dan deskripsi wsdl akan dihasilkan secara otomatis.
  • Deskripsinya, yang memiliki struktur jelas, dapat dibaca oleh semua klien sabun. Itu. apapun layanan webnya, klien akan memahami data apa yang diterima layanan web. Dengan menggunakan deskripsi ini, klien dapat membangun struktur internal kelas objeknya sendiri, yang disebut. mengikat" dan. Akibatnya, pemrogram yang menggunakan layanan web harus menulis sesuatu seperti (kodesemu):

    Pengguna Baru:=TSoapUser.Create("Vasya","Pupkin","admin"); sabun.AddUser(Pengguna Baru);

  • Validasi otomatis.

    • validasi xml. xml harus terbentuk dengan baik. Xml tidak valid - segera terjadi kesalahan pada klien, biarkan dia menyelesaikannya.
    • validasi skema. xml harus memiliki struktur tertentu. xml tidak cocok dengan skema - segera kesalahan pada klien, biarkan dia menyelesaikannya.
    • Verifikasi data dilakukan oleh server sabun agar jenis data dan batasannya sesuai dengan deskripsi.
  • Otorisasi dan otentikasi dapat diimplementasikan menggunakan metode terpisah. secara asli. atau menggunakan otorisasi http.
  • Layanan web dapat bekerja melalui protokol sabun dan melalui http, yaitu melalui permintaan dapatkan. Artinya, jika parameternya adalah data sederhana (tanpa struktur), maka Anda cukup memanggil get www.site.com/users.asmx/GetUser?Name=Vasia atau post biasa. Namun, hal ini tidak terjadi di semua tempat dan tidak selalu.
  • ... lihat di Wikipedia

Ada juga banyak kelemahan:

  • Ukuran pesan yang terlalu besar. Nah, di sini sifat xml adalah formatnya mubazir, semakin banyak tag, semakin banyak informasi yang tidak berguna. Ditambah lagi sabun menambah redundansinya. Untuk sistem intranet, masalah lalu lintas tidak terlalu akut dibandingkan dengan internet, sehingga sabun untuk jaringan lokal lebih diminati, khususnya Sharepoint memiliki layanan web sabun yang dapat digunakan untuk berkomunikasi dengan sukses (dan beberapa keterbatasan).
  • Mengubah deskripsi layanan web secara otomatis dapat merusak semua klien. Ya, seperti ini pada sistem apa pun, jika kompatibilitas mundur dengan metode lama tidak didukung, semuanya akan gagal...
  • Bukan minusnya, tapi kekurangannya. Semua pemanggilan metode harus bersifat atomik. Misalnya, saat bekerja dengan database, kita bisa memulai transaksi, mengeksekusi beberapa query, lalu melakukan rollback atau commit. Tidak ada transaksi di sabun. Satu permintaan, satu jawaban, pembicaraan selesai.
  • Berurusan dengan deskripsi tentang apa yang ada di sisi server (apakah semuanya dijelaskan dengan benar?) dan apa yang ada di klien (apa yang dijelaskan kepada saya di sini?) bisa jadi cukup sulit. Ada beberapa kali saya harus berurusan dengan sisi klien dan meyakinkan pemrogram server bahwa datanya dijelaskan secara tidak benar, tetapi dia tidak dapat memahami apa pun tentang hal itu sama sekali, karena pembuatan otomatis dan dia tidak seharusnya melakukannya, ini masalah perangkat lunak. Dan kesalahannya, tentu saja, ada pada kode metode; pemrogram tidak melihatnya.
  • Praktek menunjukkan bahwa pengembang layanan web sangat jauh dari orang-orang yang menggunakan layanan web ini. Menanggapi permintaan apa pun (berlaku dari luar), kesalahan yang tidak dapat dipahami "Kesalahan 5. Semuanya buruk" mungkin muncul. Itu semua tergantung hati nurani pengembangnya :)
  • Aku yakin aku masih tidak ingat sesuatu...

Sebagai contoh, ada layanan web terbuka belavia:

  • http://86.57.245.235/TimeTable/Service.asmx - titik masuk, ada juga deskripsi teks tentang metode untuk pengembang pihak ketiga.
  • http://86.57.245.235/TimeTable/Service.asmx?WSDL - deskripsi wsdl tentang metode dan jenis data yang diterima dan dikembalikan.
  • http://86.57.245.235/TimeTable/Service.asmx?op=GetAirportsList - deskripsi metode tertentu dengan contoh jenis permintaan xml dan respons xml.

Anda dapat membuat dan mengirim permintaan secara manual seperti:

POST /TimeTable/Service.asmx HTTP/1.1 Host: 86.57.245.235 Tipe Konten: teks/xml; charset=utf-8 Panjang Konten: panjang SOAPATindakan: "http://webservices.belavia.by/GetAirportsList" en

jawabannya akan datang:

HTTP/1.1 200 OK Tanggal: Sen, 30 Sep 2013 00:06:44 GMT Server: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-Version: 4.0.30319 Kontrol Cache: pribadi, maks -age=0 Tipe Konten: teks/xml; charset=utf-8 Panjang Konten: 2940

PS Sebelumnya, layanan web Aeroflot dibuka, tetapi setelah 1C menambahkan dukungan sabun ke 8ku, sekelompok penguji beta 1C berhasil menginstalnya. Sekarang ada yang berubah di sana (saya tidak tahu alamatnya, Anda bisa mencarinya jika tertarik).
Penafian ZZY. Dia berbicara pada tingkat sehari-hari. Anda bisa menendang.

Halo semua!
Kebetulan baru-baru ini saya mulai mengembangkan layanan web. Tapi hari ini topiknya bukan tentang saya, tapi tentang bagaimana kita bisa menulis Layanan Web XML kita sendiri berdasarkan protokol SOAP 1.2.

Saya berharap setelah membaca topik ini Anda dapat:

  • tulis implementasi server Anda sendiri dari aplikasi web;
  • tulis implementasi aplikasi web klien Anda sendiri;
  • tulis deskripsi layanan web Anda sendiri (WSDL);
  • mengirim array klien dengan tipe data yang sama ke server.

Seperti yang sudah Anda duga, semua keajaiban akan dilakukan menggunakan PHP dan kelas SoapClient dan SoapServer bawaan. Kelinci kita akan menjadi layanan pengiriman pesan SMS.

1 Pernyataan masalah

1.1 Batasan

Pada awalnya, saya mengusulkan untuk memikirkan hasil yang akan kita capai di akhir topik. Seperti yang diumumkan di atas, kami akan menulis layanan untuk mengirim pesan SMS, dan lebih tepatnya, kami akan menerima pesan dari berbagai sumber melalui protokol SOAP. Setelah itu, kami akan mempertimbangkan dalam bentuk apa mereka tiba di server. Sayangnya, proses mengantri pesan untuk pengiriman lebih lanjut ke penyedia berada di luar cakupan postingan ini karena berbagai alasan.

1.2 Data apa yang akan kami ubah?

Bagus, kami telah memutuskan batasannya! Langkah selanjutnya yang perlu dilakukan adalah memutuskan data apa yang akan kita tukarkan antara server dan klien. Pada topik ini, saya menyarankan untuk tidak membelah rambut terlalu lama dan segera menjawab sendiri pertanyaan utama:

  • Data minimum apa yang harus dikirim ke server untuk mengirim pesan SMS ke pelanggan?
  • Data minimum apa yang harus dikirim dari server untuk memenuhi kebutuhan klien?

Sesuatu memberi tahu saya bahwa untuk ini Anda perlu mengirimkan yang berikut ini:

  • nomor ponsel dan
  • teks pesan SMS.

Prinsipnya kedua ciri tersebut cukup untuk dikirim, namun saya langsung membayangkan kasus SMS ucapan selamat ulang tahun datang kepada Anda pada jam 3 pagi, atau jam 4! Saat ini, saya akan sangat berterima kasih kepada semua orang karena tidak melupakan saya! Oleh karena itu, kami juga akan mengirimkan ke server dan

  • tanggal pengiriman pesan SMS.

Hal berikutnya yang ingin saya kirim ke server adalah:

  • Jenis pesan.

Parameter ini tidak wajib, tetapi bisa sangat berguna bagi kita jika kita perlu segera memberi tahu atasan kita berapa banyak klien kita yang “senang” dengan berita kita, dan juga menarik beberapa statistik bagus mengenai hal ini.

Namun, aku melupakan sesuatu! Jika kita merenungkan lebih jauh, perlu dicatat bahwa klien dapat mengirim satu pesan SMS atau beberapa pesan ke server sekaligus. Dengan kata lain, satu paket data dapat berisi pesan dari satu hingga tak terhingga.

Hasilnya, kami mendapatkan bahwa untuk mengirim pesan SMS kami memerlukan data berikut:

  • Nomor ponsel,
  • teks pesan SMS,
  • waktu pengiriman pesan SMS ke pelanggan,
  • jenis pesan.

Pertanyaan pertama sudah kita jawab, sekarang kita perlu menjawab pertanyaan kedua. Dan mungkin aku akan membiarkan diriku sedikit main-main. Oleh karena itu, dari server kami hanya akan mengirimkan data Boolean saja, yang artinya mempunyai arti sebagai berikut:

  • BENAR – paket berhasil sampai ke server, lolos otentikasi dan antri untuk dikirim ke penyedia SMS
  • SALAH – dalam semua kasus lainnya

Ini menyimpulkan uraian dari rumusan masalah! Dan terakhir, mari kita ke bagian yang menyenangkan - mari kita cari tahu makhluk aneh macam apa SOAP ini!

2 Apa itu SABUN?

Secara umum, awalnya saya tidak berencana untuk menulis apa pun tentang apa itu SOAP dan ingin membatasi diri pada link ke website w3.org dengan spesifikasi yang diperlukan, serta link ke Wikipedia. Namun pada akhirnya saya memutuskan untuk menulis catatan singkat tentang protokol ini.

Dan saya akan memulai cerita saya dengan fakta bahwa protokol pertukaran data ini termasuk dalam subset protokol berdasarkan apa yang disebut paradigma RPC (Remote Procedure Call), yang antipodenya adalah REST (Representational State Transfer). Anda dapat membaca lebih lanjut tentang ini di Wikipedia; tautan ke artikel ada di akhir topik. Dari artikel-artikel tersebut, kita perlu memahami hal-hal berikut: “Pendekatan RPC memungkinkan penggunaan sejumlah kecil sumber daya jaringan dengan sejumlah besar metode dan protokol yang kompleks. Dengan pendekatan REST, jumlah metode dan kompleksitas protokol menjadi sangat terbatas, yang berarti jumlah sumber daya individual bisa sangat besar.” Artinya, dalam kaitannya dengan kami, ini berarti bahwa di situs dalam kasus pendekatan RPC akan selalu ada satu input (link) ke layanan dan prosedur apa yang harus dipanggil untuk memproses data masuk yang kami kirimkan beserta datanya, sedangkan dengan pendekatan REST di situs kami memiliki banyak masukan (tautan), yang masing-masing hanya menerima dan memproses data tertentu. Jika ada yang membaca mengetahui cara menjelaskan perbedaan pendekatan ini dengan lebih sederhana, pastikan untuk menulis di komentar!

Hal berikutnya yang perlu kita ketahui tentang SOAP adalah bahwa protokol ini menggunakan XML yang sama dengan transport, yang di satu sisi sangat bagus karena Gudang senjata kami segera mencakup kekuatan penuh dari tumpukan teknologi berdasarkan bahasa markup ini, yaitu XML-Schema - bahasa untuk mendeskripsikan struktur dokumen XML (terima kasih Wikipedia!), yang memungkinkan validasi otomatis data yang diterima oleh server dari klien.

Jadi, sekarang kita tahu bahwa SOAP adalah protokol yang digunakan untuk mengimplementasikan panggilan prosedur jarak jauh dan menggunakan XML sebagai transportnya! Jika Anda membaca artikel di Wikipedia, Anda juga dapat mengetahui dari sana bahwa ini dapat digunakan pada protokol tingkat aplikasi apa pun, dan tidak hanya dikombinasikan dengan HTTP (sayangnya, dalam topik ini kami hanya akan membahas SOAP melalui HTTP). Dan tahukah Anda apa yang paling saya sukai dari semua ini? Jika tidak ada tebakan, maka saya akan memberikan petunjuk - SABUN!... Masih belum ada tebakan?... Apakah Anda yakin membaca artikel di Wikipedia?... Secara umum, saya tidak akan menyiksa Anda lebih jauh. Oleh karena itu, saya akan langsung ke jawabannya: “SOAP (dari bahasa Inggris Simple Object Access Protocol - sederhana protokol akses ke objek; hingga spesifikasi 1.2)". Hal yang paling luar biasa tentang baris ini adalah huruf miring! Saya tidak tahu kesimpulan apa yang Anda tarik dari semua ini, tetapi saya melihat yang berikut - karena protokol ini sama sekali tidak dapat disebut "sederhana" (dan tampaknya bahkan w3 setuju dengan ini), maka dari versi 1.2 entah bagaimana protokol itu berhenti didekripsi ! Dan itu dikenal sebagai SOAP, hanya SOAP, titik.

Baiklah, mohon maaf, kami mengesampingkannya sedikit. Seperti yang saya tulis sebelumnya, XML digunakan sebagai transportasi, dan paket yang melakukan perjalanan antara klien dan server disebut amplop SOAP. Jika Anda mempertimbangkan struktur umum amplop, itu akan tampak sangat familiar bagi Anda, karena... menyerupai markup halaman HTML. Ini memiliki bagian utama - Menyelimuti, yang mencakup bagian Tajuk Dan Tubuh, atau Kesalahan. DI DALAM Tubuh data dikirimkan dan itu adalah bagian wajib dari amplop, sementara Tajuk adalah opsional. DI DALAM Tajuk otorisasi atau data lain apa pun yang tidak terkait langsung dengan data masukan prosedur layanan web dapat dikirimkan. Pro Kesalahan tidak ada yang istimewa untuk diceritakan, kecuali bahwa hal itu datang ke klien dari server jika terjadi kesalahan.

Di sinilah cerita ulasan saya tentang protokol SOAP berakhir (kita akan melihat amplop itu sendiri dan strukturnya secara lebih rinci ketika klien dan server kami akhirnya belajar menjalankannya satu sama lain) dan yang baru dimulai - tentang pendamping SOAP yang disebut WSDL(Bahasa Deskripsi Layanan Web). Ya, ya, inilah hal yang membuat sebagian besar dari kita takut untuk mencoba mengimplementasikan API kami pada protokol ini. Akibatnya, kami biasanya menemukan kembali roda kami dengan JSON sebagai transportasi. Jadi apa itu WSDL? WSDL adalah bahasa untuk mendeskripsikan layanan web dan mengaksesnya, berdasarkan bahasa XML (c) Wikipedia. Jika definisi ini tidak menjelaskan kepada Anda seluruh makna sakral dari teknologi ini, maka saya akan mencoba menjelaskannya dengan kata-kata saya sendiri!

WSDL dirancang untuk memungkinkan klien kami berkomunikasi secara normal dengan server. Untuk melakukan ini, file dengan ekstensi “*.wsdl” menjelaskan informasi berikut:

  • Namespace apa yang digunakan?
  • Skema data apa yang digunakan?
  • Jenis pesan apa yang diharapkan layanan web dari klien?
  • Data mana yang termasuk dalam prosedur layanan web mana,
  • Prosedur apa yang terkandung dalam layanan web?
  • Bagaimana seharusnya klien memanggil prosedur layanan web,
  • Ke alamat mana panggilan pelanggan harus dikirim?

Seperti yang Anda lihat, file ini adalah keseluruhan layanan web. Dengan menentukan alamat file WSDL di klien, kita akan mengetahui segalanya tentang layanan web apa pun! Oleh karena itu, kita tidak perlu mengetahui apa pun tentang lokasi layanan web itu sendiri. Yang perlu Anda ketahui hanyalah lokasi file WSDL-nya! Kita akan segera mengetahui bahwa SOAP tidak seseram peribahasa Rusia.

3 Pengantar Skema XML

Sekarang kita tahu banyak tentang apa itu SOAP, apa yang ada di dalamnya, dan gambaran umum tentang tumpukan teknologi yang mengelilinginya. Karena, pertama-tama, SOAP adalah metode interaksi antara klien dan server, dan bahasa markup XML digunakan sebagai transportasinya, di bagian ini kita akan memahami sedikit tentang bagaimana validasi data otomatis terjadi menggunakan skema XML.

Tugas utama diagram adalah menggambarkan struktur data yang akan kita proses. Semua data dalam skema XML dibagi menjadi sederhana(skalar) dan kompleks(struktur) jenis. Tipe sederhana meliputi tipe berikut:

  • garis,
  • nomor,
  • nilai boolean,
  • tanggal.

Sesuatu yang sangat sederhana yang tidak memiliki ekstensi di dalamnya. Antipode mereka adalah tipe kompleks yang kompleks. Contoh paling sederhana dari tipe kompleks yang terlintas di benak setiap orang adalah objek. Misalnya, sebuah buku. Buku ini terdiri dari properti: pengarang, Nama, harga, nomor ISBN dll. Dan properti ini, pada gilirannya, dapat berupa tipe sederhana dan kompleks. Dan tugas skema XML adalah menjelaskan hal ini.

Saya sarankan untuk tidak pergi jauh dan menulis skema XML untuk pesan SMS kita! Di bawah ini adalah deskripsi xml dari pesan SMS:

71239876543 Pesan tes 20-07-2013T12:00:00 12

Diagram tipe kompleks kita akan terlihat seperti ini:

Entri ini berbunyi sebagai berikut: Kami memiliki variabel " pesan" jenis " Pesan" dan ada tipe kompleks yang disebut " Pesan", yang terdiri dari sekumpulan elemen yang berurutan" telepon" jenis rangkaian, « teks" jenis rangkaian, « tanggal" jenis tanggal Waktu, « jenis" jenis desimal. Tipe ini sederhana dan sudah ditentukan dalam deskripsi skema. Selamat! Kami baru saja menulis Skema XML pertama kami!

Menurutku itu arti dari unsur-unsurnya" elemen" Dan " Tipe kompleks"Semuanya menjadi lebih atau kurang jelas bagi Anda, jadi kami tidak akan fokus pada hal itu lagi dan langsung beralih ke elemen komposer" urutan". Saat kita menggunakan elemen komposer " urutan“Kami informasikan bahwa unsur-unsur yang termasuk di dalamnya harus selalu ditempatkan menurut urutan yang ditentukan dalam diagram, dan semuanya wajib. Tapi jangan putus asa! Ada dua elemen komposer lagi dalam skema XML: " pilihan" Dan " semua". Komposer" pilihan" mengumumkan bahwa harus ada salah satu unsur yang tercantum di dalamnya, dan penciptanya " semua» – kombinasi apa pun dari elemen yang terdaftar.

Seperti yang Anda ingat, di bagian pertama topik kami sepakat bahwa pesan SMS dari satu hingga tak terbatas dapat dikirimkan dalam satu paket. Oleh karena itu, saya mengusulkan untuk memahami bagaimana data tersebut dideklarasikan dalam skema XML. Struktur paket umum mungkin terlihat seperti ini:

71239876543 Pesan tes 1 20-07-2013T12:00:00 12 71239876543 Pesan uji N 20-07-2013T12:00:00 12

Diagram untuk tipe yang rumit akan terlihat seperti ini:

Blok pertama berisi deklarasi familiar dari tipe kompleks “ Pesan". Jika Anda perhatikan, maka di setiap tipe sederhana termasuk dalam " Pesan", atribut klarifikasi baru telah ditambahkan" menitTerjadi" Dan " maxTerjadi". Seperti yang Anda duga dari namanya, yang pertama ( menitTerjadi) menunjukkan bahwa urutan ini harus mengandung setidaknya satu elemen bertipe " telepon», « teks», « tanggal" Dan " jenis", sedangkan yang berikutnya ( maxTerjadi) atribut menyatakan kepada kita bahwa ada paling banyak satu elemen seperti itu dalam urutan kita. Hasilnya, saat kita menulis skema kita sendiri untuk data apa pun, kita diberikan pilihan terluas tentang cara mengonfigurasinya!

Blok kedua diagram mendeklarasikan elemen " Daftar pesan" jenis " Daftar Pesan". Jelas bahwa" Daftar Pesan" adalah tipe kompleks yang mengandung setidaknya satu elemen " pesan", tetapi jumlah maksimum elemen tersebut tidak dibatasi!

4 Tulis WSDL Anda

Apakah Anda ingat bahwa WSDL adalah layanan web kami? Saya harap Anda ingat! Saat kami menulisnya, layanan web kecil kami akan berjalan di sana. Oleh karena itu, saya sarankan untuk tidak main-main.

Secara umum, agar semuanya berfungsi dengan benar, kita perlu mentransfer file WSDL dengan tipe MIME yang benar ke klien. Untuk melakukan ini, Anda perlu mengkonfigurasi server web Anda, yaitu mengatur jenis MIME untuk file dengan ekstensi “*.wsdl” ke baris berikut:

Aplikasi/wsdl+xml

Namun pada praktiknya, saya biasanya mengirimkan header HTTP melalui PHP" teks/xml»:

Header("Tipe Konten: teks/xml; charset=utf-8");

dan semuanya bekerja dengan baik!

Saya ingin segera memperingatkan Anda bahwa layanan web sederhana kami akan memiliki deskripsi yang cukup mengesankan, jadi jangan khawatir, karena... Sebagian besar teks adalah air wajib dan, setelah menulisnya sekali, Anda dapat terus menyalinnya dari satu layanan web ke layanan web lainnya!

Karena WSDL adalah XML, Anda perlu menulisnya langsung di baris pertama. Elemen root dari file harus selalu disebut " definisi»:

Biasanya WSDL terdiri dari 4-5 blok utama. Blok pertama adalah definisi layanan web atau, dengan kata lain, titik masuk.

Di sini dikatakan bahwa kami memiliki layanan yang disebut - “ Layanan Sms". Prinsipnya semua nama yang ada di file WSDL bisa Anda ubah sesuai keinginan Anda, karena mereka sama sekali tidak berperan.

Setelah ini kami mengumumkannya di layanan web kami " Layanan Sms"ada titik masuk ("pelabuhan") yang disebut " SmsServicePort". Ke titik masuk inilah semua permintaan dari klien ke server akan dikirim. Dan tunjukkan pada elemen “ alamat» tautan ke file pengendali yang akan menerima permintaan.

Setelah kita mendefinisikan layanan web dan menentukan titik masuknya, kita perlu mengikat prosedur yang didukung ke layanan tersebut:

Untuk melakukan ini, ia mencantumkan operasi mana dan dalam bentuk apa operasi tersebut akan dipanggil. Itu. untuk pelabuhan " SmsServicePort" pengikatan didefinisikan dengan nama " SmsServiceBinding", yang memiliki tipe panggilan " rpc"dan HTTP digunakan sebagai protokol transmisi. Jadi, kami menunjukkan di sini bahwa kami akan melakukan panggilan RPC melalui HTTP. Setelah ini kami menjelaskan prosedur mana ( operasi) didukung di layanan web. Kami hanya akan mendukung satu prosedur – “ Kirim SMS". Melalui prosedur ini pesan luar biasa kami akan dikirim ke server! Setelah prosedur diumumkan, perlu ditunjukkan dalam bentuk apa data akan dikirimkan. Dalam hal ini, diindikasikan bahwa amplop SOAP standar akan digunakan.

Setelah itu, kita perlu mengikat prosedur ke pesan:

Untuk melakukan ini, kami menentukan bahwa pengikatan kami bertipe " SmsServicePortType" dan di dalam elemen " tipe port"dengan nama jenis yang sama, kami menunjukkan pengikatan prosedur ke pesan. Jadi, pesan masuk (dari klien ke server) akan diberi nama “ kirimSmsRequest", dan keluar (dari server ke klien)" kirimSmsResponse". Seperti semua nama di WSDL, nama pesan masuk dan keluar bersifat arbitrer.

Sekarang kita perlu mendeskripsikan pesan-pesan itu sendiri, yaitu. masuk dan keluar:

Untuk melakukan ini kami menambahkan elemen " pesan"dengan nama" kirimSmsRequest" Dan " kirimSmsResponse" masing-masing. Di dalamnya kami menunjukkan bahwa masukan harus berupa amplop yang strukturnya sesuai dengan tipe data " Meminta". Setelah itu sebuah amplop dikembalikan dari server yang berisi tipe data - “ Tanggapan».

Sekarang kita hanya perlu melakukan sedikit - tambahkan deskripsi tipe ini ke file WSDL kita! Dan menurut Anda bagaimana WSDL menggambarkan data masuk dan keluar? Saya rasa Anda sudah memahami semuanya sejak lama dan berkata pada diri sendiri bahwa menggunakan skema XML! Dan Anda benar sekali!

Anda dapat memberi selamat kepada kami! WSDL pertama kami telah ditulis! Dan kami selangkah lebih dekat untuk mencapai tujuan kami.
Selanjutnya, kita akan melihat apa yang disediakan PHP untuk mengembangkan aplikasi terdistribusi kita sendiri.

5 Server SOAP pertama kami

Sebelumnya saya menulis bahwa untuk membuat server SOAP di PHP kita akan menggunakan kelas SoapServer bawaan. Agar semua tindakan selanjutnya terjadi dengan cara yang sama seperti saya, Anda perlu sedikit mengubah PHP Anda. Untuk lebih tepatnya, Anda perlu memastikan bahwa Anda telah menginstal ekstensi “php-soap”. Cara menginstalnya di server web Anda sebaiknya dibaca di situs resmi PHP (lihat daftar referensi).

Setelah semuanya terinstal dan dikonfigurasi, kita perlu membuat file di folder root hosting Anda “ smsservice.php» dengan isi sebagai berikut:

setClass("SoapSmsGateWay"); //Mulai server $server->handle();

Saya harap tidak perlu menjelaskan apa yang ada di atas baris dengan fungsi “ini_set”. Karena disana ditentukan header HTTP mana yang akan kita kirim dari server ke klien dan lingkungan dikonfigurasi. Sejalan dengan “ini_set” kami menonaktifkan caching file WSDL sehingga perubahan kami di dalamnya segera diterapkan pada klien.

Sekarang kita sampai pada server! Seperti yang Anda lihat, seluruh server SOAP hanya membutuhkan tiga baris! Pada baris pertama, kita membuat instance baru dari objek SoapServer dan meneruskan alamat deskripsi WSDL layanan web kita ke konstruktornya. Sekarang kita tahu bahwa itu akan ditempatkan di root hosting dalam file dengan nama yang cukup jelas “ smsservice.wsdl.php". Pada baris kedua, kami memberi tahu server SOAP kelas mana yang perlu ditarik untuk memproses amplop yang diterima dari klien dan mengembalikan amplop beserta responsnya. Seperti yang sudah Anda duga, di kelas inilah satu-satunya metode kami akan dijelaskan Kirim SMS. Di baris ketiga kita memulai server! Itu saja, server kami sudah siap! Dengan itu saya mengucapkan selamat kepada kita semua!

Sekarang kita perlu membuat file WSDL. Untuk melakukan ini, Anda cukup menyalin isinya dari bagian sebelumnya, atau mengambil kebebasan dan "membuat template" sedikit:

"; ?> /" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http:// skema.xmlsoap.org/wsdl/http/" name="SmsWsdl" xmlns="http://schemas.xmlsoap.org/wsdl/"> /"> /smsservice.php" />

Pada tahap ini, kita harus benar-benar puas dengan server yang dihasilkan, karena Kita dapat mencatat amplop yang masuk dan kemudian dengan tenang menganalisis data yang masuk. Agar kami dapat menerima apa pun di server, kami memerlukan klien. Jadi mari kita mulai!

6 klien SOAP dalam perjalanan

Pertama-tama, kita perlu membuat file di mana kita akan menulis klien. Seperti biasa, kami akan membuatnya di root host dan menyebutnya " klien.php", dan di dalamnya kami akan menulis yang berikut:

DaftarPesan = DaftarPesan baru(); $req->messageList->message = Pesan baru(); $req->daftar pesan->pesan->telepon = "79871234567"; $req->messageList->message->text = "Uji pesan 1"; $req->messageList->message->date = "21-07-2013T15:00:00.26"; $req->daftar pesan->pesan->tipe = 15; $klien = new SoapClient("http://($_SERVER["HTTP_HOST"])/smsservice.wsdl.php", array("soap_version" => SOAP_1_2)); var_dump($klien->sendSms($req));

Mari kita gambarkan objek kita. Saat kami menulis WSDL, ia menjelaskan tiga entitas untuk amplop yang masuk ke server: Meminta, Daftar Pesan Dan Pesan. Oleh karena itu kelas Meminta, Daftar Pesan Dan Pesan adalah refleksi dari entitas ini dalam skrip PHP kami.

Setelah kita mendefinisikan objek, kita perlu membuat objek ( $permintaan), yang akan kami kirimkan ke server. Setelah itu muncullah dua kalimat yang paling kami hargai! Klien SOAP kami! Percaya atau tidak, ini cukup bagi server kami untuk mulai menerima pesan dari klien, serta server kami berhasil menerima dan memprosesnya! Yang pertama, kami membuat instance kelas SoapClient dan meneruskan alamat lokasi file WSDL ke konstruktornya, dan dalam parameter kami secara eksplisit menunjukkan bahwa kami akan bekerja menggunakan protokol SOAP versi 1.2. Pada baris berikutnya kita memanggil metodenya Kirim SMS obyek $klien dan segera tampilkan hasilnya di browser.
Mari kita jalankan dan lihat apa yang akhirnya kita dapatkan!

Objek berikut dikembalikan kepada saya dari server:

Objek(stdClass) public "status" => boolean benar

Dan ini bagus, karena... Sekarang kita tahu pasti bahwa server kita berfungsi dan tidak hanya berfungsi, tetapi juga dapat mengembalikan beberapa nilai ke klien!

Sekarang mari kita lihat log yang kita simpan dengan hati-hati di sisi server! Pada bagian pertama kita melihat data mentah yang sampai di server:

79871234567 Pesan tes 1 21-07-2013T15:00:00.26 15

Ini amplopnya. Sekarang Anda tahu seperti apa bentuknya! Namun kecil kemungkinannya kita akan tertarik untuk melihatnya terus-menerus, jadi mari kita deserialisasi objek dari file log dan lihat apakah semuanya baik-baik saja:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "phone" => string "79871234567" (panjang=11) public "text" => string "Uji pesan 1 " (panjang=37) public "date" => string "21-07-2013T15:00:00.26" (panjang=22) public "type" => string "15" (panjang=2)

Seperti yang Anda lihat, objek telah dideserialisasi dengan benar, dan saya ingin mengucapkan selamat kepada kita semua! Sesuatu yang lebih menarik menanti kita selanjutnya! Yaitu, kami akan mengirim klien ke server tidak hanya satu pesan SMS, tetapi seluruh paket (lebih tepatnya, tiga)!

7 Mengirim objek yang kompleks

Mari kita pikirkan bagaimana kita dapat mentransfer sejumlah besar pesan ke server dalam satu paket? Mungkin cara termudah adalah dengan mengatur array di dalam elemen messageList! Mari kita lakukan:

// membuat objek untuk dikirim ke server $req = new Request(); $req->daftarpesan = DaftarPesan baru(); $msg1 = Pesan baru(); $pesan1->telepon = "79871234567"; $msg1->text = "Uji pesan 1"; $msg1->tanggal = "21-07-2013T15:00:00.26"; $pesan1->ketik = 15; $msg2 = Pesan baru(); $pesan2->telepon = "79871234567"; $msg2->text = "Uji pesan 2"; $msg2->tanggal = "22-08-2014T16:01:10"; $pesan2->ketik = 16; $msg3 = Pesan baru(); $pesan3->telepon = "79871234567"; $msg3->text = "Uji pesan 3"; $msg3->tanggal = "22-08-2014T16:01:10"; $pesan3->ketik = 17; $permintaan->daftarpesan->pesan = $pesan1; $permintaan->daftarpesan->pesan = $pesan2; $permintaan->daftarpesan->pesan = $pesan3;

Log kami menunjukkan bahwa paket berikut diterima dari klien:

79871234567 Pesan tes 1 21-07-2013T15:00:00.26 15 79871234567 Pesan tes 2 22-08-2014T16:01:10 16 79871234567 Pesan tes 3 22-08-2014T16:01:10 17

Omong kosong apa, katamu? Dan Anda akan benar dalam arti tertentu, karena... Segera setelah kami mengetahui bahwa suatu objek meninggalkan klien, objek tersebut datang ke server kami dalam bentuk yang sama persis dalam bentuk amplop. Benar, pesan SMS tidak diserialkan dalam XML seperti yang kami butuhkan - pesan tersebut harus dibungkus dalam beberapa elemen pesan, tidak masuk Struktur. Sekarang mari kita lihat dalam bentuk apa objek tersebut masuk ke dalam metode Kirim SMS:

Objek(stdClass) publik "daftar pesan" => objek(stdClass) publik "pesan" => objek(stdClass) publik "Struct" => array (ukuran=3) 0 => objek(stdClass) publik "telepon" => string "79871234567" (panjang=11) public "text" => string "Uji pesan 1" (panjang=37) public "date" => string "21-07-2013T15:00:00.26" (panjang=22) public " type" => string "15" (panjang=2) 1 => objek(stdClass) public "phone" => string "79871234567" (panjang=11) public "text" => string "Uji pesan 2" (panjang= 37) public "date" => string "22-08-2014T16:01:10" (panjang=19) public "type" => string "16" (panjang=2) 2 => objek(stdClass) public "telepon " => string "79871234567" (panjang=11) public "text" => string "Uji pesan 3" (panjang=37) public "tanggal" => string "22-08-2014T16:01:10" (panjang= 19) publik "tipe" => string "17" (panjang=2)

Apa yang diberikan pengetahuan ini kepada kita? Hanya saja jalur yang kami pilih tidak benar dan kami belum menerima jawaban atas pertanyaan - “Bagaimana kami bisa mendapatkan struktur data yang benar di server?” Tapi saya menyarankan untuk tidak putus asa dan mencoba mengubah array kita menjadi tipe tersebut Sebuah Objek:

$req->messageList->message = (objek)$req->messageList->message;

Dalam hal ini, kami akan menerima amplop lain:

79871234567 Pesan tes 1 21-07-2013T15:00:00.26 15 79871234567 Pesan tes 2 22-08-2014T16:01:10 16 79871234567 Pesan tes 3 22-08-2014T16:01:10 17

Masuk ke dalam metodenya Kirim SMS objek tersebut memiliki struktur sebagai berikut:

Objek(stdClass) public "messageList" => objek(stdClass) public "message" => objek(stdClass) public "BOGUS" => array (ukuran=3) 0 => objek(stdClass) public "phone" => string "79871234567" (panjang=11) public "text" => string "Uji pesan 1" (panjang=37) public "date" => string "21-07-2013T15:00:00.26" (panjang=22) public " type" => string "15" (panjang=2) 1 => objek(stdClass) public "phone" => string "79871234567" (panjang=11) public "text" => string "Uji pesan 2" (panjang= 37) public "date" => string "22-08-2014T16:01:10" (panjang=19) public "type" => string "16" (panjang=2) 2 => objek(stdClass) public "telepon " => string "79871234567" (panjang=11) public "text" => string "Uji pesan 3" (panjang=37) public "tanggal" => string "22-08-2014T16:01:10" (panjang= 19) publik "tipe" => string "17" (panjang=2)

Bagi saya, “jumlahnya tidak berubah dengan perubahan tempat istilah” (c). Apa PALSU, Apa Struktur– kami belum mencapai tujuan kami! Dan untuk mencapainya, kita perlu memastikan bahwa alih-alih nama-nama yang tidak dapat dipahami ini, nama asli kita yang ditampilkan pesan. Namun penulis belum mengetahui bagaimana cara mencapainya. Oleh karena itu, satu-satunya hal yang dapat kita lakukan adalah membuang wadah tambahan tersebut. Dengan kata lain, sekarang kami akan memastikannya pesan menjadi PALSU! Untuk melakukan ini, ubah objek sebagai berikut:

// membuat objek untuk dikirim ke server $req = new Request(); $msg1 = Pesan baru(); $pesan1->telepon = "79871234567"; $msg1->text = "Uji pesan 1"; $msg1->tanggal = "21-07-2013T15:00:00.26"; $pesan1->ketik = 15; $msg2 = Pesan baru(); $pesan2->telepon = "79871234567"; $msg2->text = "Uji pesan 2"; $msg2->tanggal = "22-08-2014T16:01:10"; $pesan2->ketik = 16; $msg3 = Pesan baru(); $pesan3->telepon = "79871234567"; $msg3->text = "Uji pesan 3"; $msg3->tanggal = "22-08-2014T16:01:10"; $pesan3->ketik = 17; $permintaan->daftarpesan = $pesan1; $permintaan->daftarpesan = $pesan2; $permintaan->daftarpesan = $pesan3; $req->messageList = (objek)$req->messageList;

Bagaimana jika kita beruntung dan nama yang benar muncul dari diagram? Untuk melakukan ini, mari kita lihat amplop yang tiba:

79871234567 Pesan tes 1 21-07-2013T15:00:00.26 15 79871234567 Pesan tes 2 22-08-2014T16:01:10 16 79871234567 Pesan tes 3 22-08-2014T16:01:10 17

Ya, keajaiban tidak terjadi! PALSU– kami tidak akan menang! Datang ke Kirim SMS objek dalam hal ini akan terlihat seperti ini:

Objek(stdClass) public "messageList" => objek(stdClass) public "BOGUS" => array (ukuran=3) 0 => objek(stdClass) public "phone" => string "79871234567" (panjang=11) public " text" => string "Uji pesan 1" (panjang=37) public "date" => string "21-07-2013T15:00:00.26" (panjang=22) public "type" => string "15" (panjang =2) 1 => objek(stdClass) public "phone" => string "79871234567" (panjang=11) public "text" => string "Uji pesan 2" (panjang=37) public "date" => string " 22-08-2014T16:01:10" (panjang=19) public "type" => string "16" (panjang=2) 2 => objek(stdClass) public "phone" => string "79871234567" (panjang= 11) public "text" => string "Uji pesan 3" (panjang=37) public "date" => string "22-08-2014T16:01:10" (panjang=19) public "type" => string " 17" (panjang=2)

Seperti yang mereka katakan – “Hampir”! Pada catatan (yang sedikit menyedihkan) ini, saya mengusulkan untuk secara perlahan menyelesaikan semuanya dan menarik beberapa kesimpulan untuk diri kita sendiri.

8 Kesimpulan

Akhirnya kami tiba di sini! Mari kita cari tahu apa yang dapat Anda lakukan sekarang:

  • Anda dapat menulis file WSDL yang diperlukan untuk layanan web Anda;
  • Anda dapat dengan mudah menulis klien Anda sendiri yang dapat berkomunikasi dengan server melalui SOAP;
  • Anda dapat menulis server Anda sendiri yang berkomunikasi dengan dunia luar melalui SOAP;
  • Anda dapat mengirim array dengan tipe objek yang sama ke server dari klien Anda (dengan beberapa batasan).

Kami juga membuat beberapa penemuan selama penelitian kecil kami:

  • kelas SoapClient asli tidak membuat serial struktur data bertipe sama dalam XML dengan benar;
  • ketika membuat serial array ke XML, ia menciptakan elemen tambahan yang disebut Struktur;
  • ketika membuat serial suatu objek ke XML, ia menciptakan elemen tambahan yang disebut PALSU;
  • PALSU kurang jahat dari Struktur karena amplopnya lebih ringkas (ruang nama tambahan tidak ditambahkan ke header XML amplop);
  • Sayangnya, kelas SoapServer tidak secara otomatis memvalidasi data amplop dengan skema XML kami (mungkin server lain juga tidak melakukan hal ini).

Di sini, di LeaseWeb, kami banyak bekerja dengan layanan web SOAP untuk mengintegrasikan aplikasi internal kami satu sama lain. Terutama selama pengembangan dan pengujian aplikasi kami karena kami memerlukan kemampuan untuk berlatih dengan SOAP API.

$ curl -sS http://leaseweb.github.io/php-soap-client/installer | php

Ini akan mengunduh file phar ke direktori kerja saat ini dan membuatnya dapat dieksekusi sehingga Anda dapat mulai menggunakannya segera dengan menjalankan:

$ ./soap_client

Untuk menginstal versi master terbaru Anda bisa mendapatkan kode sumber langsung dari GitHub, mengemas file .phar Anda sendiri dan menginstalnya - menggunakan GNU Make.
Untuk dapat membuat file .phar Anda harus menginstal composer. Untuk membaca lebih lanjut tentang komposer, lihat dokumentasi mereka yang sangat bagus.

# Instal klien sabun php $ git clone https://github.com/LeaseWeb/php-soap-client.git $ cd php-soap-client $ composer.phar install $ make $ sudo make install

Jika Anda mendapatkan pengecualian Gagal mengkompilasi phar saat menjalankan make Anda perlu mengatur phar.readonly = Off di php.ini Anda. Pada mesin pengembangan, hal ini boleh dilakukan tetapi harap waspada terhadap risiko keamanan saat menyetel phar.readonly ke Off .

Perintah make install di atas akan menginstal aplikasi sabun_client ke /usr/local/bin dan membuatnya dapat dieksekusi sehingga Anda dapat dengan mudah memanggilnya seperti ini:

$ sabun_client php-soap-client versi 2.1.3 Penggunaan: perintah Opsi: ... Perintah yang tersedia: panggilan Panggil layanan jarak jauh dengan `metode` yang ditentukan dan keluarkan respons ke stdout. help Menampilkan bantuan untuk daftar perintah Daftar perintah daftar-metode Dapatkan daftar metode yang tersedia untuk dipanggil pada remote. permintaan Hasilkan permintaan SOAP berformat xml untuk metode tertentu dan output ke stdout. wsdl Dapatkan WSDL dari layanan sabun.

Mulai saat ini dan seterusnya kami asumsikan Anda telah menginstal sabun_client.phar pada sistem Anda di /usr/local/bin/soap_client dan direktori /urs/local/bin ada di $PATH Anda.

Katakanlah kita ingin melihat metode apa yang tersedia pada layanan jarak jauh http://www.webservicex.net/ConvertTemperature.asmx. Kita bisa mengeluarkan perintah berikut:

$ sabun_client --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" metode daftar

Yang akan menampilkan yang berikut:

KonversiTemp

Jika Anda menjalankan perintah di atas dengan opsi -vvv Anda akan mendapatkan keluaran yang lebih panjang.
Dalam hal ini satu-satunya metode yang tersedia adalah ConvertTemp . Mari kita lihat seperti apa permintaan SOAP XML untuk metode ini:

$ sabun_client --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" permintaan ConvertTemp 0

Jika Anda ingin membuat permintaan SOAP ke metode ConvertTemp pada layanan jarak jauh gunakan perintah call sub:

$ sabun_client --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" panggilan --editor ConvertTemp

Perhatikan opsi --editor setelah perintah panggilan sub. Jika Anda menggunakan tanda --editor, sabun_klien akan membuka editor yang ditentukan dalam variabel lingkungan Anda $EDITOR sehingga Anda dapat mengubah XML permintaan sebelum mengirimnya.

Jika Anda mengeluarkan permintaan yang sama beberapa kali, Anda bisa menyimpan permintaan sabun sebagai file XML lokal dan meneruskannya ke /dev/stdin dari perintah panggilan sabun_client:

# Dapatkan permintaan xml dan simpan secara lokal $ sabun_client --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" permintaan ConvertTemp > my_sample_request.xml # Sekarang edit my_sample_request.xml # Sekarang Anda dapat memanggil Metode ConvertTemp dengan permintaan yang telah disiapkan sebelumnya $soap_client --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" panggil ConvertTemp< my_sample_request.xml

Karena Anda akan sering mengulangi perintah sabun_client dalam waktu singkat saat menjelajahi layanan web jarak jauh, Anda dapat menghemat waktu dengan menyetel variabel lingkungan SOAPCLIENT_ENDPOINT yang berisi URL ke WSDL. Ketika variabel lingkungan ini disetel, Anda dapat menghilangkan opsi baris perintah --endpoint. Mari lakukan ini sekarang dan panggil metode ConvertTemp:

$ ekspor SOAPCLIENT_ENDPOINT="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" $ sabun_klien panggilan ConvertTemp< my_sample_request.xml

Saya ingin tahu berapa 107,6 derajat Fahrenheit dalam Celcius, jadi my_sample_request.xml saya berisi:

$ kucing my_sample_request.xml 107.6 derajatFahrenheit derajat Celsius

$ sabun_klien panggilan ConvertTemp< my_sample_request.xml stdClass Object ( => 42)

Jawabannya adalah 42.

Jika Anda lebih suka melihat respons dalam format XML, Anda dapat menggunakan opsi baris perintah --xml:

$ sabun_klien panggilan --xml ConvertTemp< my_sample_request.xml 42

Tutorial ini akan memberi Anda informasi yang cukup untuk mulai menjelajahi, menguji dan/atau mengembangkan SOAP API.
Pada postingan blog selanjutnya, saya akan melanjutkan topik klien sabun php. Kami sedang berupaya mengemas arsip .phar untuk web.

Saya tidak akan memikirkan pertanyaan tentang apa itu Layanan web dan mengapa mereka dibutuhkan. Ada banyak artikel tentang topik ini di Internet. Saya hanya akan mencoba menunjukkan secara singkat betapa mudahnya membuat klien untuk layanan web apa pun di php.

Pengaturan

Untuk digunakan SABUN MANDI di php Anda perlu menghubungkan modul SOAP (termasuk dalam distribusi php5). Di Windows, ini dilakukan secara sederhana - Anda perlu menambahkan (yaitu menambahkan, karena baris ini tidak hanya dikomentari di luar sana, tetapi juga hilang sama sekali) di php.ini:
ekstensi=php_soap.dll

Jangan lupa untuk me-restart server jika Anda telah menginstal php sebagai modul.


Membuat klien SOAP dari dokumen WSDL

Pembuatan klien SOAP biasanya dilakukan dengan dokumen WSDL, yaitu dokumen XML dalam format tertentu yang menjelaskan secara lengkap layanan web tertentu. Untuk detail tentang WSDL, saya merujuk Anda ke situs web konsorsium W3C - http://www.w3.org/TR/2005/WD-wsdl20-soap11-binding-20050510/.

Hal utama yang perlu Anda ketahui untuk membangun klien untuk layanan web adalah mengetahui URL dokumen WSDL-nya.
Sebagai contoh, mari kita ambil layanan web "Nilai Tukar Mata Uang" dari xmethods.com. Alamat layanan web ini, yang memungkinkan Anda menerima nilai tukar secara online, adalah http://www.xmethods.net/sd/2001/CurrencyExchangeService.wsdl.

Poin penting kedua adalah dari deskripsi layanan web perlu diperoleh informasi tentang metode apa yang disediakan layanan ini, dan parameter apa yang harus kita berikan sebagai nilai input (sangat mirip dengan memanggil fungsi atau kelas PHP biasa metode). Biasanya informasi ini terdapat dalam deskripsi layanan di situs webnya. Layanan web kami untuk mendapatkan nilai tukar menyediakan metode getRate(), yang mana kode mata uang diteruskan sebagai argumen.

Dan terakhir, penting untuk mengetahui apa yang diharapkan sebagai jawaban: berapa banyak nilai, jenis apa, dll. Ini juga bisa didapat dari deskripsinya.
Dan hasilnya, kodenya menjadi sangat sederhana dan ringkas, hampir mendasar:

// Menggunakan layanan Web
// "Nilai Tukar Mata Uang" dari xmethods.com

// Membuat klien SOAP dari dokumen WSDL
$klien = new SoapClient("http://www.xmethods.net/sd/2001/CurrencyExchangeService.wsdl");

// Kirim permintaan SOAP dan terima hasilnya
$hasil = $klien->getRate("kita", "rusia");

Echo 'Nilai tukar dolar saat ini: ', $result, 'rubel';
?>

Seperti yang Anda lihat dari kode, Anda perlu meneruskan URL dokumen WSDL ke konstruktor kelas SoapClient dan membuat objek berfungsi dengan layanan web yang diinginkan. Kemudian metode objek ini dipanggil, yang namanya sesuai dengan nama metode layanan web itu sendiri. Metode ini mengembalikan hasil yang kita inginkan.

Jadi, contoh sederhana ini menggambarkan prinsip membangun klien SOAP untuk layanan web di php. Namun dalam aplikasi nyata, masih banyak hal yang harus diperhatikan, khususnya pada saat mengakses layanan web, mungkin untuk sementara tidak tersedia atau menghasilkan kesalahan. Ini jelas menyarankan penggunaan blok coba/tangkap/lempar :)

Terjemahan Brett McLaughlin oleh Ilya Chekmenev

SOAP adalah Protokol Akses Objek Sederhana. Jika Anda belum pernah mendengar tentang dia sebelumnya, maka Anda harus tinggal di suatu hutan belantara, jauh dari peradaban. Ini telah menjadi mode terkini dalam pemrograman web, dan merupakan bagian integral dari layanan web yang digunakan dengan fanatisme dalam pengembangan web generasi terbaru. Jika Anda pernah mendengar tentang Microsoft .NET, atau "revolusi" peer-to-peer, Anda pasti pernah mendengar tentang teknologi berbasis SOAP (walaupun Anda tidak tahu apa itu). Tidak ada satu pun, tapi dua implementasi SOAP, dari Apache dan dari Microsoft, yang memiliki ribuan halaman di situs dukungan teknis MSDN mereka (http://msdn.microsoft.com/).

Pada artikel ini saya akan memberi tahu Anda apa itu SOAP dan mengapa SOAP merupakan bagian penting dalam evolusi paradigma pemrograman web. Ini akan membantu Anda melewati dasar-dasarnya dan langsung bekerja dengan perangkat SOAP. Saya kemudian memberikan gambaran singkat tentang proyek SOAP yang ada dan mendalami implementasi Apache. Artikel ini tidak mengklaim untuk membuat ulang gambaran lengkap SOAP, buku saya "Java & XML 2nd Edition" mengisi banyak kekosongan. Jawaban atas banyak pertanyaan yang muncul setelah membaca artikel ini dapat Anda temukan di dalam buku.

Perkenalan

Pertama, Anda perlu memahami apa itu SOAP. Anda dapat membaca opini W3C secara lengkap (dan cukup panjang) di http://www.w3.org/TR/SOAP. Kemudian, setelah mengetahuinya dan membuang semua sekamnya, Anda akan memahami bahwa SOAP hanyalah sebuah protokol. Ini adalah protokol sederhana (tidak perlu menulis yang baru untuk menggunakannya) berdasarkan gagasan bahwa pada titik tertentu dalam arsitektur terdistribusi terdapat kebutuhan untuk bertukar informasi. Selain itu, untuk sistem yang memiliki kemungkinan kelebihan beban dan kesulitan dalam proses pemrosesan, protokol ini sangat diuntungkan karena ringan dan membutuhkan sumber daya yang minimal. Terakhir, ini memungkinkan semua operasi dilakukan melalui HTTP, yang memungkinkan untuk melewati hal-hal rumit seperti firewall dan melindungi diri Anda dari penyadapan menggunakan soket pada port yang jumlahnya sangat banyak. Hal utama adalah Anda menyadari hal ini, dan yang lainnya adalah detailnya.

Tentu saja, Anda ingin mengetahui detailnya, dan saya tidak akan mengabaikannya. Ada tiga komponen dasar spesifikasi SOAP: amplop SOAP, seperangkat aturan enkripsi, dan sarana interaksi antara permintaan dan respons. Anggaplah pesan SOAP sebagai surat biasa. Masih ingatkah Anda benda-benda kuno dalam amplop dengan prangko dan alamat tertulis di depannya? Analogi ini akan membantu Anda memahami konsep SOAP sebagai "amplop" dengan lebih jelas. Gambar 12-1 menggambarkan proses SOAP dalam bentuk analogi ini.

Gambar 12-1. Proses Pesan SOAP

Ingatlah gambaran ini dan mari kita lihat tiga komponen spesifikasi SOAP. Saya akan membahas secara singkat masing-masingnya, memberikan contoh yang paling mewakili konsep tersebut. Ketiga komponen kunci ini menjadikan SOAP begitu penting dan bermakna. Penanganan kesalahan, dukungan untuk berbagai enkripsi, serialisasi parameter, dan fakta bahwa SOAP bekerja melalui HTTP dalam banyak kasus membuatnya lebih menarik daripada solusi protokol terdistribusi lainnya. SOAP memberikan interoperabilitas tingkat tinggi dengan aplikasi lain, yang saya bahas lebih detail di buku saya. Untuk saat ini, saya ingin fokus pada elemen inti SOAP.

Amplop

Amplop SOAP mirip dengan amplop surat biasa. Berisi informasi tentang pesan yang akan dienkripsi di bagian utama SOAP, termasuk informasi tentang penerima dan pengirim, serta informasi tentang pesan itu sendiri. Misalnya, header amplop SOAP mungkin menunjukkan bagaimana pesan harus diproses. Sebelum aplikasi mulai memproses pesan, aplikasi memeriksa informasi tentang pesan tersebut, termasuk apakah aplikasi dapat memproses pesan tersebut. Berbeda dengan situasi dengan panggilan XML-RPC standar (ingat? Pesan XML-RPC, enkripsi, dll., semuanya digabungkan menjadi satu fragmen XML), dengan SOAP pemrosesan berkelanjutan terjadi untuk mempelajari sesuatu tentang pesan tersebut. Pesan SOAP yang khas mungkin juga menyertakan gaya enkripsi yang akan membantu penerima dalam memproses pesan. Contoh 12-1 menunjukkan amplop SOAP yang diakhiri dengan spesifikasi pengkodean.

Contoh 12-1: Amplop SABUN

Kotak sabun http://www-106.ibm.com/developerworks/library/x-soapbx1.html

Seperti yang Anda lihat, enkripsi diatur di dalam amplop, yang memungkinkan aplikasi untuk menentukan (menggunakan nilai atribut gaya pengkodean), apakah dapat membaca pesan masuk yang terletak di elemen Tubuh. Pastikan namespace amplop SOAP sudah benar, atau server SOAP yang menerima pesan Anda akan melaporkan kesalahan ketidakcocokan versi dan Anda tidak akan dapat berkomunikasi dengan mereka.

Enkripsi

Elemen penting kedua dari SOAP adalah kemampuan untuk mengenkripsi tipe data khusus. Dengan RPC (dan XML-RPC), enkripsi hanya dapat dilakukan pada tipe data yang telah ditentukan sebelumnya dan didukung dalam toolkit XML-RPC yang Anda unduh. Mengenkripsi jenis data lain mengharuskan Anda memodifikasi sendiri server dan klien RPC. Dengan SOAP, skema XML dapat digunakan dengan cukup mudah untuk menentukan tipe data baru (menggunakan struktur Tipe kompleks, dibahas di Bab 2 buku saya), dan tipe baru ini dapat direpresentasikan dalam XML sebagai bagian dari bagian utama SOAP. Berkat integrasi Skema XML, Anda dapat mengenkripsi semua jenis data dalam pesan SOAP dengan mendeskripsikannya secara logis dalam Skema XML.

Panggilan

Cara terbaik untuk memahami cara kerja panggilan SOAP adalah dengan membandingkannya dengan sesuatu yang Anda kenal, seperti XML-RPC. Jika Anda ingat, panggilan XML-RPC terlihat mirip dengan cuplikan kode yang disajikan pada Contoh 12-2.

Contoh 12-2. Panggilan ke XML-RPC

// Menentukan prosesor XML (parser) untuk menggunakan XmlRpc.setDriver("org.apache.xerces.parsers.SAXParser"); // Menentukan server tempat koneksi dibuat XmlRpcClient client = new XmlRpcClient("http://rpc.middleearth.com"); // Membuat parameter Parameter vektor = new Vector(); params.addElement(flightNumber); params.addElement(numSeats); params.addElement(creditCardType); params.addElement(creditCardNum); // Permintaan Boolean buyTickets = (Boolean)client.execute("ticketCounter.buyTickets", params); // Memproses responsnya

Saya membuat program sederhana untuk memesan tiket pesawat. Sekarang lihat Contoh 12-3, yang menunjukkan panggilan SOAP.

Contoh 12-3. Panggilan ke SABUN

// Membuat parameter Parameter vektor = new Vector(); params.addElement(Parameter baru("flightNumber", Integer.class, flightNumber, null)); params.addElement(Parameter baru("numSeats", Integer.class, numSeats, null)); params.addElement(Parameter baru("creditCardType", String.class, creditCardType, null)); params.addElement(Parameter baru("creditCardNumber", Long.class, creditCardNum, null)); // Membuat objek Panggilan Panggilan panggilan = Panggilan baru(); call.setTargetObjectURI("urn:xmltoday-airline-tickets"); call.setMethodName("beliTiket"); call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC); panggilan.setParams(params); // Respon Panggilan res = call.invoke(URL baru("http://rpc.middleearth.com"), ""); // Memproses responsnya

Seperti yang Anda lihat, panggilan sebenarnya diwakili oleh objek Panggilan, penghuni memori. Ini memungkinkan Anda menentukan target panggilan, metode panggilan, gaya enkripsi, parameter, dan banyak parameter lain yang tidak disajikan dalam contoh ini. Ini adalah mekanisme yang lebih fleksibel daripada metode XML-RPC, memungkinkan Anda untuk secara eksplisit menentukan serangkaian parameter berbeda yang secara implisit ditentukan dalam XML-RPC. Nanti di artikel ini, Anda akan mempelajari lebih lanjut tentang proses panggilan, termasuk bagaimana SOAP menangani permintaan yang tidak valid, hierarki kesalahan, dan, tentu saja, hasil panggilan yang dikembalikan.

Setelah perkenalan singkat tersebut, Anda sudah cukup tahu untuk tertarik dengan hal lucu ini. Sekarang izinkan saya memperkenalkan Anda pada implementasi SOAP yang akan saya gunakan. Saya akan menjelaskan alasan mengapa saya memilihnya dan melihat beberapa contoh kode.

Pengaturan

Sekarang setelah Anda mempelajari dasar-dasar konsepnya, sekarang saatnya untuk bagian yang menyenangkan: pemrograman. Untuk melakukan ini, Anda memerlukan proyek atau produk praktis yang lebih mudah ditemukan daripada yang terlihat pada pandangan pertama. Jika Anda memerlukan proyek Java yang menyediakan kemampuan SOAP, Anda tidak perlu mencari lama untuk menemukannya. Ada dua kelompok produk: komersial dan gratis. Seperti dalam buku saya, saya akan menghindari menyebutkan produk komersial. Ini sama sekali bukan karena contoh-contoh tersebut buruk (sebaliknya, beberapa di antaranya sangat bagus), tetapi karena saya ingin setiap pembaca dapat mencoba salah satu contoh yang diberikan. Hal ini disebabkan oleh aksesibilitas yang tidak dimiliki oleh banyak produk komersial. Anda harus membayar untuk menggunakannya, atau menggunakannya sementara untuk jangka waktu terbatas setelah mengunduh.

Oleh karena itu, kami dengan lancar mendekati proyek sumber terbuka. Dari area ini saya hanya dapat menyebutkan satu produk: Apache SOAP. Itu terletak di http://xml.apache.org/soap dan menyediakan toolkit SOAP untuk Java. Pada saat penulisan ini, versi 2.2 telah dirilis, yang dapat Anda unduh dari situs web Apache. Versi inilah yang akan saya gunakan dalam contoh artikel ini.

Alternatif Lain

Sebelum melanjutkan ke instalasi dan konfigurasi Apache SOAP, saya akan menjawab beberapa pertanyaan yang mungkin terlintas di benak Anda. Saya rasa saya sudah menjelaskan dengan cukup jelas alasan mengapa saya tidak menggunakan produk komersial. Namun, Anda mungkin memikirkan beberapa sumber terbuka atau proyek terkait lainnya yang mungkin ingin Anda gunakan, dan Anda terkejut karena saya belum mengomentarinya.

Bagaimana dengan IBM SOAP4J?

Alternatif pertama dalam daftar alternatif adalah implementasi dari IBM: SOAP4J. Pekerjaan IBM menjadi dasar proyek Apache SOAP, sama seperti XML4J IBM yang berkembang menjadi apa yang sekarang dikenal sebagai proyek parser XML Apache Xerces. Diasumsikan bahwa implementasi IBM akan didesain ulang, digabungkan dengan Apache SOAP. Hal yang sama terjadi dengan XML4J IBM: sekarang hanya menyediakan pengemasan dalam Xerces. Ini hanya menyoroti tren - produsen besar sering mendukung dan menggunakan proyek OpenSource, dalam hal ini kedua proyek (Apache dan IBM) menggunakan basis kode yang sama.

Apakah Microsoft keluar dari permainan?

Tentu tidak. Microsoft dan implementasi SOAP-nya, serta seluruh pergerakan .NET (dibahas lebih detail di buku saya), cukup signifikan. Saya benar-benar ingin menghabiskan sebagian besar waktu saya melihat implementasi SOAP Microsoft secara detail, tetapi hanya mendukung objek COM dan tidak mendukung Java. Karena alasan ini, uraian seperti itu tidak dapat dimasukkan dalam artikel tentang Java dan XML. Namun, Microsoft (terlepas dari semua keluhan yang kami, sebagai pengembang, miliki tentang perusahaan ini) telah melakukan pekerjaan penting di bidang layanan web, dan Anda akan membuat kesalahan jika Anda mengabaikannya tanpa berpikir, hanya dipandu oleh emosi yang mentah. Jika Anda perlu bekerja dengan komponen COM atau Visual Basic, saya sangat menyarankan Anda mencoba menggunakan toolkit Microsoft SOAP, tersedia di http://msdn.microsoft.com/library/default.asp?url=/nhp/Default .asp ?contentid=28000523 bersama dengan banyak sumber SOAP lainnya.

Apa itu sumbu?

Anda yang mengikuti aktivitas Apache pasti pernah mendengar tentang Apache Axis. Axis adalah toolkit SOAP generasi berikutnya yang juga dikembangkan di bawah payung Apache XML. SOAP (spesifikasi, bukan implementasi spesifik), yang akhir-akhir ini berkembang pesat dan radikal, sangat sulit untuk diikuti. Mencoba membuat versi SOAP yang sepenuhnya memenuhi persyaratan saat ini seiring dengan perkembangannya juga cukup menantang. Hasilnya, versi Apache SOAP saat ini menawarkan solusi yang dibatasi oleh desainnya. Setelah memutuskan bahwa tidak ada gunanya mencoba mendesain ulang sepenuhnya alat yang ada, pengembang Apache mulai membuat proyek berdasarkan kode baru. Maka lahirlah Axis. Nama SOAP pun berubah, pertama dari SOAP menjadi XP dan kemudian menjadi XMLP. Kemudian nama spesifikasi dihilangkan dari nama SOAP baru dan lahirlah nama "Axis". Tapi sekarang sepertinya W3C akan kembali ke nama spesifikasi SOAP (versi 1.2 atau 2.0), jadi segalanya mungkin masih berubah dan akan ada lebih banyak kebingungan!

Pikirkan IBM SOAP4J sebagai arsitektur?1 dari toolkit SOAP. Bagaimana dengan Apache SOAP (dibahas dalam artikel ini) sebagai arsitektur?2. Dan Axis mewakili arsitektur ?3, arsitektur generasi baru. Proyek ini menggunakan SAX sedangkan Apache SOAP berbasis DOM. Selain itu, Axis, tidak seperti Apache SOAP, menyediakan pendekatan interaksi pengguna yang lebih ramah pengguna. Setelah menyebutkan kelebihan-kelebihan tersebut, Anda mungkin bertanya-tanya mengapa saya tidak memilih Axis sebagai subjek studi saya. Itu hanya akan menjadi sedikit terlalu dini. Saat ini, hanya Axis versi 0.51 yang sedang dipersiapkan untuk dirilis. Ini belum merupakan versi beta, atau bahkan versi alfa. Saya ingin berbicara tentang fitur-fitur Axis yang baru, tetapi Anda tidak memiliki kesempatan untuk meyakinkan manajemen Anda bahwa Anda dapat menggunakan perangkat lunak sumber terbuka sub-alfa untuk kebutuhan sistem penting Anda. Jadi saya memutuskan untuk fokus pada sesuatu yang nyata Anda dapat gunakan sudah Hari ini- SABUN Apache. Saya rasa ketika versi final Apache Axis dirilis, saya akan memperbarui materi ini di edisi berikutnya buku saya. Sampai saat itu tiba, mari kita fokus pada solusi yang sudah tersedia.

Instalasi

Ada dua kemungkinan bentuk instalasi SOAP. Yang pertama adalah memulai klien SOAP menggunakan SOAP API untuk berkomunikasi dengan server yang dapat menerima pesan SOAP. Cara kedua adalah dengan menjalankan server SOAP yang dapat menerima pesan dari klien SOAP. Di bagian ini saya telah menjelaskan kedua prosedur tersebut.

Klien

Untuk menggunakan klien SOAP, Anda perlu mengunduh Apache SOAP terlebih dahulu, tersedia di http://xml.apache.org/dist/soap. Saya mengunduh versi 2.2 dalam format biner (dari subdirektori versi-2.2). Kemudian Anda harus mengekstrak isi arsip ke dalam direktori di komputer Anda. Dalam kasus saya itu adalah direktori javaxml2 (c:\javaxml2 di komputer Windows saya /javaxml2 di komputer Mac OS X saya). Hasilnya, file-file tersebut di-unzip /javaxml2/soap-2_2. Anda juga perlu mengunduh paket JavaMail yang tersedia dari Sun http://java.sun.com/products/javamail/. Ini diperlukan untuk mendukung protokol transfer SMTP yang digunakan oleh Apache SOAP. Kemudian unduh Java Beans Activation Framework (JAF), juga tersedia dari server Sun http://java.sun.com/products/beans/glasgow/jaf.html . Berdasarkan asumsi bahwa Anda sudah menginstal Xerces atau parser XML lainnya dan siap digunakan.

Catatan: Pastikan parser XML Anda mematuhi JAXP dan menggunakan namespace yang benar. Parser Anda kemungkinan besar memenuhi persyaratan ini. Jika Anda mengalami masalah, sebaiknya kembali menggunakan Xerces.

Catatan: Gunakan Xerces versi terbaru. Versi 1.4 dan lebih tinggi sudah cukup. Ada sejumlah bug saat bekerja dengan SOAP dan Xerces 1.3(.1), jadi saya menyarankan Anda untuk tidak menggunakan kombinasi ini.

Buka zip paket JavaMail dan JAF lalu sertakan toplesnya di classpath Anda serta perpustakaan sabun.jar. Masing-masing file jar ini harus ditempatkan di direktori root program terkait, atau di subdirektori /lib. Setelah selesai variabel Anda jalur kelas akan terlihat seperti ini:

$ echo $CLASSPATH /javaxml2/soap-2_2/lib/soap.jar:/javaxml2/lib/xerces.jar: /javaxml2/javamail-1.2/mail.jar:/javaxml2/jaf-1.0.1/activation.jar

Untuk Windows akan terlihat seperti ini:

c:\>echo %CLASSPATH% c:\javaxml2\soap-2_2\lib\soap.jar;c:\javaxml2\lib\xerces.jar; c:\javaxml2\javamail-1.2\mail.jar;c:\javaxml2\jaf-1.0.1\activation.jar

Dan terakhir tambahkan direktori javaxml2/sabun-2_2/ di dalam kamu jalur kelas untuk menjalankan contoh SOAP. Saya telah menjelaskan pengaturannya untuk beberapa contoh di bab ini.

pelayan

Untuk membuat kumpulan komponen sisi server yang kompatibel dengan SOAP, Anda memerlukan mesin servlet terlebih dahulu. Seperti pada bab sebelumnya, saya menggunakan Apache Tomcat (tersedia di http://jakarta.apache.org/) sebagai contoh untuk bab ini. Anda perlu menambahkan semua yang dibutuhkan klien jalur kelas server. Cara termudah untuk melakukannya adalah dengan mengatur ulang sabun.jar, aktivasi.jar Dan mail.jar, serta parser Anda, ke dalam direktori perpustakaan mesin servlet Anda. Untuk Tomcat, ini adalah direktori /lib, yang berisi perpustakaan untuk memuat otomatis. Jika Anda ingin memberikan dukungan untuk skrip (yang tidak dibahas dalam bab ini, tetapi ditemukan dalam contoh Apache SOAP), Anda perlu memasukkan bsf.jar(tersedia di http://oss.software.ibm.com/developerworks/projects/bsf) dan js.jar(tersedia di http://www.mozilla.org/rhino/) ke direktori yang sama.

Catatan: Jika Anda menggunakan Xerces dengan Tomcat, Anda perlu mengulangi trik yang saya jelaskan di Bab 10. Ganti nama parser.jar V z_parser.jar, A jaxp.jar V z_jaxp.jar untuk memastikan itu xerces.jar dan versi JAXP yang disertakan dimuat sebelum parser atau implementasi JAXP lainnya.

Kemudian muat ulang mesin servlet Anda dan Anda akan siap untuk menulis komponen server SOAP.

Router Servlet dan Klien Admin

Terlepas dari operasi dasar, Apache SOAP menyertakan servlet router serta klien admin. Bahkan jika Anda tidak bermaksud menggunakannya, saya sarankan Anda menginstalnya untuk menguji apakah SOAP telah diinstal dengan benar. Proses ini tergantung pada mesin servlet yang Anda gunakan, jadi saya akan membatasi proses instalasi pada Tomcat. Petunjuk instalasi untuk beberapa mesin servlet lainnya dapat ditemukan di http://xml.apache.org/soap/docs/index.html.

Instalasi di bawah Tomcat sangat sederhana: cukup ambil filenya sabun.perang dari direktori sabun-2_2/webapps dan letakkan di direktori $TOMCAT_HOME/aplikasi web- dan itu saja! Untuk memeriksa instalasi, masukkan alamat di browser Anda http://localhost:8080/soap/servlet/rpcrouter. Anda akan menerima respons serupa dengan yang ditunjukkan pada Gambar 12-2.

Gambar 12-2. Servlet RPC Router

Meskipun pesan tersebut tampak seperti pesan kesalahan, ini menunjukkan bahwa semuanya berfungsi dengan benar. Anda akan mendapatkan respons yang sama jika mengarahkan browser Anda ke alamat klien administrator: http://localhost:8080/soap/servlet/messagerouter.

Untuk menyelesaikan pengujian server dan klien, pastikan Anda telah mengikuti semua instruksi sepenuhnya. Kemudian jalankan kelas Java berikut seperti yang ditunjukkan di bawah ini untuk mendukung URL servlet Anda untuk servlet router RPC:

C:\>java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter list Layanan yang Dikerahkan:

Anda harus mendapatkan daftar layanan kosong seperti yang ditunjukkan di atas. Jika Anda menerima pesan apa pun, harap tinjau daftar panjang kemungkinan kesalahan yang tersedia di http://xml.apache.org/soap/docs/trouble/index.html. Ini adalah daftar terlengkap masalah yang mungkin Anda temui. Jika Anda menerima daftar kosong, ini berarti pengaturan telah selesai dan Anda siap untuk mulai melihat contoh yang diberikan dalam bab ini.

Mari kita mulai

Ada tiga tahapan utama dalam penulisan sistem berbasis SOAP. Setelah mendaftar, saya akan membahas secara singkat masing-masing:

  • Memilih antara pesan SOAP-RPC dan SOAP;
  • Menulis atau mendapatkan akses ke layanan SOAP;
  • Menulis atau mengakses klien SOAP.

Langkah pertama adalah memilih apakah Anda akan menggunakan SOAP untuk panggilan RPC (di mana prosedur jarak jauh dijalankan di server), atau pesan (di mana klien hanya mengirimkan potongan informasi ke server). Saya membahas proses ini secara rinci di bawah. Setelah Anda membuat keputusan ini, Anda perlu mengakses atau membuat layanan Anda sendiri. Tentu saja, karena kita semua profesional di bidang Java, bab ini membahas cara membuatnya sendiri. Dan terakhir, Anda perlu menulis klien untuk layanan ini, itu saja!

RPC atau Pesan?

Tugas pertama Anda tidak ada hubungannya dengan pemrograman dan lebih bersifat desain. Anda harus memilih apakah Anda akan menggunakan RPC atau layanan pesan. Kami berasumsi bahwa Anda sudah familiar dengan RPC (misalnya, dengan membaca salah satu bab buku saya). Klien menjalankan prosedur jarak jauh di server dan kemudian menerima respons. Dalam skenario ini, SOAP bertindak sebagai sistem XML-RPC yang disempurnakan yang menyediakan penanganan kesalahan yang lebih baik dan transfer tipe data kompleks melalui jaringan. Anda sudah familiar dengan konsep ini, dan karena sistem RPC lebih mudah untuk ditulis dalam SOAP, saya akan memulainya. Artikel ini menjelaskan cara membuat layanan RPC, klien RPC, dan menerapkan sistem.

Cara kerja SOAP yang lain didasarkan pada pertukaran pesan. Alih-alih melakukan prosedur jarak jauh, ini hanya digunakan untuk bertukar informasi. Seperti yang bisa Anda tebak, ini adalah alat yang ampuh yang tidak mengharuskan klien mengetahui metode individual dari server mana pun. Hal ini juga membuat pemodelan sistem jarak jauh menjadi lebih terisolasi dengan mengizinkan paket data (paket dalam arti kiasan, bukan dalam arti jaringan) untuk dikirim ke sistem lain. Pada saat yang sama, sistem lain tidak perlu mengetahui operasi yang dilakukan dengan data ini. Gaya ini lebih kompleks daripada pemrograman RPC, jadi saya tidak akan menjelaskannya di sini. Anda akan menemukannya di buku saya, bersama dengan rincian interaksi bisnis-ke-bisnis lainnya. Pertama, berkenalan dengan pemrograman SOAP-RPC.

Seperti kebanyakan masalah desain, pengambilan keputusan terserah Anda. Analisis aplikasi Anda dan coba tentukan mengapa Anda perlu menggunakan SOAP. Jika Anda memiliki server dan sekumpulan klien yang menjalankan fungsi bisnis tertentu sesuai permintaan, maka RPC lebih cocok untuk Anda. Dalam sistem yang kompleks di mana pertukaran data lebih dari sekedar menjalankan fungsi bisnis tertentu sesuai permintaan, penggunaan pesan SOAP jauh lebih disukai.

layanan RPC

Sekarang formalitas sudah selesai, sekarang saatnya bertindak. Seperti yang Anda ketahui, di RPC Anda memerlukan kelas yang metodenya akan dieksekusi dari jarak jauh.

Cuplikan kode

Saya akan mulai dengan melihat beberapa cuplikan kode untuk server. Fragmen ini adalah kelas dengan metode yang dijalankan untuk klien RPC. Saya menggunakan kode dari buku saya sebagai contoh. Daripada menggunakan kelas sederhana, saya memilih contoh yang lebih kompleks untuk menunjukkan kemampuan SOAP sejelas mungkin. Jadi, saya menggunakan kelas CD sebagai contoh. Pertama kita mendefinisikan elemennya peta untuk setiap jenis parameter non-standar. Untuk atribut gaya pengkodean, setidaknya di Apache SOAP 2.2. Anda harus memberikan nilai http://schemas.xmlsoap.org/soap/encoding/ . Saat ini ini adalah satu-satunya pengkodean yang didukung. Anda perlu menentukan namespace untuk tipe yang ditentukan pengguna dan kemudian nama kelas yang diawali dengan namespace untuk tipe tersebut. Dalam kasus kami, untuk tujuan ini saya menggunakan namespace fiktif dan awalan sederhana " X". Kemudian menggunakan atribut javaType, tetapkan nama asli kelas Java (untuk kasus ini - javaxml2.CD). Dan terakhir, kuralesil dengan atribut java2XMLClassName Dan xml2JavaClassName. Dengan bantuan mereka, sebuah kelas ditentukan yang dikonversi dari Java ke XML dan sebaliknya. Saya menggunakan kelas BeanSerializer yang sangat berguna, juga disertakan dengan Apache SOAP. Jika parameter khusus Anda dalam format JavaBean, serializer dan deserializer ini akan menyelamatkan Anda dari keharusan menulis sendiri. Anda memerlukan kelas dengan konstruktor default (ingat, untuk kelas CD saya mendefinisikan konstruktor sederhana tanpa parameter), dan mempublikasikan semua data kelas ini menggunakan metode setXXX Dan dapatkanXXX. Karena kelas CD memenuhi semua persyaratan ini dengan sempurna, BeanSerializer bekerja dengan sempurna.

Catatan: Kelas apa CD memenuhi persyaratan BeanSerializer. tidak terlalu penting. Sebagian besar kelas mudah dikonversi ke format ini. Oleh karena itu, saya menyarankan untuk menghindari menulis serializer dan deserializer Anda sendiri. Ini sangat memusingkan (tidak ada yang rumit, tetapi terlalu melelahkan) dan saya menyarankan Anda menghemat energi dan menggunakan konversi kacang dalam parameter khusus Anda. Dalam banyak kasus, konversi kacang hanya memerlukan konstruktor default (tanpa parameter) di kelas Anda.

Sekarang mari kita buat ulang stoples file dan instal ulang layanan kami:

(gandalf)/javaxml2/Ch12$ java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter xml/CDcatalogDD.xml

Perhatian: Jika Anda membiarkan mesin servlet Anda berjalan dan menghosting ulang layanan pada saat yang sama, Anda perlu me-restart mesin servlet untuk mengaktifkan kelas baru untuk layanan SOAP dan menghosting ulang layanan tersebut.

Sekarang yang tersisa hanyalah memodifikasi klien untuk menggunakan kelas dan metode baru. Contoh 12-10 berisi versi kelas klien yang dimodifikasi Penambah CD. Perubahan yang dilakukan pada versi sebelumnya disorot.

Contoh 12-10: Kelas CDAdder yang diperbarui

paket javaxml2; impor java.net.URL; impor java.util.Vector; import org.apache.soap.Constants; import org.apache.soap.Fault; import org.apache.soap.SOAPException; import org.apache.soap.encoding.SOAPMappingRegistry; import org.apache.soap.encoding.soapenc.BeanSerializer; import org.apache.soap.rpc.Call; import org.apache.soap.rpc.Parameter; import org.apache.soap.rpc.Respon; import org.apache.soap.util.xml.QName; CDAdder kelas publik( public void add(URL url, Judul string, Artis string, Label string) menampilkan SOAPException ( System.out.println("Menambahkan CD dengan title "" + title + "" artist "" + artist + "" studio " + label); CD cd = CD baru (judul, artis, label); // Membuat objek panggilan Panggilan Panggilan panggilan = Panggilan baru(); call.setSOAPMappingRegistry(registrasi); call.setTargetObjectURI("urn:cd-catalog"); panggilan.setMethodName("addCD"); call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC); // Mengatur parameter Parameter vektor = new Vector(); params.addElement(Parameter baru("cd", CD.kelas, cd, null)); panggilan.setParams(params); // Memproses respons Respon panggilan Invoke; respon = panggilan.invoke(url, ""); if (!response.generatedFault()) ( System.out.println("Tambahkan CD berhasil diselesaikan."); ) else ( Kesalahan kesalahan = respon.getFault(); System.out.println(Kesalahan: " + kesalahan.getFaultString ()); ) ) public static void main(String args) ( if (args.length != 4) ( System.out.println("Templat: java javaxml2.CDAdder " + "\"[Judul CD]\" \"[Nama Artis]\ " \"[CD Studio]\""); kembali; ) coba ( // URL server SOAP tempat koneksi dibuat URL url = URL baru(args); // Dapatkan nilai untuk CD String baru title = args; Artis senar = args; Label string = args; // Tambahkan CD Adder CDadder = new CDAdder(); adder.add(url, judul, artis, label); ) tangkapan (Pengecualian e) ( e.printStackTrace(); ) ) )

Satu-satunya perubahan yang menarik adalah pada pemetaan kelas CD:

// Petakan tipe ini sehingga dapat digunakan dengan SOAP SOAPMappingRegistry registry = new SOAPMappingRegistry(); Serializer BeanSerializer = BeanSerializer baru(); registry.mapTypes(Constants.NS_URI_SOAP_ENC, QName baru("urn:cd-catalog-demo", "cd"), CD.class, serializer, serializer);

Ini adalah bagaimana parameter pengguna dapat dikodekan dan dikirim melalui jaringan. Aku sudah memberitahumu bagaimana kelasnya BeanSerializer dapat digunakan untuk memproses parameter dalam format JavaBean, seperti class CD. Saya menggunakan deskriptor penempatan untuk menunjukkan ini ke server, meskipun sekarang saya perlu memberi tahu klien untuk menggunakan serializer dan deserializer ini. Fungsi ini dilakukan oleh kelas SOAPMappingRegistry. metode tipe peta() mengambil string terenkripsi (sekali lagi, lebih baik menggunakan konstanta untuk ini NS_URI_SOAP_ENC), dan informasi tentang tipe parameter yang serialisasi khusus harus digunakan. QName ditentukan terlebih dahulu. Inilah sebabnya namespace aneh digunakan di deskriptor hosting. Anda perlu memberikan URN yang sama di sini, serta nama lokal elemen (untuk contoh ini "CD"), lalu objek Java Kelas kelas yang akan diserialkan ( CD.kelas) dan terakhir turunan kelas untuk serialisasi dan deserialisasi. Untuk contoh ini, kedua kasus akan melibatkan sebuah instance BeanSerializer. Setelah semua pengaturan ini dimasukkan ke dalam registri, beri tahu objek tersebut Panggilan menggunakan metode tersebut setSOAPMapping-Registry().

Anda dapat menjalankan kelas ini seperti yang ditunjukkan sebelumnya, menambahkan CD, dan semuanya akan berfungsi seperti yang diharapkan:

C:\javaxml2\build>java javaxml2.CDAdder http://localhost:8080/soap/servlet/rpcrouter "Tony Rice" "Manzanita" "Sugar Hill" Menambahkan CD berjudul "Tony Rice" oleh "Manzanita" dari Sugar Hill Berhasil menambahkan CD.

Saya meninggalkan kelas modifikasi Daftar CD untukmu. Semuanya diproduksi menurut template yang sama. Untuk mengujinya sendiri, Anda dapat merujuk ke file contoh untuk buku saya, yang sudah berisi kelas-kelas yang diperbarui ini.

Catatan: Anda dapat memutuskannya karena kelasnya Daftar CD tidak berinteraksi langsung dengan objeknya CD(dikembalikan dengan metode daftar() jenisnya penting tabel hash), maka Anda tidak perlu melakukan perubahan apa pun. Namun, kelas kembali tabel hash berisi contoh objek CD. Jika SOAP tidak tahu cara melakukan deserialisasi, klien akan membuat kesalahan. Dalam hal ini, untuk menyelesaikan masalah, Anda harus menentukan objeknya Panggilan contoh SOAPMappingRegistry.

Penanganan kesalahan yang efisien

Sekarang setelah Anda melihat objek khusus dan melakukan panggilan RPC dan semacamnya, izinkan saya membicarakan topik yang kurang menarik: penanganan kesalahan. Dengan transaksi jaringan apa pun, banyak kegagalan dapat terjadi. Layanan tidak dimulai, ada kesalahan di server, objek tidak dapat ditemukan, kelas hilang dan banyak masalah lainnya. Sejauh ini saya hanya menggunakan metode tersebut kesalahan.getString() untuk menghasilkan pesan kesalahan. Namun cara ini mungkin tidak selalu berguna. Untuk melihatnya beraksi, hapus komentar pada konstruktor Katalog CD:

Katalog CD publik() ( //katalog = Hashtable baru(); // Buat direktori addCD(CD baru("Nickel Creek", "Nickel Creek", "Sugar Hill")); addCD(CD baru("Biarkan Jatuh", "Sean Watkins", "Sugar Hill")); addCD(CD baru("Batas Udara", "Michael Hedges", "Windham Hill")); addCD(CD baru("Akar Tunggang", "Michael Hedges", "Bukit Windham")); )

Kompilasi ulang, restart mesin servlet dan host ulang. Hal ini akan menghasilkan pengecualian NullPointerException ketika konstruktor kelas mencoba menambahkan CD ke yang tidak diinisialisasi tabel hash. Saat memulai klien, pesan kesalahan akan muncul, tetapi tidak terlalu informatif:

(gandalf)/javaxml2/build$ java javaxml2.CDLister http://localhost:8080/soap/servlet/rpcrouter Lihat direktori CD saat ini. Kesalahan: Tidak dapat menyelesaikan objek target: null

Ini sama sekali bukan informasi yang dapat membantu dalam mengidentifikasi dan memperbaiki kesalahan. Namun demikian, kerangka kerja tersebut mengatasi penanganan kesalahan dengan baik. Apakah kamu ingat Pendengar Kesalahan DOMF, yang Anda tentukan sebagai nilai elemen pendengar kesalahan? Waktunya telah tiba baginya untuk memasuki permainan. Objek dikembalikan jika terjadi kesalahan Kesalahan berisi DOM (Model Objek Dokumen) org.w3c.dom.Elemen dengan informasi rinci tentang kesalahan tersebut. Pertama, tambahkan ekspresi impor ke kode sumber Anda java.util.Iterator:

impor java.net.URL; import java.util.Enumeration; import java.util.Hashtable; impor java.util.Iterator; impor java.util.Vector; import org.apache.soap.Constants; import org.apache.soap.Fault; import org.apache.soap.SOAPException; import org.apache.soap.encoding.SOAPMappingRegistry; import org.apache.soap.encoding.soapenc.BeanSerializer; import org.apache.soap.rpc.Call; import org.apache.soap.rpc.Parameter; import org.apache.soap.rpc.Respon; import org.apache.soap.util.xml.QName;

Sekarang mari kita membuat perubahan untuk menangani kesalahan dalam metode list():

if (!response.generatedFault()) ( Parameter returnValue = respon.getReturnValue(); Katalog Hashtable = (Hashtable)returnValue.getValue(); Pencacahan e = catalog.keys(); while (e.hasMoreElements()) ( String title = (String)e.nextElement(); CD cd = (CD)catalog.get(title); System.out.println(" "" + cd.getTitle() + "" artis " + cd.getArtist() + " studios " + cd.getLabel()); ) ) else ( Kesalahan kesalahan = respon.getFault(); System.out.println("Kesalahan: " + kesalahan.getFaultString()); Entri vektor = kesalahan.getDetailEntries(); untuk (Iterator i = entri.iterator(); i.hasNext();) ( org.w3c.dom.Element entri = (org.w3c.dom.Element)i.next(); System.out.println(entri .getFirstChild().getNodeValue()); ) )

Menggunakan metode dapatkanDetailEntries() Anda mendapatkan akses ke layanan SOAP dan server data mentah yang mendukung masalah tersebut. Kode memprosesnya kembali (biasanya hanya ada satu elemen, tetapi memerlukan perhatian) dan mencegat DOM Elemen, terdapat di setiap entri. Pada dasarnya, inilah XML yang sedang Anda kerjakan:

SOAP-ENV:Server.BadTargetObjectURI Tidak dapat menyelesaikan target: null Ini adalah apa yang kita inginkan!

Dengan kata lain, objek Fault memberi Anda akses ke bagian amplop SOAP yang berisi kesalahan. Selain itu, Apache SOAP menyediakan pelacakan tumpukan Java ketika terjadi kesalahan, memberikan informasi rinci yang diperlukan untuk memperbaikinya. Mencegat suatu elemen stackTrace dan mencetak nilai simpul Teks dari elemen ini klien Anda dapat mencetak jejak tumpukan server. Dengan mengkompilasi perubahan ini dan memulai ulang klien, Anda akan mendapatkan hasil berikut:

C:\javaxml2\build>java javaxml2.CDLister http://localhost:8080/soap/servlet/rpcr luar Melihat direktori CD saat ini. Kesalahan: Tidak dapat menyelesaikan target: null java.lang.NullPointerException di javaxml2.CDcatalog.addCD(CDcatalog.java:24) di javaxml2.CDcatalog. (CDKatalog.java:14) di java.lang.Class.newInstance0(Metode Asli) di java.lang.Class.newInstance(Class.java:237)

Memang tidak jauh lebih baik, namun setidaknya Anda dapat melihat beberapa informasi kecil bahwa pengecualian terjadi NullPointerException dan bahkan mengetahui nomor baris di kelas server tempat masalah ini terjadi. Hasil dari perubahan terbaru ini telah memberi Anda gambaran yang jelas tentang masalah penanganan kesalahan. Anda sekarang harus memeriksa kesalahan pada kelas server Anda. Ya hampir lupa, sebelum itu jangan lupa untuk mengubah kelasmu kembali Katalog CD untuk menghilangkan kesalahan yang sengaja kami perkenalkan demi kejelasan!

  1. Ada banyak pembicaraan tentang menjalankan SOAP melalui protokol lain seperti SMTP (atau bahkan Jabber). Standar SOAP saat ini tidak menyediakan hal ini, namun kemampuan serupa mungkin ditambahkan di masa mendatang. Oleh karena itu, jangan heran jika Anda menjumpai diskusi aktif mengenai topik ini.