Skip to content

8. الإصدار 4 – العميل/الخادم في بنية خدمة الويب

في هذا الإصدار الجديد، سيعمل تطبيق [Pam] في وضع العميل/الخادم ضمن بنية خدمات الويب. دعونا نلقي نظرة مجددة على بنية التطبيق السابق:

في الأعلى، مكنت طبقة الاتصال [C، RMI، S] من الاتصال الشفاف بين العميل [ui] والطبقة البعيدة [business]. سنستخدم بنية مماثلة، حيث سيتم استبدال طبقة الاتصال [C، RMI، S] بطبقة [C، HTTP / SOAP، S]:

يتميز بروتوكول HTTP/SOAP على بروتوكول RMI/EJB السابق بكونه متعدد المنصات. وبالتالي، يمكن كتابة خدمة الويب بلغة Java ونشرها على خادم Glassfish، في حين يمكن أن يكون العميل عميلاً .NET أو PHP.

سنطور هذه البنية في ثلاثة أوضاع مختلفة:

  1. سيتم توفير خدمة الويب بواسطة EJB [Business]
  2. سيتم توفير خدمة الويب بواسطة تطبيق ويب يستخدم [Business] EJB
  3. سيتم توفير خدمة الويب بواسطة تطبيق ويب يستخدم Spring

يمكن تنفيذ خدمة الويب بطرق مختلفة داخل خادم Java EE:

  • عن طريق فئة مزودة بعلامة @WebService تعمل في حاوية ويب
  • بواسطة EJB مرفقة بعلامة @WebService تعمل في حاوية EJB

سنبدأ بالبنية الأخيرة.

8.1. خدمة ويب يتم تنفيذها بواسطة EJB

8.1.1. جانب الخادم

8.1.1.1. مشروع NetBeans

لنبدأ بإنشاء مشروع Maven جديد يمثل نسخة من مشروع EJB [mv-pam-ejb-metier-dao-jpa-eclipselink]:

  

في البنية التالية:

ستكون طبقة [business] هي خدمة الويب التي تتصل بها طبقة [ui]. لا تحتاج هذه الفئة إلى تنفيذ واجهة. إن التعليقات التوضيحية هي التي تحول POJO (كائن جافا قديم عادي) إلى خدمة ويب. يتم تحويل فئة [Business]، التي تنفذ طبقة [business] أعلاه، على النحو التالي:


    <dependency>
      <groupId>org.swinglabs</groupId>
      <artifactId>swing-layout</artifactId>
      <version>1.0.3</version>
</dependency>
  • السطر 4: تعمل علامة @WebService على تحويل فئة [Business] إلى خدمة ويب. تعرض خدمة الويب طرقًا لعملائها. يجب أن تكون هذه الطرق مزودة بعلامة @WebMethod.
  • السطران 19 و 25: تصبح الطريقتان الخاصتان بفئة [Metier] طرقًا لخدمة الويب.
  • السطر 29: من المهم إزالة طرق الحصول والتعيين؛ وإلا فستُعرض في خدمة الويب، مما يتسبب في أخطاء أمنية.

يكتشف NetBeans إضافة هذه التعليقات التوضيحية، ثم يغير طبيعة المشروع:

في [1]، ظهرت شجرة [خدمات الويب] في المشروع. وهي تحتوي على خدمة الويب Metier وطريقتيها. يمكن نشر تطبيق الخادم [2]. يجب أن يكون خادم MySQL قيد التشغيل، ويجب أن تكون قاعدة البيانات [dbpam_eclipselink] موجودة ومملوءة. قد يكون من الضروري مسبقًا إزالة [3] EJBs من مشروع EJB للعميل/الخادم الذي تمت دراسته سابقًا لتجنب تعارض الأسماء. في الواقع، يتضمن مشروعنا الجديد نفس EJBs الموجودة في المشروع السابق.

في [1]، نرى تطبيق الخادم الخاص بنا قد تم نشره على خادم GlassFish. بمجرد نشر خدمة الويب، يمكن اختبارها:

  • في [1]، في المشروع الحالي، نختبر خدمة الويب [Metier]
  • يمكن الوصول إلى خدمة الويب عبر عناوين URL مختلفة. يتيح لك عنوان URL [2] اختبار خدمة الويب
  • في [3]، رابط إلى ملف XML الذي يحدد خدمة الويب. يحتاج عملاء خدمة الويب إلى معرفة عنوان URL لهذا الملف. يتم إنشاء طبقة العميل (الستوب) لخدمة الويب من هذا الملف.
  • في [4،5]، نموذج لاختبار الطرق التي تعرضها خدمة الويب. يتم عرض هذه الطرق مع معلماتها، والتي يمكن للمستخدم تحديدها.

على سبيل المثال، دعونا نختبر الطريقة [findAllEmployees]، التي لا تتطلب أي معلمات:

 

في الأعلى، نقوم باختبار الطريقة. ثم نتلقى الرد أدناه (عرض جزئي). يمكننا بالفعل رؤية الموظفين الاثنين مع مزاياهما. ندعو القارئ إلى اختبار الطريقة [4] بنفس الطريقة عن طريق تمرير المعلمات الثلاثة التي تتوقعها.

Image

8.1.2. جانب العميل

8.1.2.1. مشروع NetBeans الخاص بالعميل -console

سنقوم الآن بإنشاء مشروع Java من النوع [تطبيق Java] للجانب الخاص بالعميل من التطبيق. حتى يونيو 2012، لم يكن من الممكن إنشاء مشروع Maven لهذا العميل. تحدث خطأ، يبدو أنه معروف عبر الإنترنت ولكنه لا يزال دون حل.

 

بمجرد إنشاء المشروع، نحدد أنه سيكون عميلاً لخدمة الويب التي قمنا بنشرها للتو على خادم GlassFish:

  • في [2]، نختار المشروع الجديد ونضغط على زر [ملف جديد]
  • في [3]، نحدد أننا نريد إنشاء عميل خدمة ويب
  • في [4]، نختار مشروع NetBeans الخاص بخدمة الويب
  • في النافذة [5]، يتم سرد جميع المشاريع التي تحتوي على فرع [Web Services]؛ وهنا، يظهر فقط مشروع [mv-pam-ws-metier-dao-eclipselink].
  • يمكن لمشروع واحد نشر خدمات ويب متعددة. في [6]، نحدد خدمة الويب التي نريد الاتصال بها.
  • في [7]، يتم عرض عنوان URL الذي يحدد خدمة الويب. يتم استخدام عنوان URL هذا بواسطة أدوات البرمجيات التي تقوم بإنشاء طبقة العميل التي ستتفاعل مع خدمة الويب.
  • تتكون طبقة العميل [C] [1] التي سيتم إنشاؤها من مجموعة من فئات Java التي سيتم وضعها في نفس الحزمة. يتم تعيين اسم هذه الحزمة في [8].
  • بمجرد إكمال معالج إنشاء عميل خدمة الويب بالنقر فوق الزر [Finish]، يتم إنشاء الطبقة [C] الموضحة أعلاه.

وينعكس ذلك في عدد من التغييرات في المشروع:

  • في [10] أعلاه، تظهر شجرة [Generated Sources]، تحتوي على فئات الطبقة [C] التي تسمح للعميل [3] بالتواصل مع خدمة الويب. تسمح هذه الطبقة للعميل [3] بالتواصل مع طبقة [business] [4] كما لو كانت محلية وليست بعيدة.
  • في [11]، تظهر شجرة [Web Service References]، تسرد خدمات الويب التي تم إنشاء طبقة عميل لها.

لاحظ أنه في الطبقة [C] التي تم إنشاؤها [10]، نجد فئات تم نشرها على جانب الخادم: Indemnite، Cotisation، Employe، FeuilleSalaire، ElementsSalaire، Metier. Metier هي خدمة الويب، أما الفئات الأخرى فهي فئات مطلوبة من قبل هذه الخدمة. قد يشعر المرء بالفضول لفحص كودها. سنرى أن تعريف الفئات — التي تمثل، عند إنشائها، كائنات يتم التعامل معها بواسطة الخدمة — يتكون من تعريف حقول الفئة ووحدات الوصول إليها، بالإضافة إلى إضافة تعليقات توضيحية تتيح تسلسل الفئة إلى دفق XML. أصبحت فئة Metier واجهة تحتوي على الطريقتين اللتين تمت تعليقهما بـ @WebMethod. تؤدي كل منهما إلى ظهور فئتين، على سبيل المثال [CalculatePayroll.java] و [CalculatePayrollResponse.java]، حيث تغلف إحداهما استدعاء الطريقة والأخرى نتيجتها. أخيرًا، فئة MetierService هي الفئة التي تسمح للعميل بالحصول على مرجع لخدمة الويب Metier البعيدة:


package metier;
 
...
@WebService
@Stateless()
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class Metier implements IMetierLocal,IMetierRemote {
  
  // references on layers [DAO]
  @EJB
  private ICotisationDaoLocal cotisationDao = null;
  @EJB
  private IEmployeDaoLocal employeDao=null;
  @EJB
  private IIndemniteDaoLocal indemniteDao=null;
 
 
  // get your payslip
@WebMethod
  public FeuilleSalaire calculerFeuilleSalaire(String SS,
...
  }
 
  // list of employees
@WebMethod
   public List<Employe> findAllEmployes() {
...
  }
// important - no getters and setters for EJB
 }

تسترد طريقة getMetierPort في السطر 2 مرجعًا إلى خدمة الويب Metier البعيدة.

8.1.2.2. عميل وحدة التحكم لخدمة الويب Metier

كل ما تبقى هو كتابة عميل خدمة الويب Metier. ننسخ فئة [MainRemote] من مشروع [mv-pam-client-metier-dao-jpa-eclipselink] —الذي كان عميلاً لخادم EJB—إلى المشروع الجديد.

  • في [1]، فئة عميل خدمة الويب. تحتوي فئة [MainRemote] على أخطاء. لإصلاحها، سنبدأ بإزالة جميع عبارات [import] الموجودة في الفئة وإعادة إنشائها باستخدام خيار [Fix Imports]. وذلك لأن بعض الفئات التي تستخدمها فئة [MainRemote] أصبحت الآن جزءًا من حزمة [client] التي تم إنشاؤها.
  • في [3]، مقتطف الشفرة حيث يتم إنشاء مثيل لطبقة [business] [3]. يتم إنشاء المثيل باستخدام شفرة JNDI للحصول على مرجع إلى EJB بعيد.

نقوم بتحديث الكود على النحو التالي:

  • تمت إزالة كود JNDI
  • نظرًا لعدم وجود فئة [PamException] على جانب العميل، نقوم بإزالة كتلة catch المرتبطة بها للاحتفاظ فقط بكتلة catch الخاصة بالفئة الأصلية [Exception].
  • في [4]، ما زلنا بحاجة إلى الحصول على مرجع لخدمة الويب البعيدة [Metier] من أجل استدعاء أسلوبها [calculatePayroll].
  • في [5]، نستخدم الماوس لسحب الأسلوب [calculerFeuilleSalaire] من خدمة الويب [Metier] وإفلاته في [4]. يتم إنشاء الكود [6]. يمكن للمطور بعد ذلك تكييف هذا الكود العام.
  • في السطر 112، نرى أن [calculatePayroll] هي طريقة من فئة [client.Metier] (السطر 111). والآن بعد أن عرفنا كيفية الحصول على طبقة [metier]، يمكن إعادة كتابة الكود السابق على النحو التالي:
1
2
3
4
    @WebEndpoint(name = "MetierPort")
    public Metier getMetierPort() {
        return super.getPort(new QName("http://metier/", "MetierPort"), Metier.class);
}

يسترد السطر 7 مرجعًا إلى خدمة الويب Metier. وبمجرد الانتهاء من ذلك، يظل كود الفئة دون تغيير، باستثناء أنه في السطر 10، لا يتم التعامل مع النوع [Exception]، بل النوع الأكثر عمومية Throwable، وهو الفئة الأم لفئة Exception. في حالة حدوث استثناء، نعرض جميع أسبابه المتداخلة حتى السبب الجذري.

نحن جاهزون للاختبار:

  • تأكد من تشغيل نظام إدارة قواعد البيانات MySQL5، ومن إنشاء قاعدة بيانات dbpam_eclipselink وتهيئتها
  • تأكد من نشر خدمة الويب على خادم GlassFish
  • قم بإنشاء العميل (تنظيف وإنشاء)
  • قم بتكوين العميل للتشغيل
  
  • تشغيل العميل

النتائج في وحدة التحكم هي كما يلي:

...    
// it's okay - we can ask for the payslip
    FeuilleSalaire feuilleSalaire = null;
    Metier metier = null;
    try {
       // instantiation layer [metier]
      metier = new MetierService().getMetierPort();
       // wage sheet calculation
      feuilleSalaire = metier.calculerFeuilleSalaire(args[0], nbHeuresTravaillées, nbJoursTravaillés);
    } catch (Throwable th) {
       // exception chain
      System.out.println("Chaîne des exceptions --------------------------------------");
      System.out.println(th.getClass().getName() + ":" + th.getMessage());
      while (th.getCause() != null) {
        th = th.getCause();
        System.out.println(th.getClass().getName() + ":" + th.getMessage());
      }
      System.exit(1);
    }
     // quick viewing
...

مع التكوين التالي:

Image

نحصل على النتائج التالية:

...
Valeurs saisies :
N° de sécurité sociale de l'employé : 254104940426058
Nombre d'heures travaillées : 150
Nombre de jours travaillés : 20

Informations Employé : 
Nom : Jouveinal
Prénom : Marie
Adresse : 5 rue des oiseaux
...

لاحظ أنه في حين أن خدمة الويب [Metier] ترسل استثناءً من نوع [PamException]، فإن الاستثناء الذي يتلقاه العميل يكون من نوع [SOAPFaultException]. وحتى في سلسلة الاستثناءات، لا يظهر نوع [PamException].

8.1.3. عميل Swing لخدمة الويب Metier


المهمة: قم بنقل عميل Swing من مشروع [mv-pam-client-ejb-metier-dao-jpa-eclipselink] إلى المشروع الجديد بحيث يصبح هو أيضًا عميلاً لخدمة الويب التي تم نشرها على خادم GlassFish.


8.2. خدمة الويب التي تم تنفيذها بواسطة تطبيق ويب

نحن نعمل الآن ضمن إطار العمل المعماري التالي:

يتم توفير خدمة الويب بواسطة تطبيق ويب يعمل داخل حاوية الويب الخاصة بخادم GlassFish. ستعتمد خدمة الويب هذه على EJB [Metier]، الذي يتم نشره في حاوية EJB3.

8.2.1. جانب الخادم

نقوم بإنشاء تطبيق ويب:

  • في [1]، نقوم بإنشاء مشروع جديد
  • في [2]، هذا المشروع من نوع [تطبيق ويب]
  • في [3]، نسميه [mv-pam-ws-ejb-metier-dao-eclipselink]
  • في [4]، نختار Java EE 6
  • في [6]، يتم إنشاء المشروع

في الرسم التوضيحي أدناه، سيتم تشغيل تطبيق الويب الذي تم إنشاؤه في حاوية الويب. وسيستخدم EJB [Metier]، الذي سيتم نشره في حاوية EJB الخاصة بالخادم.

لضمان أن التطبيق الويب الذي تم إنشاؤه لديه حق الوصول إلى الفئات المرتبطة بـ EJB [Metier]، نضيف التبعية لخادم EJB [mv-pam-ejb-metier-dao-eclipselink] —التي تناولناها سابقًا—إلى مكتبات التطبيق الويب [mv-pam-ws-ejb-metier-dao-eclipselink].

  • في [1]، نضيف مشروعًا إلى تبعيات مشروع الويب؛
  • في [2]، نختار المشروع [mv-pam-ejb-metier-dao-eclipselink
  • في [3]، نوع التبعية هو ejb،
  • في [4]، يتم توفير نطاق التبعية، مما يعني أنه سيتم توفيرها بواسطة بيئة وقت التشغيل،
  • في [5]، تمت إضافة التبعية.

لإنشاء نفس خدمة الويب كما في السابق، نحتاج إلى:

  • إنشاء فئة مزودة بعلامة @WebService
  • مع طريقتين، calculerFeuilleSalaire و findAllEmployes، مع تعليق @WebMethod

نقوم بإنشاء فئة [PamWsEjbMetier] في حزمة [pam.ws]:

  

فيما يلي فئة [PamWsEjbMetier]:

1
2
3
4
Chaîne des exceptions --------------------------------------
javax.xml.ws.soap.SOAPFaultException:L'employé de n°[xx] est introuvable
com.sun.xml.internal.ws.developer.ServerSideException:L'employé de n°[xx] est introuvable
Java Result: 1
  • الأسطر 7–10: تستورد الفئة فئات من وحدة EJB [pam-serveurws-metier-dao-jpa-eclipselink]، التي تمت إضافة مشروع Maven الخاص بها إلى تبعيات المشروع.
  • السطر 12: الفئة هي خدمة ويب
  • السطر 13: تنفذ واجهة IMetier المحددة في وحدة EJB
  • السطران 18-19: يتم عرض الأسلوب `calculerFeuilleSalaire` كأسلوب خدمة ويب
  • السطران 23-24: يتم عرض طريقة `findAllEmployees` كطريقة لخدمة ويب
  • السطران 15-16: يتم إدخال الواجهة المحلية لـ EJB [Metier] في الحقل الموجود في السطر 16. نستخدم الواجهة المحلية لأن تطبيق الويب ووحدة EJB يعملان في نفس JVM.
  • السطران 20 و25: تقوم طريقتا `calculerFeuilleSalaire` و`findAllEmployes` بتفويض معالجتهما إلى الطرق التي تحمل الاسم نفسه في EJB [Metier]. وبالتالي، فإن الفئة لا تخدم سوى عرض طرق EJB [Metier] للعملاء البعيدين كطرق خدمة ويب.

في NetBeans، يُعرف تطبيق الويب بأنه يعرض خدمة ويب:

لنشر خدمة الويب على خادم GlassFish، يجب نشر كليهما:

  • وحدة الويب في حاوية الويب الخاصة بالخادم
  • وحدة EJB في حاوية EJB الخاصة بالخادم

للقيام بذلك، نحتاج إلى إنشاء [تطبيق مؤسسي] يقوم بنشر كلا الوحدتين في نفس الوقت. وللقيام بذلك، يجب تحميل كلا المشروعين في NetBeans [2].

بمجرد الانتهاء من ذلك، نقوم بإنشاء مشروع جديد [3].

  • في [4]، نختار نوع المشروع [تطبيق مؤسسي].
  • في [5]، نسمي المشروع
  • في [6]، نقوم بتكوين المشروع. سيكون إصدار Java EE هو Java EE 6. يمكن إنشاء مشروع مؤسسي باستخدام وحدتين: وحدة EJB ووحدة ويب. هنا، سيقوم المشروع المؤسسي بتغليف وحدة الويب ووحدة EJB اللتين تم إنشاؤهما وتحميلهما بالفعل في NetBeans. لذلك، لا نطلب إنشاء وحدات جديدة.
  • في [7]، يتم إنشاء مشروع المؤسسة [mv-pam-webapp-ear]. تم إنشاء مشروع Maven آخر في نفس الوقت [mv-pam-webapp]. لن نهتم به.
  • في [8]، نضيف التبعيات إلى مشروع المؤسسة
  • في [9]، نضيف مشروع الويب من نوع WAR،
  • في [10]، نضيف مشروع EJB من النوع ejb،
  • في [11]، مشروع المؤسسة مع تبعيتيه.

نقوم بإنشاء مشروع المؤسسة باستخدام Clean و Build. نحن على وشك الانتهاء من النشر على خادم GlassFish. قبل القيام بذلك، قد يكون من الضروري إيقاف تشغيل أي تطبيقات تعمل بالفعل على الخادم لتجنب تعارضات محتملة في أسماء EJB [11]:

يجب أن يكون خادم MySQL قيد التشغيل، ويجب أن تكون قاعدة البيانات [dbpam_eclipselink] متاحة ومملوءة. بمجرد الانتهاء من ذلك، يمكن نشر التطبيق المؤسسي [12]. في [13]، يمكننا أن نرى أنه تم نشره بنجاح على خادم GlassFish.

يمكننا اختبار خدمة الويب التي تم نشرها للتو:

  • في [1]، نطلب اختبار خدمة الويب [PamWsEjbMetier]
  • في [2]، صفحة الاختبار. نترك للقارئ إجراء الاختبارات.

8.2.2. جانب العميل


المهمة: باتباع الإجراء الموصوف في القسم 8.1.2.1، قم بإنشاء عميل وحدة تحكم لخدمة الويب السابقة.


8.3. خدمة ويب تم تنفيذها باستخدام Spring و Tomcat

نحن نعمل الآن ضمن إطار العمل المعماري التالي:

يتم توفير خدمة الويب بواسطة تطبيق ويب يعمل داخل حاوية الويب الخاصة بخادم Tomcat. وستكون بنية التطبيق على النحو التالي:

سنبني على مشروع [mv-pam-spring-hibernate] الذي تم إنشاؤه في القسم 5.11:

  

8.3.1. جانب الخادم

نقوم بإنشاء تطبيق Maven من نوع الويب باسم [mv-pam-ws-spring-tomcat] [1]:

نقوم بتعديل ملف [pom.xml] لتضمين التبعيات التالية [2]:

package pam.ws;

import java.util.List;
import javax.ejb.EJB;
import javax.jws.WebMethod;
import javax.jws.WebService;
import jpa.Employe;
import metier.FeuilleSalaire;
import metier.IMetier;
import metier.IMetierLocal;

@WebService
public class PamWsEjbMetier implements IMetier{

  @EJB
  private IMetierLocal metier;

  @WebMethod
  public FeuilleSalaire calculerFeuilleSalaire(String SS, double nbHeuresTravaillées, int nbJoursTravaillés) {
    return metier.calculerFeuilleSalaire(SS, nbHeuresTravaillées, nbJoursTravaillés);
  }

  @WebMethod
  public List<Employe> findAllEmployes() {
    return metier.findAllEmployes();
  }

}
  • الأسطر 3–7: التبعية لمشروع [spring-pam-jpa-hibernate
  • الأسطر 8–17: التبعيات على إطار عمل Apache CXF [http://cxf.apache.org/]. يسهل هذا الإطار إنشاء خدمات الويب.

يقدم ملف [pom.xml] هذا العديد من التبعيات [2].

لنعد إلى بنية التطبيق:

يتم التعامل مع المكالمات الموجهة إلى خدمة الويب التي سنقوم ببنائها بواسطة سيرفلت من إطار عمل CXF. وينعكس ذلك في ملف [WEB-INF/web.xml] على النحو التالي:


  <dependencies>
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>mv-pam-spring-hibernate</artifactId>
      <version>${project.version}</version>
    </dependency>
    <!-- Apache CXF dependencies -->
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-frontend-jaxws</artifactId>
      <version>2.2.12</version>
    </dependency>
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-transports-http</artifactId>
      <version>2.2.12</version>
    </dependency>
</dependencies>
  • يعتمد إطار عمل CXF على Spring. الأسطر 4–6: يتم إعلان مستمع. سيتم تحميل الفئة المقابلة في نفس وقت تحميل تطبيق الويب. وسيستخدم ملف تكوين Spring [WEB-INF/applicationContext.xml]:
  • الأسطر 8–12: خدمة CXF التي ستتعامل مع المكالمات الموجهة إلى خدمة الويب التي سنقوم بإنشائها،
  • الأسطر 13–16: ستكون عناوين URL التي تتعامل معها خدمة CXF على شكل /ws/*. أما العناوين الأخرى فلن تتعامل معها خدمة CXF.

لتعريف خدمة الويب، نقوم بتعريف واجهة وتطبيقها:

ستكون الواجهة [IWsMetier] على النحو التالي:


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name>mv-pam-ws-spring-tomcat</display-name>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
<!--   CXF configuration -->
  <servlet>
    <servlet-name>CXFServlet</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>CXFServlet</servlet-name>
    <url-pattern>/ws/*</url-pattern>
  </servlet-mapping>
  <session-config>
    <session-timeout>
      30
    </session-timeout>
  </session-config>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>
  • السطر 7: واجهة [IWsMetier] مشتقة من واجهة [IMetier] في طبقة [business] لمشروع [mv-pam-spring-hibernate
  • السطر 6: واجهة [IWsMetier] هي واجهة خدمة ويب.

فئة التنفيذ لهذه الواجهة هي كما يلي:


package pam.ws;
 
import javax.jws.WebService;
import metier.IMetier;
 
@WebService
public interface IWsMetier extends IMetier{
 
}
  • السطر 11: تنفذ فئة [PamWsMetier] الواجهة المحددة سابقًا،
  • السطر 10: يُعرّف الفئة كخدمة ويب،
  • السطر 14: سيتم إدخال طبقة [business] بواسطة Spring،
  • السطران 21 و26: تعمل علامة @WebMethod على تحويل الأسلوب إلى أسلوب معروض بواسطة خدمة الويب،
  • السطران 23 و28: يتم تنفيذ الطرق باستخدام طبقة [business].

لا يزال يتعين علينا تعريف محتويات ملف تكوين Spring [applicationContext.xml]:

محتواه كما يلي:


package pam.ws;
 
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebService;
import jpa.Employe;
import metier.FeuilleSalaire;
import metier.IMetier;
 
@WebService
public class PamWsMetier implements IWsMetier {
 
  // business layer
  private IMetier metier;
 
  // manufacturer
  public PamWsMetier(){
 
  }
 
  @WebMethod
  public FeuilleSalaire calculerFeuilleSalaire(String SS, double nbHeuresTravaillees, int nbJoursTravailles) {
    return metier.calculerFeuilleSalaire(SS, nbHeuresTravaillees, nbJoursTravailles);
  }
 
  @WebMethod
  public List<Employe> findAllEmployes() {
    return metier.findAllEmployes();
  }
 
  // getters and setters
 
  public void setMetier(IMetier metier) {
    this.metier = metier;
  }
 
}
  • الأسطر 13–15: يتم استيراد ملفات تكوين Apache CXF. يتم البحث عن هذه الملفات في مسار فئات المشروع (سمة classpath
  • الأسطر 4 و9 و10: يتم إعلان مساحات الأسماء الخاصة بـ Apache CXF،
  • السطر 18: يتم استيراد ملف تكوين Spring لمشروع [mv-pam-spring-hibernate
  • الأسطر 21–23: تعريف حبة خدمة الويب مع تبعيتها لطبقة [business] (السطر 22)،
  • الأسطر 24-27: تعريف خدمة الويب نفسها،
    • السطر 25: حبة Spring التي تنفذ خدمة الويب هي تلك المحددة في السطر 21؛
    • السطر 26: يحدد عنوان URL الذي ستتوفر فيه خدمة الويب، وهو هنا /business. وبالاقتران مع التنسيق المطلوب لعناوين URL التي يعالجها Apache CXF (انظر ملف web.xml)، يصبح عنوان URL هذا /ws/business.

مشروعنا جاهز للتشغيل. نقوم بتشغيله (Run) ونطلب عنوان URL [http://localhost:8080/mv-pam-ws-spring-tomcat/ws] في متصفح:

Image

تسرد الصفحة جميع خدمات الويب التي تم نشرها. هنا، لا يوجد سوى خدمة واحدة. نتبع رابط WSDL:

النص المعروض [1] مأخوذ من ملف XML يحدد وظائف خدمة الويب، وكيفية استدعائها، والاستجابات التي ترسلها. لاحظ عنوان URL [2] لملف WSDL هذا. يجب على جميع عملاء خدمة الويب معرفته.

8.3.2. جانب العميل


المهمة: باتباع الإجراء الموضح في القسم 8.1.2.1، قم بإنشاء عميل وحدة التحكم لخدمة الويب السابقة.


ملاحظة: لتحديد عنوان URL لملف WSDL الخاص بخدمة الويب، اتبع الخطوات التالية:

أدخل عنوان URL المذكور سابقًا في [2] في [3].