Enterprise JavaBeans

Enterprise JavaBeans (אנטרפרייז ג'אווה בינז; בקיצור: EJB, וברבים: EJBs) היא ארכיטקטורת רכיבים לצד-שרת המשמשת ליצירת יישומי enterprise מודולריים.
המפרט של EJB הוא אחד מבין ממשקי תכנות היישומים (APIs) הנכללים במפרט של EJB .Java Enterprise Edition הוא מודל צד-שרת שתפקידו לכמס את הלוגיקה העסקית של יישום. המפרט של EJB פותח במקור על ידי חברת IBM בשנת 1997, ובשנת 1999 אומץ של ידי סאן מיקרוסיסטמס (החברה שפיתחה את Java עד שנקנתה על ידי אורקל), וממשיך להיות משופר במסגרת ה-Java Community Process. הגרסה הנוכחית היא EJB 3.1.
מטרת המפרט של EJB היא לספק צורה סטנדרטית למימוש קוד back-end "עסקי", אשר בדרך כלל נמצא ביישומי enterprise (בניגוד לקוד front-end השייך לממשק המשתמש). בדרך כלל קוד כזה מטפל בבעיות דומות החוזרות על עצמן בפרויקטים שונים, ולעיתים קרובות מתכנתים מממשים מחדש את הפתרונות לבעיות אלו. מטרת ה-Enterprise JavaBeans היא לטפל בצורה סטנדרטית בבעיות נפוצות כאלה, כדוגמת: persistence, שלמות טרנזקציות (transactional integrity), ואבטחת מידע, על מנת לשחרר את המתכנתים להתרכז בפיתוח פתרונות לבעיות הספציפיות של הפרויקט.
כדי לפרוס ולהריץ Enterprise JavaBeans, ניתן להשתמש בשרת יישומים ל-Java EE אשר כברירת מחדל כולל מנגנון להרצת EJB container) EJBs). לחלופין ניתן להשתמש בקונטיינר נפרד כדוגמת OpenEJB.

אימוץ מהיר המלווה בביקורת

חזון ה-EJB הוצג בצורה משכנעת על ידי התומכים בו כדוגמת IBM ו-Sun Microsystems, וה-Enterprise JavaBeans אומצו במהרה על ידי חברות גדולות. זמן קצר לאחר מכן התחילו להופיע בעיות בגרסאות הראשונות. חלק מהמפתחים הרגישו כי ממשקי תכנות היישומים (APIs) של סטנדרט ה-EJB היו הרבה יותר מסובכים לעומת מה שהם היו רגילים אליו. ריבוי החריגות הנבדקות (checked exceptions), ממשקים נדרשים, והמימוש של מחלקת ה-bean כמחלקה אבסטרקטית, היו חריגים ולא אינטואיטיביים עבור מתכנתים. הבעיות שבהן סטנדרט ה-EJB ניסה לטפל, כדוגמת מיפוי אובייקטי-רלציוני (ORM) ושלמות טרנזקציות, אכן היו בעיות מורכבות, אך מתכנתים רבים חשו שממשקי תכנות היישומים של EJB היו לא פחות מסובכים. זה הוביל לתפיסה ש-EJBs הכניסו מורכבות נוספת מבלי לספק שום יתרונות ממשיים.
בנוסף לכך, התברר שהשימוש ב-EJBs לצורך כימוס הלוגיקה העסקית גרם לירידה בביצועים. זה נגרם בגלל שהמפרט המקורי איפשר הפעלת מתודות מרוחקות (remote method invocation) רק באמצעות CORBA (ואפשרית גם פרוטוקולים אחרים), למרות הרוב הגדול של היישומים העסקיים אינם דורשים פונקציונליות כזאת של חישוב מבוזר. המפרט EJB 2.0 טיפל בבעיה זו על ידי הוספת רעיון הממשקים המקומיים שניתן לקרוא להם ישירות מיישומים שאינם מבוזרים על פני כמה שרתים, מבלי לפגוע בביצועים.
בעיות המורכבות של EJB המשיכו לעכב את תפוצת השימוש בה. אף על פי שנוצרו כלי פיתוח שהקלו על היצירה והשימוש ב-EJBs על ידי אוטומציה של מרבית המשימות שחוזרות על עצמן, כלים אלה לא הפכו את תהליך הלימוד של השימוש בטכנולוגיה זו לקל יותר. יתר על כן, התחילה לצמוח "תנועת מחאה עממית" בקרב מתכנתים. התוצרים העיקריים של תנועה זו היו הטכנולוגיות ה"קלות" (בהשוואה ל-EJB): הייברנייט (לטיפול ב-persistence ומיפוי אובייקטי-רלציוני), ו-Spring Framework (מספקת שיטה אלטרנטיבית והרבה יותר תמציתית לקודד את הלוגיקה העסקית). אף על פי שלא הייתה להן התמיכה של עסקים גדולים, הפופולריות של טכנולוגיות אלה גדלה והן אומצו על ידי ארגונים רבים.

"המצאה מחדש" של ה-EJBs

בהדרגה נוצר בתעשייה קונצנזוס שהמעלה העיקרית של המפרט המקורי של EJB – לאפשר שלמות טרנזקציות על פני יישומים מבוזרים – היא בעלת שימושיות מוגבלת עבור מרבית יישומי ה-enterprise, ושהפונקציונליות שמספקות תשתיות תוכנה פשוטות יותר כדוגמת Spring ו-Hibernate היא שימושית יותר.
בעקבות זאת, המפרט של EJB 3.0 היווה סטייה קיצונית מהמפרטים שקדמו לו, תוך שהוא נצמד לפרדיגמה חדשה זו. במפרט החדש ניתן לראות השפעה ברורה של Spring עם השימוש ב-POJOs, והתמיכה ב-dependency injection כדי לפשט את תהליך הקונפיגורציה והשילוב של מערכות הטרוגניות. גאווין קינג, היוצר של Hibernate, השתתף בפיתוח של EJB 3.0 ומשמש כדובר לטובת הטכנולוגיה. הרבה מהאפשרויות שהיו במקור ב-Hibernate שולבו ב-Java Persistence API, התחליף של entity beans ב-EJB 3.0. המפרט של EJB 3.0 מסתמך רבות על שימוש ב-annotations, תכונה שנוספה לשפת Java בגרסה 5.0 שלה, וב-convention over configuration, כדי לאפשר סגנון כתיבת קוד תמציתי הרבה יותר.
לפיכך EJB 3.0 היא קלה הרבה יותר ומהווה API חדש כמעט לגמרי, בעל דמיון מועט למפרטים הקודמות של EJB.

דוגמה

הקטע הבא מציג דוגמה בסיסית של האופן בו EJB נראה בתוך קוד:
@Stateless 
public class CustomerService { 
  
  @PersistenceContext 
  private EntityManager entityManager; 
    
  public void addCustomer(Customer customer) { 
    entityManager.persist(customer); 
  } 
}
הקוד למעלה מגדיר מחלקת שירות לשימור (persisting) של אובייקט Customer (באמצעות מיפוי אובייקטי-רלציוני). ה-EJB מטפל בניהול ה-persistence והמתודה addCustomer היא בטוחה לשימוש מקבילי (thread-safe) ולצורך העברת טרנזקציות. כפי שניתן לראות בדוגמה, ה-EJB מתמקד רק בלוגיקה העסקית וב-persistence, ולא מודע לשום דבר הנוגע לצורת פרזנטציה מסוימת.
לדוגמה, EJB כזה יכול לשמש מחלקה משכבת ה-web בצורה הבאה:
@Named@RequestScopedpublic class CustomerBacking {

   @EJB 
   private CustomerService customerService;

   public String addCustomer() {
      customerService.addCustomer(customer);
      context.addMessage(...); // abbreviated for brevity
      return "customer_overview";
   }}
הקוד למעלה מגדיר backing bean של (JavaServer Faces (JSF שבו ה-EJB מוזרק על ידי שימוש באנוטציה EJB@. המתודה addCustomer תהיה מקושרת לאחד מרכיבי ממשק המשתמש, כמו כפתור לדוגמה. בניגוד ל-EJB, ה-backing bean אינו מכיל שום לוגיקה עסקית או קוד פרזנטציה, אלא במקום זאת מאציל (delegates) את הטיפול בבעיות אלה ל-EJB. ה-backing bean מודע לצורת פרזנטציה מסוימת, שה-EJB לא היה מודע אליה.