JBoss Seam 2. - Dependency Injection

A Seam segítségével egyszerű POJO-ból építhetünk szerviz komponenst. Nincs szükség sem különböző interfészek implementálására, sem absztrakt osztályra, ahhoz, hogy a komponenst az alkalmazáshoz kapcsoljuk (lásd Java EE keretrendszerek integrációja). A következő kérdés az, hogy hogyan lépnek kapcsolatba az egyes osztályok futás időben, valamint, hogyan lépnek kapcsolatba olyan konténer szolgáltatásokkal (container services), mint például az adatbázis perzisztencia szerviz.

A Seam egy kedvelt tervezési mintát (desgin pattern) használ a POJO komponensek összekötéséhez, melyet függőségi befecskendezésnek (dependency injection, DI) neveznek. Ezen minta szerint a Seam keretrendszer menedzseli az összes komponens életciklusát. Ha egy komponens használni szeretné a másikat, akkor Seam annotációkkal kell leírni a köztük lévő függést (tervezési időben). Futási időben a Seam az alkalmazás aktuális állapota alapján meghatározza, hogy hol található az a komponens, melyet be kell fecskendezni az adott változóba.

A függőségi befecskendezés koncepcióját példázza, hogy egy Seam-ben lévő ,,A'' komponensnek lehetősége van egy ,,B'' komponens létrehozására (példányosítással), majd azt az alkalmazás környezetbe kiküldeni (outject into the application context). Miután kiküldte bármely, más Seam-ben lévő komponens használhatja ,,B''-t.

Jó példa a függőségi befecskendezésre az azonosítás (hitelesítés). Az Autenticator komponens elvégzi a felhasználói azonosítást. Sikeres belépést követően létrehozza a User objektumot, melyet kiküld az alkalmazás környezetbe. Ezután a PetDao komponens szabadon használhatja azt a felhasználó háziállatainak listázására, a lista bővítésére.
Entitás osztályok:

@Entity
public class User implements Serializable {
   private Integer id;
   private String name;
   @OneToMay(mappedBy="owner")
   private List pets;

   ... ... /* GETTERS / SETTERS */
}

@Entity
public class Pet implements implements Serializable {
   private Integer id;
   private String name;
   @ManyToOne
   private User owner;

   ... ... /* GETTERS / SETTERS */
}

Akció és Dao osztályok:

@Name("authenticator")
public class Authenticator {
   /* Kikuldes az alkalmazas kornyezetbe */
   @Out(required=false, scope=ScopeType.SESSION)
   private User user;

   public boolean authenticate() {
   ... ...
   try {
      user = (User)q.getSingleResult();
   } catch (javax.persistence.NoResultException nre) {
      return false;
   }
   ... ...
   }
}

@Name("petDao")
public class PetDao implements Serializable {
   /* Befecskendezes az alkalmazas kornyezetbol */
   @In
   private User currentUser;
   /* Injektaljuk a perzisztencia kontextust is */
   @In
   private EntityManager entityManager;

   public void addPet(Pet pet) {
      //currentUser = entityManager.merge(currentUser);
      currentUser.getPets().add(pet);
   }
   ... ...
}

A @In annotáció jelentése tehát: Mielőtt bármely PetDao metódust futtatnánk, fecskendezzük be az alkalmazás környezetből az objektum aktuális állapotát. A @Out pedig az objektum átadását jelenti az alkalmazás környezetnek, miután lefutott a kéréshez tartozó aktuális metódus. Ha több azonos típusú objektum található az alkalmazás környezetben, akkor lehetőség van külön-külön nevet adni mindegyiknek: @In(value="valami_nev").