غالبًا ما يكون العمل مع SOAP أمرًا صعبًا ، وقد يكون التعامل مع WSDL مساهمة كبيرة في تعقيد هذه المهمة. حقًا ، قد يكون الأمر الأقل توقعًا عند مواجهتك لغة عصرية ومبهرة ، على سبيل المثال ، Scala ، المعروفة بفاعليتها وطريقة غير متزامنة للتعامل مع الطلبات. في الواقع ، فإن العديد من مطوري البرامج الذين شقوا طريقهم إلى الصناعة مؤخرًا ، ربما لا يعرفون حتى بروتوكولات SOAP و WSDL ، ويتضايقون بسرعة أو حتى يغضبون عند محاولة الاتصال بمثل هذه الخدمة القديمة. لذا ، هل ينبغي لنا أن نستنكر ذلك كله لصالح مجموعة التكنولوجيا الحديثة ، أو ربما هناك حل أقل إيلاما؟
الصابون: إرث
من الصعب القول أن هذا الشيء SOAP يبدو قديمًا جدًا في هذه الأيام ، لا سيما على عكس الوضع الحالي للتكنولوجيا. قد تكون كتابة عميل WSDL من البداية باستخدام Kotlin أو Scala أو أي لغة حديثة أخرى أمرًا مؤلمًا ، كما أن عدم وجود وثائق مناسبة لأنه لا يجعل الحياة أسهل. لكن لدي أخبار جيدة لك ، هناك بقعة من الضوء في مملكة الصابون المظلمة. حسنا ، في الواقع WSDL نفسها هي واحدة. على الرغم من أن الوزن الثقيل والقبيح إلى حد ما ، لديها ميزة معينة. إن الإفراط في تنسيق WSDL يجعل من السهل للغاية إنشاء كود العميل (وكذلك الخادم) ، ربما ليس للبشر ولكن بالتأكيد للأنظمة الآلية.
حتى بالمقارنة مع مواصفات API الحديثة ، فإنه في الواقع يمكن أن يظل على قدم المساواة مع OpenAPI أو مفاهيم Swagger API الفاخرة حيث يتم وصف كل شيء في المواصفات اللغوية. يتيح ذلك فرصًا هائلة للتشغيل البيني بين الأنظمة الأساسية واللغات المختلفة ، وصولاً إلى مستوى التنفيذ. على سبيل المثال ، إذا كشف أحدهم ، دعنا نقول خدمة ويب .NET مع مواصفات WSDL ، يمكن لآخر إنشاء عميل يستند إلى JVM تلقائيًا للاتصال به دون حدوث أي تحويل أو عدم توافق في تنسيقات البيانات.
WSDL استيراد ماجيك
دعنا ندور أكثر ونتحدث عن توليد الشفرة الآلية. قد تتفاجأ ، لكن معظم الأنظمة الأساسية للمؤسسات ، وخاصة Java و .NET ، تأتي مع أدوات إنشاء التعليمات البرمجية لـ WSDL. على سبيل المثال ، هناك wsimport الذي يأتي كجزء من توزيع JDK. هذه الأدوات قوية جدًا ويجب أن تغطي نهاية مهمة الإنشاء التلقائي. الجزء الوحيد المتبقي هو ربط منطق عملك برمز العميل والاستفادة منه.
لذلك ، نظرًا لأننا في موضوع Scala حاليًا ، فلنلق نظرة أعمق على أداة wsimport
من Java:
wsimport -p stockquote http://stockquote.example.com/quote?wsdl
يأخذ الأمر مخطط WSDL كمعلمة مطلوبة ، وهو في الأساس يكفي لإنتاج مجموعة كاملة من POJOs والواجهات ، والتي تتميز بكل التعليقات التوضيحية المناسبة. في الواقع ، يقوم الأشخاص الأخيرون بالخدعة: هذا ما يجعل كل الأشياء ممكنة. عند التنفيذ ، تقوم JVM بتوصيل كود العميل الخاص بك مع تنفيذ عميل خدمة الويب الداخلية ، والذي سيصدر من خارج الصندوق ، لذلك لا داعي لأن تزعج الكثير بشأن الشبكات ذات المستوى المنخفض والتوصيل والتوعية. بقية العمل هو التعامل مع خصوصيات وعموميات بشكل صحيح ، وتوخي الحذر مع الأخطاء والاستثناءات.
جلب الأتمتة إلى المستوى التالي مع SBT
حسنا ، لقد حان الوقت لبعض التدريب العملي. تخيل أن لدينا بعض خدمات الويب SOAP التي نحتاجها للاتصال أيضًا ، وهي تعرض WSDL. أخذت عمدا بعض الاختبارات ، من أجل العلم والتعليم فقط ، بطبيعة الحال. قم بتشغيل مولد الشفرة:
wsimport -s ../src/main/java -extension -p your.package.wsdl.nl \ -XadditionalHeaders -Xnocompile \ http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso?WSDL
وتنتج عددا من شفرة جافا الخام في مجلد الإخراج. يمكننا المضي قدمًا في ربط منطق أعمالنا ، كما هو مقترح أعلاه. لكن انتظر ثانيةً ، ماذا لو تغير جانب الخادم - سنكون على دراية به فقط في لحظة تنفيذ التعليمات البرمجية الفعلية (أو في لحظة فشل اختبارات التكامل ، إذا كان لدينا بعض). ليس جميل لن يصبح الأمر سريعًا على الإطلاق إذا كنت ستفكر في ارتكاب كل شفرة رموز جافا هذه في مستودع سكالا الأصلي.
بالطبع ، سيكون من الأسهل إنشاء كل هذه الأشياء تلقائيًا والحفاظ على الأمور نظيفة ونظيفة. تتمثل الخطوة الأولى في هذا في أتمتة الحصول على جميع فئات WSDL باستخدام أمر واحد وإخراج برنامج نصي من Shell. لقد صنعت بالفعل واحدة لك حتى تتمكن من إلقاء نظرة: wsdl_import.sh .
بعد ذلك يمكننا أن نلفها بمهمة بناء: فلنأخذ SBT كمثال ، لأننا في Scala ، لذلك يجب أن يعمل شيء من هذا القبيل:
lazy val wsdlImport = TaskKey[Unit]("wsdlImport", "Generates Java classes from WSDL") wsdlImport := { val wsdlSources = "./wsdl/src/main/java" val d = file(wsdlSources) if (d.isDirectory) { // don't forget to rename to your fav one in line with WSDL generating sh val gen = file(s"$wsdlSources/github/sainnr/wsdl") if (!gen.exists() || gen.listFiles().isEmpty) { import sys.process._ println("[wsdl_import] Importing Java beans from WSDL...") "./wsdl/bin/wsdl_import.sh" ! } else println("[wsdl_import] Looks like WSDL is already imported, skipping.") } else println(s"[wsdl_import] Make sure the directory ${d.absolutePath} exists.") }
مصدر
الآن ، نحن بحاجة إلى التأكد من حصولنا على كل هذا الرمز قبل تجميع أجزاء Scala ، لأسباب واضحة. من السهل ، لدينا SBT لذلك نحن فقط بحاجة إلى تنفيذ البرنامج النصي Shell كمهمة SBT مثل أعلاه وتشغيل الأشياء بالترتيب الصحيح ، الصحيح؟ حسنًا ، الأمر أكثر تعقيدًا في الحياة الواقعية. دون الخوض في الكثير من التفاصيل حول كيفية عمل SBT ، تصبح الأمور أسهل إذا فصلنا جزء WSDL-Java هذا إلى مشروع فرعي يحتوي على ذاتي ، وجعل التبعية المناسبة في تكوين SBT الرئيسي.
lazy val wsdl = (project in file("wsdl")) .settings ( publishSettings, sources in (Compile, doc) := Seq.empty ) lazy val root = (project in file(".")) .aggregate(wsdl) .dependsOn(wsdl)
مصدر
عندما تقوم بترجمة المشروع الرئيسي ، يضمن SBT أولاً أن المشروع الفرعي مترجم بالفعل. ولكن هناك نقطة جذب: عندما تكون قد قمت للتو بسحب مستودع التخزين الخاص بك ، فقد لا تكون قد نفذت المجموعة. لذلك عند فتحه لأول مرة في المحرر ، ستكون بعض التبعيات مفقودة ، بالطبع. نأمل أن يكون الشيء الوحيد الذي تحتاجه هو تشغيل برنامج sbt compilecommand ، وربما تحديث المشروع في IDE.
قد يكون هناك تحذير آخر إذا كنت تقوم بتشغيل تطبيق Scala الخاص بك كعميل مستقل أو في حاوية ويب خفيفة (على سبيل المثال Netty إذا كنت تستخدم Play Framework). في هذه الحالة ، من المحتمل جدًا أن يفقد وقت تشغيل التطبيق بت التطبيق الذي يساعد JVM على القيام بسحر SOAP من أجلك ، وذلك بفضل إصدارات JRE الحديثة ومشروع Java Jigsaw. لا داعي للذعر ، فما عليك سوى إضافة عدد قليل من المكتبات إلى قائمة التبعية الخاصة بك ، أو رمي rt.jar واحد من توزيع JRE الخاص بك باعتباره تبعية غير مُدارة:
unmanagedJars in Test += Attributed.blank( file(System.getenv("JAVA_HOME") + "/jre/lib") )
كخلاصة
حسنًا ، كملخص: لقد تعلمنا بعض الشيء عن SOAP و WSDL ، ونأمل أن ندرك أنه ليس كابوسًا للعمل به ، وذلك بفضل كل منشئي الأكواد هذه ومواصفات WSDL المفرطة. لقد اكتشفنا أيضًا كيفية أتمتة مهمة قذرة ، ووجدنا طريقة للحفاظ على مستودعاتنا نائية ونظيفة من شفرة الغليان غير المرغوب فيها. استغرق الأمر بعض المعرفة من SBT لتكوين ترتيب التحويلات والتبعيات بشكل صحيح ، ولكن بعد كل شيء ، يجب أن تعمل بسلاسة تامة. لتبسيط الأمور بشكل أكبر ، قمت بعمل قالب صغير للأحذية من شأنه أن يساعدك على بدء مشروع في المرة القادمة: https://github.com/sainnr/sbt-scala-wsdl-template . آمل أن تستمتع بهذه الرحلة الصغيرة إلى الماضي!
مراجع
يرجى ترك لي رسالة إذا كنت ترى أي الأخطاء المطبعية أو الأخطاء.
نشرت هذه المقالة في الأصل في مدونتي fullstackme.co.uk مع بعض التعديلات.