Skip to content

7. نسخه ۳: انتقال برنامه PAM به سرور برنامه GlassFish

برنامه این است که فایل‌های EJB را از لایه‌های [metier] و [DAO] معماری OpenEJB قرار دهیم / معماری EclipseLink را در یک کانtejner سرور برنامه‌ای GlassFish قرار دهید.

پیاده‌سازی فعلی با OpenEJB / EclipseLink

همان‌طور که در بالا نشان داده شده است، لایه [ui] از رابط دور لایه [metier] استفاده می‌کند.

ما دو زمینهٔ اجرای زیر را آزمایش کردیم: local و distant. در حالت دوم، لایه [ui] مشتری لایه [metier] بود که توسط EJB پیاده‌سازی شده بود. برای کار در حالت کلاینت/سرور، که در آن کلاینت و سرور در دو نمونهٔ مختلف JVM اجرا می‌شوند، لایه‌های [metier, DAO, jpa] را روی سرور جاوای GlassFish EE مستقر خواهیم کرد. این سرور همراه با NetBeans عرضه می‌شود.

پیاده‌سازی‌ای که باید با سرور GlassFish ساخته شود

  • لایه [ui] در یک محیط جاوا SE (ویرایش استاندارد) اجرا خواهد شد.
  • لایه‌های [metier, DAO, JPA] در یک محیط Java EE (نسخه سازمانی) روی سرور GlassFish v3 اجرا خواهند شد
  • کلاینت از طریق یک شبکه TCP/IP با سرور ارتباط برقرار خواهد کرد. ارتباطات شبکه برای توسعه‌دهنده شفاف است، اگرچه باید آگاه باشد که کلاینت و سرور برای برقراری ارتباط به جای ارجاع اشیاء، اشیاء سریالی‌شده را مبادله می‌کنند. پروتکل شبکه‌ای که برای این ارتباط استفاده می‌شود RMI (فراخوانی متد از راه دور) نامیده می‌شود، پروتکلی که تنها بین دو برنامه جاوا قابل استفاده است.
  • پیاده‌سازی JPA که در سرور GlassFish استفاده می‌شود، EclipseLink خواهد بود.

7.1. بخش server- e از برنامهٔ کلاینت/سرور PAM

7.1.1. معماری برنامه

در اینجا ما در حال بررسی مؤلفهٔ سرور هستیم که توسط کانتینر EJB3 روی سرور GlassFish میزبانی خواهد شد:

هدف این است که آنچه قبلاً با کانتینر OpenEJB توسعه یافته و آزمایش شده است را به سرور GlassFish منتقل کنیم. این مزیت OpenEJB و به طور کلی‌تر، کانتینرهای تعبیه‌شده EJB است: آنها به ما امکان می‌دهند برنامه را در یک محیط اجرایی ساده‌شده آزمایش کنیم. پس از آزمایش برنامه، تنها کاری که باقی می‌ماند، انتقال آن به یک سرور هدف، در این مورد سرور GlassFish، است.

7.1.1.1. پروژه NetBeans

بیایید با ایجاد یک پروژه جدید NetBeans شروع کنیم:

  • در [1]، پروژه جدید
  • در [2]، دسته Maven و در [3]، نوع EJB ماژول را انتخاب کنید. هدف ساخت پروژه‌ای است که توسط یک کانتینر EJB، یعنی سرور GlassFish، میزبانی و اجرا شود.
  • با استفاده از دکمه [4a]، پوشه والد پوشه پروژه را انتخاب کنید یا نام آن را مستقیماً در [4b] وارد کنید.
  • در [5]، برای پروژه یک نام انتخاب کنید
  • در [6]، سرور برنامه‌ای را که روی آن اجرا خواهد شد، انتخاب کنید. مورد انتخاب‌شده در اینجا یکی از سرورهای قابل مشاهده در زبانه [Runtime / Servers] است، که در این مورد GlassFish v3 می‌باشد.
  • در [7]، نسخهٔ جاوا را انتخاب کنید EE.
  • در [1]، پروژه جدید. این پروژه از چند جهت با یک پروژه استاندارد جاوا متفاوت است:
    • یک شاخه [Other Sources] [2] به طور خودکار ایجاد می‌شود. به طور خاص، این شاخه حاوی فایل [persistence.xml] خواهد بود که لایه JPA را پیکربندی می‌کند؛
    • اگر پروژه را بسازید، وابستگی‌ای به نام [javaee-api-6.0] ظاهر می‌شود. این از نوع provided است زیرا در زمان اجرا توسط کانتینر GlassFish EJB ارائه می‌شود.

7.1.1.2. پیکربندی لایه پایداری

با «پی‌کنفورم کردن لایه پایداری»، منظور ایجاد فایل [persistence.xml] است که تعریف می‌کند:

  • پیاده‌سازی JPA که باید استفاده شود
  • تعریف منبع داده‌ای که توسط لایه JPA استفاده می‌شود. این یک منبع JDBC خواهد بود که توسط سرور GlassFish مدیریت می‌شود.

می‌توانید به شرح زیر اقدام کنید. ابتدا، در زبانه [Runtime / Databases]، یک اتصال به پایگاه داده MySQL5 / dbpam_eclipselink ایجاد کنید:

پس از انجام این کار، می‌توانیم به ایجاد منبع JDBC که توسط ماژول EJB استفاده می‌شود، بپردازیم:

  • در [1]، یک فایل جدید ایجاد کنید – اطمینان حاصل کنید که پروژه EJB قبل از انجام این عملیات انتخاب شده باشد
  • در [2]، پروژه EJB
  • برای [3]، دسته [Glassfish] را انتخاب کنید
  • در [4]، شما می‌خواهید یک منبع JDBC ایجاد کنید
  • در [5]، مشخص کنید که منبع JDBC از یک استخر اتصال جدید استفاده خواهد کرد. توجه داشته باشید که استخر اتصال، مجموعه‌ای از اتصالات باز است که برای تسریع تعاملات برنامه با پایگاه داده استفاده می‌شود.
  • در [6]، نام JNDI را به منبع JDBC که ایجاد شده است، اختصاص دهید. این نام می‌تواند هر چیزی باشد، اما اغلب به شکل jdbc/nom است. این نام، JNDI، در فایل [persistence.xml] برای مشخص کردن منبع داده‌ای که پیاده‌سازی JPA باید از آن استفاده کند، به کار می‌رود.
  • در [7]، هر نامی را که مایلید برای استخر اتصال آینده انتخاب کنید
  • در لیست کشویی [8]، اتصال JDBC را که قبلاً روی پایگاه داده MySQL / dbpam_eclipselink ایجاد شده است، انتخاب کنید.
  • در [9]، خلاصه‌ای از ویژگی‌های استخر اتصال نمایش داده می‌شود – همه چیز را همان‌طور که هست رها کنید
  • به [10]؛ در اینجا می‌توانید چندین مورد از ویژگی‌های استخر اتصال را مشخص کنید – مقادیر پیش‌فرض را حفظ کنید
  • در [11]، پس از تکمیل ویزارد برای ایجاد یک منبع JDBC برای ماژول EJB، فایلی به نام [glassfish-resources.xml] در شاخه [Other Sources] ایجاد شد. محتویات این فایل به شرح زیر است:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
  <jdbc-resource enabled="true" jndi-name="jdbc/dbpam_eclipselink" object-type="user" pool-name="dbpamEclipselinkConnectionPool">
    <description/>
  </jdbc-resource>
  <jdbc-connection-pool allow-non-component-callers="false" associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" connection-validation-method="auto-commit" datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" fail-all-connections="false" idle-timeout-in-seconds="300" is-connection-validation-required="false" is-isolation-level-guaranteed="true" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="false" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="dbpamEclipselinkConnectionPool" non-transactional-connections="false" pool-resize-quantity="2" res-type="javax.sql.DataSource" statement-timeout-in-seconds="-1" steady-pool-size="8" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">
    <property name="URL" value="jdbc:mysql://localhost:3306/dbpam_eclipselink"/>
    <property name="User" value="root"/>
    <property name="Password" value=""/>
  </jdbc-connection-pool>
</resources>

فایل [glassfish-resources.xml] یک فایل XML است که حاوی تمام داده‌های جمع‌آوری‌شده توسط جادوگر است. این فایل توسط NetBeans هنگام استقرار ماژول EJB در سرور GlassFish برای درخواست ایجاد منبع JDBC مورد نیاز این ماژول استفاده خواهد شد.

اکنون می‌توانیم فایل [persistence.xml] را ایجاد کنیم که لایه JPA ماژول EJB را پیکربندی خواهد کرد:

  • در [1] یک فایل جدید ایجاد کنید – اطمینان حاصل کنید که پروژه EJB قبل از انجام این عملیات انتخاب شده باشد
  • در [2]، پروژه EJB
  • در [3]، دسته [Persistence] را انتخاب کنید
  • در [4]، شما می‌خواهید یک واحد پایداری ایجاد کنید
  • به [5]، یک نام برای واحد پایداری بدهید
  • در [6]، چندین پیاده‌سازی (JPA) پیشنهاد شده است. در اینجا، ما [EclipseLink] را انتخاب خواهیم کرد. پیاده‌سازی‌های دیگر نیز می‌توانند مورد استفاده قرار گیرند، به شرطی که کتابخانه‌های پیاده‌سازی‌کننده آن‌ها در کنار کتابخانه‌های سرور GlassFish قرار داده شوند.
  • در لیست کشویی [7]، منبع داده JDBC [jdbc/dbpam_eclipselink] را که به تازگی ایجاد شده است، انتخاب کنید.
  • در [8] مشخص کنید که تراکنش‌ها توسط کانتینر EJB مدیریت می‌شوند
  • در [9]، مشخص کنید که هنگام استقرار ماژول EJB به سرور، هیچ عملیاتی روی منبع داده انجام نشود. این به این دلیل است که ماژول EJB از پایگاه داده [dbpam_eclipselink] که قبلاً ایجاد شده است استفاده خواهد کرد.
  • در پایان جادوگر، فایلی به نام [persistence.xml] ([10]) ایجاد شد. محتویات آن به شرح زیر است:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="mv-pam-ejb-metier-dao-eclipselinkPU" transaction-type="JTA">
    <jta-data-source>jdbc/dbpam_eclipselink</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties/>
  </persistence-unit>
</persistence>
  • خط ۳: نام واحد پایداری [mv-pam-ejb-metier-dao-eclipselinkPU] و نوع تراکنش (JTA برای یک کانتینر EJB)
  • خط ۵: نام JNDI منبع داده‌ای که توسط لایه پایداری استفاده می‌شود: jdbc/dbpam_eclipselink
  • خط ۶: انتیت‌های JPA مشخص نشده‌اند. آنها در کلاس‌پث ماژول EJB جستجو خواهند شد.
  • نام پیاده‌سازی JPA (Hibernate، EclipseLink و غیره) که در حال استفاده است مشخص نشده است. در این صورت، GlassFish v3 به‌طور پیش‌فرض از EclipseLink استفاده می‌کند.

7.1.1.3. وارد کردن لایه‌های [jpa, DAO, metier]

اکنون که فایل [persistence.xml] تعریف شده است، می‌توانیم لایه‌های [metier, dao, jpa] را از برنامه سازمانی [pam] به پروژه وارد کنیم:

این سه لایه با لایه‌های موجود در OpenEJB یکسان هستند. ما می‌توانیم به سادگی آن‌ها را بین دو پروژه کپی و پیست کنیم. کاری که اکنون انجام خواهیم داد همین است:

  • در [1]، نتیجه کپی کردن بسته‌های [jpa, dao, metier, exception] از پروژه [mv-pam-openejb-eclipselink] به ماژول EJB [mv-pam-ejb-metier-dao-jpa-eclipselink]

7.1.1.4. پیکربندی سرور GlassFish

اکنون باید سرور GlassFish را از دو جنبه پیکربندی کنیم:

  • لایه JPA توسط EclipseLink پیاده‌سازی شده است. ما باید اطمینان حاصل کنیم که سرور GlassFish کتابخانه‌های مربوط به این پیاده‌سازی، JPA، را در اختیار دارد.
  • منبع داده یک پایگاه داده MySQL است. باید اطمینان حاصل کنیم که سرور GlassFish درایور JDBC برای این SGBD را دارد.

ممکن است هنگام استقرار ماژول EJB متوجه شوید که این کتابخانه‌ها وجود ندارند. در اینجا یکی از چندین روش برای افزودن کتابخانه‌های گمشده به سرور GlassFish آورده شده است:

  • به [1]، ویژگی‌های سرور GlassFish را مشاهده کنید
  • در [2]، به پوشه domains سرور توجه کنید. ما به این پوشه <domains> خواهیم گفت.
  • در پوشه <domains>\domain1\lib، کتابخانه‌های گمشده را قرار دهید. در این مثال، کتابخانه‌های Hibernate (lib/hibernate-tools) و درایور JDBC از MySQL (lib/misc) اضافه شده‌اند. به طور پیش‌فرض، سرور GlassFish شامل کتابخانه‌های EclipseLink است. بنابراین، ما فقط درایور JDBC را از MySQL اضافه خواهیم کرد.
  • به [1]؛ در زبانه [Services]، سرور GlassFish v3 را راه‌اندازی می‌کنیم
  • به [2]؛ اکنون فعال است

7.1.1.5. استقرار ماژول EJB

اکنون ما ماژول EJB را به سرور GlassFish مستقر می‌کنیم:

  • در [1]، ماژول EJB مستقر شد
  • به [2]، درخت سرور GlassFish تازه می‌شود
  • به [3]؛ پس از استقرار، ماژول EJB در شاخه [Applications] سرور GlassFish ظاهر می‌شود
  • در [4]، منبع JDBC [jdbc / dbpam_eclipselink] روی سرور GlassFish ایجاد شده است. به عنوان یادآوری، ما این مورد را در بخش 7.1.1.2 تعریف کردیم.

در حین استقرار، سرور GlassFish اطلاعات جالبی را در کنسول ثبت می‌کند:

INFO: Realm admin-realm of classtype com.sun.enterprise.security.auth.realm.file.FileRealm successfully created.
....
INFO: Portable JNDI names for EJB IndemniteDao : [java:global/pam-serveur-metier-dao-jpa-eclipselink/IndemniteDao!DAO.IIndemniteDaoLocal, java:global/pam-serveur-metier-dao-jpa-eclipselink/IndemniteDao!DAO.IIndemniteDaoRemote]
INFO: Glassfish-specific (Non-portable) JNDI names for EJB IndemniteDao : [DAO.IIndemniteDaoRemote#DAO.IIndemniteDaoRemote, DAO.IIndemniteDaoRemote]
...
INFO: Portable JNDI names for EJB CotisationDao : [java:global/pam-serveur-metier-dao-jpa-eclipselink/CotisationDao!DAO.ICotisationDaoLocal, java:global/pam-serveur-metier-dao-jpa-eclipselink/CotisationDao!DAO.ICotisationDaoRemote]
INFO: Glassfish-specific (Non-portable) JNDI names for EJB CotisationDao : [DAO.ICotisationDaoRemote, DAO.ICotisationDaoRemote#DAO.ICotisationDaoRemote]
INFO: Portable JNDI names for EJB Metier : [java:global/pam-serveur-metier-dao-jpa-eclipselink/Metier!metier.IMetierRemote, java:global/pam-serveur-metier-dao-jpa-eclipselink/Metier!metier.IMetierLocal]
INFO: Glassfish-specific (Non-portable) JNDI names for EJB Metier : [metier.IMetierRemote#metier.IMetierRemote, metier.IMetierRemote]
...
INFO: Portable JNDI names for EJB EmployeDao : [java:global/pam-serveur-metier-dao-jpa-eclipselink/EmployeDao!DAO.IEmployeDaoLocal, java:global/pam-serveur-metier-dao-jpa-eclipselink/EmployeDao!DAO.IEmployeDaoRemote]
INFO: Glassfish-specific (Non-portable) JNDI names for EJB EmployeDao : [DAO.IEmployeDaoRemote#DAO.IEmployeDaoRemote, DAO.IEmployeDaoRemote]
INFO: pam-serveur-metier-dao-jpa-eclipselink was successfully deployed in 12 891 milliseconds.

توجه داشته باشید که در خطوط

  • ۳، ۶، ۸ و ۱۱، نام‌های قابل حمل JNDI نمونه‌های مستقر شده EJB. جاوا EE ۶ مفهوم نام قابل حمل JNDI را معرفی کرد. این نشان می‌دهد که نام JNDI توسط همهٔ سرورهای Java EE 6 شناسایی می‌شود. با Java EE 5، نام‌های JNDI مختص سروری هستند که استفاده می‌شود.
  • ۴، ۷، ۹، ۱۲: نام ماژول‌های JNDI که در قالبی اختصاصی برای GlassFish v3 مستقر شده‌اند.

این نام‌ها برای اپلیکیشن کنسولی که قصد داریم برای استفاده از ماژول مستقرشده EJB بنویسیم، مفید خواهند بود.

7.2. کنسول کلاینت – نسخهٔ ۱

اکنون که بخش سمت سرور برنامهٔ کلاینت/سرور خود را مستقر کرده‌ایم، به بررسی مؤلفهٔ سمت کلاینت [1] می‌پردازیم:

7.2.1. پروژه کلاینت

ما یک پروژهٔ جدید Maven از نوع [Java Application] به نام [mv-pam-client-ejb-metier-dao-eclipselink] ایجاد می‌کنیم:

  • در [1]، پروژهٔ مشتری

در فایل [pom.xml]، وابستگی‌های زیر را اضافه می‌کنیم:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>istia.st</groupId>
  <artifactId>mv-pam-client-ejb-metier-dao-eclipselink</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>mv-pam-client-ejb-metier-dao-eclipselink</name>
  <url>http://maven.apache.org</url>
  <repositories>
    <repository>
      <url>http://download.eclipse.org/rt/eclipselink/maven.repo/</url>
      <id>eclipselink</id>
      <layout>default</layout>
      <name>Repository for library Library[eclipselink]</name>
    </repository>    
    <repository>
      <url>http://repo1.maven.org/maven2/</url>
      <id>swing-layout</id>
      <layout>default</layout>
      <name>Repository for library Library[swing-layout]</name>
    </repository>
  </repositories>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.glassfish.appclient</groupId>
      <artifactId>gf-client</artifactId>
      <version>3.1.1</version>
    </dependency>    
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>mv-pam-ejb-metier-dao-eclipselink</artifactId>
      <version>${project.version}</version>
      <type>ejb</type>
    </dependency>
    <dependency>
      <groupId>org.swinglabs</groupId>
      <artifactId>swing-layout</artifactId>
      <version>1.0.3</version>
    </dependency>
  </dependencies>
</project>
  • خطوط ۳۱–۳۵: وابستگی به کتابخانه [gf-client]، که به کلاینت Classfish امکان می‌دهد با یک سرور راه دور ارتباط برقرار کند،
  • خطوط ۳۶–۴۱: وابستگی به پروژه Maven برای ماژول EJB. در اینجا، می‌خواهیم تعاریف موجودیت‌های JPA و انواع رابط‌ها، و همچنین کلاس استثنای [PamException] را بازیابی کنیم،

از پروژه [mv-pam-openejb-eclipselink]، کلاس [MainRemote] را کپی می‌کنیم:

کلاس [MainRemote] باید یک مرجع به EJB را از لایه [metier] دریافت کند. کد کلاس [MainRemote] به شرح زیر تغییر می‌کند:


// مشکلی نیست – می‌توانیم فیش حقوقی را درخواست کنیم
    FeuilleSalaire feuilleSalaire = null;
    IMetierRemote metier = null;
    try {
      // زمینه JNDI روی سرور GlassFish
      InitialContext initialContext = new InitialContext();
      // مصالحه‌سازی لایه کسب‌وکار
      metier = (IMetierRemote) initialContext.lookup("java:global/istia.st_mv-pam-ejb-metier-dao-eclipselink_ejb_1.0-SNAPSHOT/Metier!metier.IMetierRemote");
      // محاسبه فیش حقوقی
      feuilleSalaire = metier.calculerFeuilleSalaire(args[0], nbHeuresTravaillées, nbJoursTravaillés);
    } catch (PamException ex) {
      System.err.println("L'erreur suivante s'est produite : "
              + ex.getMessage());
      return;
    } catch (Exception ex) {
      System.err.println("L'erreur suivante s'est produite : "
              + ex.toString());
      return;
    }
  • خط ۶: инициалиزه‌سازی زمینه JNDI روی سرور GlassFish.
  • خط ۸: از این زمینه JNDI درخواست می‌شود تا مرجعی به رابط دوردست لایه [metier] ارائه دهد. بر اساس لاگ‌های GlassFish، می‌دانیم که رابط دوردست لایه [metier] دو نام ممکن دارد:
Infos: EJB5181:Portable JNDI names for EJB Metier: [java:global/istia.st_mv-pam-ejb-metier-dao-eclipselink_ejb_1.0-SNAPSHOT/Metier!metier.IMetierLocal, java:global/istia.st_mv-pam-ejb-metier-dao-eclipselink_ejb_1.0-SNAPSHOT/Metier!metier.IMetierRemote]
Infos: EJB5182:Glassfish-specific (Non-portable) JNDI names for EJB Metier: [metier.IMetierRemote#metier.IMetierRemote, metier.IMetierRemote]

خط ۱: نام JNDI، که می‌توان از آن با هر سرور برنامه‌ای (JAVA، EE و غیره) استفاده کرد. خط ۲: نام JNDI، که مختص GlassFish است. در کد، در خط ۹، از نام قابل حمل JNDI استفاده می‌کنیم.

  • بقیه کد بدون تغییر باقی می‌ماند

در [1]، پروژه را طوری پیکربندی می‌کنیم که کلاس [MainRemote] را با آرگومان‌ها اجرا کند. اگر همه چیز به‌خوبی پیش برود، اجرای پروژه نتیجه زیر را تولید می‌کند:

run:
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
Ville : St Corentin
Code Postal : 49203
Indice : 2

Informations Cotisations : 
CSGRDS : 3.49 %
CSGD : 6.15 %
Retraite : 7.88 %
Sécurité sociale : 9.39 %

Informations Indemnités : 
Salaire horaire : 2.1 euro
Entretien/jour : 2.1 euro
Repas/jour : 3.1 euro
Congés Payés : 15.0 %

Informations Salaire : 
Salaire de base : 362.25 euro
Cotisations sociales : 97.48 euro
Indemnités d'entretien : 42.0 euro
Indemnités de repas : 62.0 euro
Salaire net : 368.77 euro

BUILD SUCCESSFUL (total time: 2 seconds)

اگر شماره بیمه ملی نادرستی در ویژگی‌ها وارد شود، نتیجه زیر به دست می‌آید:

1
2
3
run:
L'erreur suivante s'est produite : L'employé de n°[254104940426058x] est introuvable
BUILD SUCCESSFUL (total time: 2 seconds)

7.3. کلاینت کنسول – نسخه ۲

در نسخه‌های قبلی، محیط JNDI روی سرور GlassFish با استفاده از فایلی به نام [jndi.properties] که در جایی از آرشیوهای پروژه قرار دارد، پیکربندی می‌شد. محتوای پیش‌فرض آن به شرح زیر است:


#دسترسی به سرور برنامه Sun از طریق JNDI
java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory
java.naming.factory.url.pkgs=com.sun.enterprise.naming
# برای افزودن یک javax.naming.spi.StateFactory برای CosNaming که
#از RMI-IIOP پویا پشتیبانی می‌کند.
java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl
org.omg.CORBA.ORBInitialHost=localhost
org.omg.CORBA.ORBInitialPort=3700

خطوط ۷ و ۸ ماشین میزبان سرویس JNDI و پورت گوش‌دادن آن را مشخص می‌کنند. این فایل به شما اجازه نمی‌دهد تا به سرور JNDI غیر از localhost یا سروری که روی پورتی غیر از 3700 در حال اجرا است، درخواست دهید. اگر می‌خواهید این دو پارامتر را تغییر دهید، می‌توانید فایل [jndi.properties] خود را ایجاد کنید یا از پیکربندی Spring استفاده کنید. ما تکنیک دوم را نشان خواهیم داد.

ما با ایجاد یک پروژه جدید بر اساس پروژه اولیه [pam-client-metier-dao-jpa-eclipselink] شروع می‌کنیم.

  • به [1]، پروژه جدید تبدیل می‌شود.
  • به [2]، فایل پیکربندی Spring [spring-config-client.xml]. محتوای آن به شرح زیر است:

فایل پیکربندی Spring به شرح زیر است:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
       http://www.springframework.org/schema/jee
       http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">

  <!--شغل -->
  <jee:jndi-lookup id="metier" jndi-name="java:global/istia.st_mv-pam-ejb-metier-dao-eclipselink_ejb_1.0-SNAPSHOT/Metier!metier.IMetierRemote">
    <jee:environment>
      java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory
      java.naming.factory.url.pkgs=com.sun.enterprise.naming
      java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl
      org.omg.CORBA.ORBInitialHost=localhost
      org.omg.CORBA.ORBInitialPort=3700
    </jee:environment>
  </jee:jndi-lookup>
</beans>

در اینجا از تگ <jee> (خط ۱۴) استفاده می‌کنیم که در Spring 2.0 معرفی شد. استفاده از این تگ مستلزم تعریف اسکیمای مربوطه در خطوط ۴، ۱۰ و ۱۱ است.

  • خط ۱۴: تگ <jee:jndi-lookup> برای بازیابی یک مرجع به یک شیء از یک سرویس JNDI استفاده می‌شود. در اینجا، بیان با نام «metier» با منبع JNDI مرتبط شده است که به EJB و [Metier] پیوند دارد. نام JNDI که در اینجا استفاده شده، نام قابل حمل (Java EE 6) برای EJB است.
  • محتویات فایل [jndi.properties] به محتویات تگ <jee:environment> (خط 15) تبدیل می‌شوند که برای تعریف پارامترهای اتصال سرویس JNDI استفاده می‌شود.

کلاس اصلی [MainRemote] به شرح زیر تغییر می‌کند:

...
     // بسیار خب – می‌توانیم فیش حقوقی را درخواست کنیم
    FeuilleSalaire feuilleSalaire = null;
    IMetierRemote metier=null;
    try {
       // مصداق‌سازی لایه [metier]
      ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config-client.xml");
      metier = (IMetierRemote) ctx.getBean("metier");
       // محاسبه فیش حقوقی
      feuilleSalaire = metier.calculerFeuilleSalaire(args[0], nbHeuresTravaillées, nbJoursTravaillés);
    } catch (PamException ex) {
      System.err.println("L'erreur suivante s'est produite : "
              + ex.getMessage());
      return;
    } catch (Exception ex) {
      System.err.println("L'erreur suivante s'est produite : "
              + ex.toString());
      return;
    }
    ...

خطوط ۷–۸: از Spring خواسته شده است تا مرجع نوع [IMetierRemote] را در لایه [metier] فراهم کند. این راه‌حل انعطاف‌پذیری را به معماری ما می‌آورد. در واقع، اگر EJB از لایه [metier] محلی شود، c.a.d. در صورتی که در همان JVM به عنوان [MainRemote] کلاینت ما اجرا شود، کد کلاینت بدون تغییر باقی می‌ماند. فقط محتویات فایل [spring-config-client.xml] تغییر می‌کرد. در این صورت ما پیکربندی‌ای مشابه معماری Spring / JPA مورد بحث در بخش 5.11 خواهیم داشت.

از خوانندگان دعوت می‌شود تا این نسخه جدید را آزمایش کنند.

7.4. کلاینت Swing

اکنون کلاینت swing را برای برنامهٔ کلاینت/سرور EJB خود می‌سازیم.

فایل [pom.xml] باید وابستگی لازم به برنامه‌های Swing را داشته باشد:


    <dependency>
      <groupId>org.swinglabs</groupId>
      <artifactId>swing-layout</artifactId>
      <version>1.0.3</version>
</dependency>

در بالا، کلاس [PamJFrame] در اصل برای اجرا در محیط Spring / JPA نوشته شده بود:

اکنون این کلاس باید به کلاینت راه دور EJB مستقرشده بر روی سرور GlassFish تبدیل شود.


تمرین عملی: با پیروی از مثال کلاینت کنسول [ui.console.MainRemote] در پروژه، نحوه عملکرد [doMyInit] را تغییر دهید (به بخش 5.12.4 مراجعه کنید) در کلاس [PamJFrame] به منظور دریافت مرجعی به لایه [metier] که اکنون راه دور است.