Březen 11th, 2008Seam - tipy a triky (EJB)
Seam je dobře použitelný s EJB, kde jsou jednotlivé EJB vystaveny jako Seam komponenty a navíc obsahují všechny služby, které EJB kontejner nabízí.
Jsou ovšem chvíle, kdy bych potřeboval obyčejnou Seam komponentu a do ní nějakým způsobem vstříknout EJB beanu. Co se týče implementaci pro glassfish, není situace tak jednoduchá, jak by se mohlo zdát.
Takže, mějme příklad, kdy potřebuji vytvořit Seam komponentu, která bude míti jednu metodu, která bude vracet seznam hodnot z nějaké entity.
Klasický přístup by mohl vypadat následovně:@Name(„testList“)
public class TestList {
@Unwrap
public List<Entita> lookup() {
return entityManager.createQuery(„from Entita e“).getResultList();
}
}
Použití ve facelets stránce by poté vypadalo následovně:
public class TestList {
@Unwrap
public List<Entita> lookup() {
return entityManager.createQuery(„from Entita e“).getResultList();
}
}
<h:selectonemenu id=„zarazeni“ value=„#{komponenta.hodnotaTestList}“>
<s:selectitems value=„#{testList}“ var=„t“ label=„#{t.nazev}“ noselectionlabel=„- _testList -“>
</s:selectitems></h:selectonemenu>
Pravdou je, že použití samotné anotace @Unwrap může mít hezké
uplatnění.
<s:selectitems value=„#{testList}“ var=„t“ label=„#{t.nazev}“ noselectionlabel=„- _testList -“>
</s:selectitems></h:selectonemenu>
Jenže, osobně se mi nelibí možnost, že musím uvnitř samotného „testListu“ volat entity manager a navíc psát nějaké OQL. Mám již definovanou DAO vrstvu pomocí EJB a chci lookupnout samotnou EJB jako Seam komponentu.
K tomtuto účelu jsem si vytvořil jednoduchou lookup službu, která vypadá následnovně:@Stateless
@Name(„lookup“)
@Scope(ScopeType.APPLICATION)
@Interceptors(value = {SeamInterceptor.class})
public class LookupBean implements LookupLocal {
@Resource
private EJBContext context;
@EJB
private SessionLookupLocal sess;
public Object ejb(String bean) {
return context.lookup(bean);
}
public EntityManager getEntityManager() {
return sess.getEntityManager();
}
public Session getSession() {
return sess.getSession();
}
}
Takže lookup služba slouží k získaní jak EJB beany tak entity manageru
popřípadě Hibernate Session. Dá se sice namítnout, že Seam umí přímo
injectnout EntityManager (dokonce se to dá hackem zprovoznit i v glassfish),
ale já si raději vsrtvy odděluji, proto injectuji daný „persistence
provider“ jen v nejnutnějších chvílích. Druhou věcí je fakt, že daný
provider pro persistenci přenáší jiná EJB beana. Důvodem je fakt, že při
inicializaci a vytvoření Seam komponenty ještě není znám provider pro
entity manager, proto ho musím získat z jiné EJB.Ale zpět. K tomu, aby
daná lookup služba (která je jak Seam komponentou tak EJB komponentou) byla
schopná lookupovat EJB, musí být navíc definovana reference na dané EJB
beany v ejb.jar.xml, nebo pomocí anotací. Já jsem zde raději přistoupil
k možnosti pomocí XML, jelikož se jedná o speciální požadavek, který
se v průběhu života může změnit.
@Name(„lookup“)
@Scope(ScopeType.APPLICATION)
@Interceptors(value = {SeamInterceptor.class})
public class LookupBean implements LookupLocal {
@Resource
private EJBContext context;
@EJB
private SessionLookupLocal sess;
public Object ejb(String bean) {
return context.lookup(bean);
}
public EntityManager getEntityManager() {
return sess.getEntityManager();
}
public Session getSession() {
return sess.getSession();
}
}
<enterprise-beans>
<session>
<ejb-name>LookupBean</ejb-name>
<ejb-class>cz.irminsul.seam.app.LookupBean</ejb-class>
<ejb-local-ref>
<ejb-ref-name>NejakaDAOBean</ejb-ref-name>
<local>cz.irminsul.NejakaDAOLocal</local>
<ejb-link>NejakaDAOBean</ejb-link>
</ejb-local-ref>
</session>
</enterprise-beans>
Díky této definici reference mám možnost uvnitř lookupBean získávat ejb
dynamicky, tedy přes initialContext.Konečné použití uvnitř Seam
komponenty, která není EJB beanou, může vypadat následovně:
<session>
<ejb-name>LookupBean</ejb-name>
<ejb-class>cz.irminsul.seam.app.LookupBean</ejb-class>
<ejb-local-ref>
<ejb-ref-name>NejakaDAOBean</ejb-ref-name>
<local>cz.irminsul.NejakaDAOLocal</local>
<ejb-link>NejakaDAOBean</ejb-link>
</ejb-local-ref>
</session>
</enterprise-beans>
@Name(„testList“)
public class TestList {
@In(value = „#{lookup.ejb(‚NejakaBean‘)}“)
private NejakaLocal bean;
private List<Entita> data;
@Unwrap
public List<Entita> lookup() {
if (data == null) {
data = bean.metodaLokalnihoInterface();
}
return data;
}
}
Samozřejmě je možné získat i Entity Manager či Hibernate Session.
Použití je v podstatě jasné:
public class TestList {
@In(value = „#{lookup.ejb(‚NejakaBean‘)}“)
private NejakaLocal bean;
private List<Entita> data;
@Unwrap
public List<Entita> lookup() {
if (data == null) {
data = bean.metodaLokalnihoInterface();
}
return data;
}
}
@In(„#{lookup.entityMananger}“)
private EntityManager em;
Daný návod je funkční v Seam 2.0, EJB 3 a Glassfish V2.
private EntityManager em;
Březen 15th, 2008 at 19.08
Proc nepouzijes seamovskou konponentu org.jboss.seam.Component:
JinaKomponenta jc = Component.getInstance(„jmeno_jine_komponenty“);
Březen 15th, 2008 at 20.19
To je samozrejme pravda, ale tyka se Seam komponenty. Me slo o pravy opak. Tedy do Seam komponenty dostal EJB komponentu, ktera o Seamu nic nevi.
Březen 20th, 2008 at 12.03
Ja tedy o Seamu taky nic nevim, ale chtela jsem se poucit. Neni mi jasne to vstrikovani, slo by to k necemu pribodobnit? Lze si to predstavit jako vstrikovani fazoli do ostrikovace, napr. u Ford Escort? A jak se zachovat v pripade praskle hadicky? Dekuji za odpoved
Září 11th, 2010 at 20.30
< blockquote >< a href=„http://cheaptabletsonline.com/“>CheapTabletsOnline.com. Canadian Health&Care.Best quality drugs.Special Internet Prices.No prescription online pharmacy. High quality drugs. Buy pills online< /a >…
Buy:Valtrex.Prevacid.Zyban.Retin-A.Nexium.Accutane.Lumigan.Actos.100% Pure Okinawan Coral Calcium.Mega Hoodia.Petcam (Metacam) Oral Suspension.Prednisolone.Human Growth Hormone.Zovirax.Synthroid.Arimidex…