450 likes | 461 Views
JNDI Enterprise Naming Conext (ENC) and Injection. Goals. Configure applications Using the JNDI Enterprise Naming Context (ENC) Using Context and Dependency Injection (CDI) Access remote EJBs. Objectives. JNDI ENC Overview JNDI ENC Lookup XML Population Annotation Population
E N D
JNDI ENC JNDI Enterprise Naming Conext (ENC)andInjection
JNDI ENC Goals • Configure applications • Using the JNDI Enterprise Naming Context (ENC) • Using Context and Dependency Injection (CDI) • Access remote EJBs
JNDI ENC Objectives • JNDI ENC Overview • JNDI ENC Lookup • XML Population • Annotation Population • Dependency Injection • Context and Dependency Injection (CDI) Population • Remote JNDI Client
JNDI ENC JNDI ENC Overview • Component's individual address space • Holds references to values and objects in the environment • Theoretical equivalent to Unix soft links • ln -s <some physical file path> $HOME/<my logical path> • Object's registered • EJB interfaces (local and remote) • JMS connection factories • JMS destinations • data sources • any JCA resource • primitive values
JNDI ENC JNDI ENC and Injection • Objects are placed in the component's JNDI ENC by the container • Components may look these values up • using raw JNDI calls • using SessionContext convenience method • allows any nested component to also get the environment • Components may have values injected into properties/fields. • fewer lines of code dedicated to lookups • inversion of control
JNDI ENC Reading JNDI ENC • JNDI InitialContext jndi = new InitialContext(); object = jndi.lookup(“java:comp/env/encname); • SessionContext SessionContext ctx; ... object = ctx.lookup(“encname”);
JNDI ENC XML Population: Example POJO Style //@Local declared by ejb-jar.xml entry public interface HospitalLocal extends Scheduler {} //@Remote declared by ejb-jar.xml entry public interface HospitalRemote extends Scheduler {} //@Stateless(name=”Hospital”) declared by ejb-jar.xml entry public class HospitalEJB extends SchedulerBase implements HospitalLocal, HospitalRemote { public String getName() { return "HospitalEJB"; } @Resource public void setSessionContext(SessionContext ctx) { this.ctx = ctx; } } //@Local declared by ejb-jar.xml entry public interface AidSchedulerLocal extends Scheduler {} //@Remote declared by ejb-jar.xml entry public interface AidSchedulerRemote extends Scheduler {}
JNDI ENC XML Population: Example POJO Style //@Stateless(name=”AidScheduler”) declared by ejb-jar.xml entry public class AidSchedulerEJB extends SchedulerBase implements AidSchedulerLocal, AidSchedulerRemote { private EntityManager em; private DataSource ds; private String message; private HospitalLocal hospital; @Resource //in super - protected SessionContext ctx; public void setSessionContext(SessionContext ctx) { this.ctx = ctx; } public void init() { log.info("************* AidScheduler Created ************"); log.debug("ctx=" + ctx); log.debug("ejb/hospital=" + ctx.lookup("ejb/hospital")); log.debug("message=" + message); log.debug("em=" + em); log.debug("ds=" + ds); log.debug("hospital=" + hospital); } public String getName() { return "AidScheduler"; } }
JNDI ENC XML Population: Example Output ******************* AidScheduler Created ****************** ctx=org.jboss.as.ejb3.context.SessionContextImpl@178cae4 ejb/hospital=Proxy for view class: ejava.examples.jndidemo.ejb.HospitalLocal of EJB: Hospital message=Hello Helping World em=org.jboss.as.jpa.container.TransactionScopedEntityManager@77051f ds=org.jboss.jca.adapters.jdbc.WrapperDataSource@1839aa9 hospital=Proxy for view class: ejava.examples.jndidemo.ejb.HospitalLocal of EJB: Hospital listing env jndi: java:comp/env/ejb/hospital=Proxy for view class: ejava.examples.jndidemo.ejb.HospitalLocal of EJB: Hospital enc: ejb/hospital=Proxy for view class: ejava.examples.jndidemo.ejb.HospitalLocal of EJB: Hospital jndi: java:comp/env/persistence/jndidemo=org.jboss.as.jpa.container.TransactionScopedEntityManager@10750d5 enc: persistence/jndidemo=org.jboss.as.jpa.container.TransactionScopedEntityManager@b32027 java:comp/env=listing java:comp/env
JNDI ENC XML Population: META-INF/ejb-jar.xml <?xml version="1.0"?> <ejb-jar 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/ejb-jar_3_1.xsd" version="3.1"> <enterprise-beans> ... <session> <ejb-name>Hospital</ejb-name> <business-local>ejava.examples.jndidemo.ejb.HospitalLocal</business-local> <business-remote>ejava.examples.jndidemo.ejb.HospitalRemote</business-remote> <ejb-class>ejava.examples.jndidemo.ejb.HospitalEJB</ejb-class> </session> </enterprise-beans> </ejb-jar>
JNDI ENC XML Population: META-INF/ejb-jar.xml <enterprise-beans> <session> <ejb-name>AidScheduler</ejb-name> <business-local>ejava.examples.jndidemo.ejb.AidSchedulerLocal</business-local> <business-remote>ejava.examples.jndidemo.ejb.AidSchedulerRemote</business-remote> <ejb-class>ejava.examples.jndidemo.ejb.AidSchedulerEJB</ejb-class> <session-type>Stateless</session-type> <!-- REMAINDER OF EXAMPLE GOES HERE --> <post-construct> <lifecycle-callback-method> init </lifecycle-callback-method> </post-construct> </session>
JNDI ENC XML Population: env-entry <env-entry> <env-entry-name>vals/message</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>Hello Helping World</env-entry-value> <injection-target> <injection-target-class> ejava.examples.jndischeduler.ejb.AidSchedulerEJB </injection-target-class> <injection-target-name>message</injection-target-name> </injection-target> </env-entry>
JNDI ENC XML Population: ejb-local-ref <ejb-local-ref> <ejb-ref-name>ejb/hospital</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <local>ejava.examples.jndischeduler.ejb.HospitalLocal</local> <ejb-link>Hospital</ejb-link> <injection-target> <injection-target-class> ejava.examples.jndischeduler.ejb.AidSchedulerEJB </injection-target-class> <injection-target-name>hospital</injection-target-name> </injection-target> </ejb-local-ref>
JNDI ENC XML Population: EntityManager <persistence-context-ref> <persistence-context-ref-name> persistence/jndidemo </persistence-context-ref-name> <persistence-unit-name>jndischeduler</persistence-unit-name> <persistence-context-type>Transaction</persistence-context-type> <injection-target> <injection-target-class> ejava.examples.jndischeduler.ejb.AidSchedulerEJB </injection-target-class> <injection-target-name>em</injection-target-name> </injection-target> </persistence-context-ref>
JNDI ENC XML Population: DataSource <resource-ref> <res-ref-name>jdbc/myds</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> <injection-target> <injection-target-class> ejava.examples.jndidemo.ejb.AidSchedulerEJB </injection-target-class> <injection-target-name>ds</injection-target-name> </injection-target> </resource-ref>
JNDI ENC XML JNDI mapping META-INF/jboss-ejb3.xml <?xml version="1.0"?> <jboss:ejb-jar xmlns:jboss="urn:jboss:domain:ejb3:1.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:s="urn:security" 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/ejb-jar_3_1.xsd" version="3.1" impl-version="2.0"> <enterprise-beans> <session> <ejb-name>AidScheduler</ejb-name> <resource-ref> <res-ref-name>jdbc/myds</res-ref-name> <jndi-name>java:jboss/datasources/ExampleDS</jndi-name> </resource-ref> </session> </enterprise-beans> </jboss:ejb-jar>
JNDI ENC Annotation Population: Example Entities @Local public interface CookLocal extends Scheduler {} @Stateless public class CookEJB extends SchedulerBase implements CookLocal { public String getName() { return "CookEJB"; } @Resource protected void setSessionContext(SessionContext ctx) { super.ctx = ctx; } } @Remote public interface BakeSchedulerRemote extends Scheduler {}
JNDI ENC Annotation Population: Example Java Class @Stateful(name="BakeScheduler") @PersistenceContext(unitName="jndidemo", name="persistence/jndidemo", type=PersistenceContextType.EXTENDED) public class BakeSchedulerEJB extends SchedulerBase implements BakeSchedulerRemote { @PersistenceContext(unitName="jndidemo", type=PersistenceContextType.EXTENDED) private EntityManager em; @Resource(name="persistence/jndidemo") private EntityManager em2; @Resource(mappedName="java:jboss/datasources/ExampleDS") private DataSource ds; @Resource protected void setSessionContext(SessionContext ctx) { super.ctx = ctx; }
JNDI ENC Annotation Population: Example Java Class protected CookLocal cook; @EJB(name=“ejb/cook”) protect CookLocal cook2; @Resource(name="vals/message") String message; @PostConstruct public void init() { log.info("********* BakeScheduler Created ********"); log.debug("ctx=" + ctx); log.debug("em=" + em); log.debug("ds=" + ds); log.debug("persistence/jndidemo=" + ctx.lookup("persistence/jndidemo")); log.debug("message=" + message); log.debug("cook=" + cook); log.debug("cook=" + cook2); log.debug("ejb/cook=" + ctx.lookup("ejb/cook")); }
JNDI ENC Annotation Population: Example Output ******************* BakeScheduler Created ****************** ctx=org.jboss.as.ejb3.context.SessionContextImpl@18d9f9b em=ExtendedEntityManager [ jndiDemoEAR-3.0.2012.2-SNAPSHOT.ear/jndiDemoEJB.jar#jndidemo] em2=ExtendedEntityManager [ jndiDemoEAR-3.0.2012.2-SNAPSHOT.ear/jndiDemoEJB.jar#jndidemo] ds=org.jboss.jca.adapters.jdbc.WrapperDataSource@1839aa9 message=null cook=null cook2=Proxy for view class: ejava.examples.jndidemo.ejb.CookLocal of EJB: CookEJB ejb/cook=Proxy for view class: ejava.examples.jndidemo.ejb.CookLocal of EJB: CookEJB listing java:comp/env jndi: java:comp/env/ejb/cook=Proxy for view class: ejava.examples.jndidemo.ejb.CookLocal of EJB: CookEJB enc: ejb/cook=Proxy for view class: ejava.examples.jndidemo.ejb.CookLocal of EJB: CookEJB jndi: java:comp/env/persistence/jndidemo=ExtendedEntityManager [jndiDemoEAR-3.0.2012.2-SNAPSHOT.ear/jndiDemoEJB.jar#jndidemo] enc: persistence/jndidemo=ExtendedEntityManager [jndiDemoEAR-3.0.2012.2-SNAPSHOT.ear/jndiDemoEJB.jar#jndidemo] java:comp/env=listing java:comp/env
JNDI ENC Dependency Injection • fields • simple, less verbose • property setter • easier to plug into unit tests • no need for getter • inheritance supported
JNDI ENC Context and Dependency Injection (CDI): JSR-299 • JSR-299 • Started as “Web Beans” • Derived from Seam • Original Draft conflicted with Google+Spring submission • JSR-330 (Java Injection) • Approved version refactored to account for JSR-330
JNDI ENC Sample CDI Related Types • java.lang.annotation • @Retention – how long annotation is retained (default=CLASS) • RetentionPolicy • CLASS – annotation recorded in class file but not available at runtime • RUNTIME – annotation recorded in class and available at runtime • SOURCE – annotation discarded by compiler • @Target – kind of Java construct annotation applies • ElementType • TYPE • FIELD • METHOD • PARAMETER • (more) • javax.inject (JSR-330) • @Inject – an injection target • @Named – string qualifier • @Qualifier – identifes qualifier annotations • javax.enterprise.inject (JSR-299) • @Produces – an injection source • @Any – no qualifiers • Instance<Bean> -- runtime source for Bean
JNDI ENC CDI: Producer Field, Named Qualifiers, and Injection public class SchedulerResources{ @PersistenceContext(name="jndidemo") @Produces @Named("jndidemo") public EntityManagerem; @Stateless public class TrainSchedulerEJB extends SchedulerBase implements TrainSchedulerRemote { @Inject @Named("jndidemo") private EntityManagerem;
JNDI ENC CDI: Method Producer and Annotation Qualifier public class SchedulerResources{ @Produces @JndiDemo public EntityManagergetEM() { return em; } import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.RetentionPolicy.*; import static java.lang.annotation.ElementType.*; import javax.inject.Qualifier; @Qualifier @Retention(RUNTIME) @Target({METHOD, FIELD, PARAMETER, TYPE}) public @interface JndiDemo { } @Stateless public class TrainSchedulerEJB extends SchedulerBase implements TrainSchedulerRemote { @Inject @JndiDemo private EntityManager em2;
JNDI ENC CDI: JNDI Resource public class SchedulerResources { @Resource(mappedName="java:jboss/datasources/ExampleDS") @Produces @JndiDemo public DataSource ds; @Stateless public class TrainSchedulerEJB extends SchedulerBase implements TrainSchedulerRemote { @Inject @JndiDemo private DataSource ds;
JNDI ENC CDI: String Resource public class SchedulerResources { @Produces @JndiDemo public String message="Hello CDI!!!"; @Stateless public class TrainSchedulerEJB extends SchedulerBase implements TrainSchedulerRemote { @Inject @JndiDemo String message;
CDI: EJB Resource, @Any, Instance public class SchedulerResources{ @EJB(lookup="java:app/jndiDemoEJB/CookEJB!ejava.examples.jndidemo.ejb.CookLocal") @Produces @Cook public Scheduler cook; @Stateless public class TrainSchedulerEJB extends SchedulerBase implements TrainSchedulerRemote { @Inject @Any protected Instance<Scheduler> anyCook; protected Scheduler cook2; import javax.enterprise.util.AnnotationLiteral; public class CookQualifier extends AnnotationLiteral<Cook> { } cook2 = anyCook.select(new CookQualifier()).get();
JNDI ENC CDI: Bean Resource @Named public class JPASchedulerDAOImpl extends JPADAOBase<Task> implements SchedulerDAO { … @Stateless public class TrainSchedulerEJB extends SchedulerBase implements TrainSchedulerRemote { @Inject protected SchedulerDAO schedulerDAO; @Inject protected JPASchedulerDAOImpl jpaSchedulerDAOImpl; (assignable)
JNDI ENC CDI: Bean Resource and @Typed @Typed({SchedulerDAO.class, JPASchedulerDAOImpl.class}) public class JPASchedulerDAOImpl extends JPADAOBase<Task> implements SchedulerDAO { … @Stateless public class TrainSchedulerEJB extends SchedulerBase implements TrainSchedulerRemote { @Inject protected SchedulerDAO schedulerDAO; @Inject protected JPASchedulerDAOImpl jpaSchedulerDAOImpl; (not assignable)
JNDI ENC CDI: Injecting into POJOs public class JPASchedulerDAOImpl @Inject @Named("jndidemo") public void setEntityManager(EntityManager em) { super.em = em; } @Override public String toString() { return new StringBuilder(super.toString()) .append(", em=" + em).toString(); }
JNDI ENC CDI: @PostConstruct @PostConstruct public void init() { log.info("******************* TrainScheduler Created ******************"); log.debug("ctx=" + ctx); log.debug("em=" + em); log.debug("em=" + em2); log.debug("ds=" + ds); log.debug("message=" + message); log.debug("cook=" + cook); cook2 = anyCook.select(new CookQualifier()).get(); log.debug("cook2=" + cook2); log.debug("schedulerDAO=" + schedulerDAO); log.debug("jpaSchedulerDAOImpl=" + jpaSchedulerDAOImpl); }
JNDI ENC CDI: Population Output ******************* TrainScheduler Created ****************** ctx=org.jboss.as.ejb3.context.SessionContextImpl@1b9d518 em=org.jboss.as.jpa.container.TransactionScopedEntityManager@1553d64 em=org.jboss.as.jpa.container.TransactionScopedEntityManager@131a01b ds=org.jboss.jca.adapters.jdbc.WrapperDataSource@1839aa9 message=Hello CDI!!! cook=Proxy for view class: ejava.examples.jndidemo.ejb.CookLocal of EJB: CookEJB cook2=Proxy for view class: ejava.examples.jndidemo.ejb.CookLocal of EJB: CookEJB schedulerDAO=ejava.examples.jndidemo.dao.JPASchedulerDAOImpl@106504d, em=org.jboss.as.jpa.container.TransactionScopedEntityManager@18215b6 jpaSchedulerDAOImpl=ejava.examples.jndidemo.dao.JPASchedulerDAOImpl@15f65a1, em=org.jboss.as.jpa.container.TransactionScopedEntityManager@931d5
JNDI ENC CDI: beans.xml • ***REQUIRED*** • Triggers CDI Processing • META-INF/beans.xml for EJBs • WEB-INF/beans.xml for WARs • Can be empty <beans 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/beans_1_0.xsd"> </beans>
JNDI ENC JNDI Clients • Portable EJB JNDI Names • RMI Clients • JBoss Remoting • JBoss EJB Client
JNDI ENC Portable JNDI Names • EJB Spec defines a standard naming scheme java:global[/<app-name>]/<module-name>/<bean-name>[!<fully-qualified-interface-name>] • “java:” - JNDI naming strategy • “global” – JNDI context • app-name – used only when packaged in .ear • Defaults to EAR basename • Can be specified in application.xml#application-name • module-name – name of module housing session bean • Defaults to module.ejb archive basename • Can be specified in ejb-jar.xml#module-name or web.xml#module-name • bean-name • Set to EJB bean-name • EJB bean-name can be set using @annotation or ejb-jar.xml • fully-qualified-interface-name
JNDI ENC Other Contexts • java:app • Unique namespace within deployed application java:app/<module-name>/<bean-name>[!<fully-qualified-interface-name>] • java:module • Unique namespace within deployed module java:module/<bean-name>[!<fully-qualified-interface-name>]
JNDI ENC Example Application |-- jndiDemoEJB.jar |-- lib | `-- ejava-util-3.0.2012.2-SNAPSHOT.jar `-- META-INF `-- application.xml <application 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/application_6.xsd" version="6"> <application-name>jndiDemoEAR</application-name> <display-name>jndiDemoEAR</display-name> <module> <ejb>jndiDemoEJB.jar</ejb> </module> <library-directory>lib</library-directory> </application>
JNDI ENC Forming the JNDI Name java:global/jndiDemoEAR/jndiDemoEJB/CookEJB!ejava.examples.jndidemo.ejb.CookLocal <application ...> <application-name>jndiDemoEAR</application-name> <display-name>jndiDemoEAR</display-name> <module> <ejb>jndiDemoEJB.jar</ejb> </module> <library-directory>lib</library-directory> </application> @Stateless public class CookEJB implements CookLocal { package ejava.examples.jndidemo.ejb; @Local public interface CookLocal {
JNDI ENC Example: Deployed JNDI Tree • Internal Names java:global/jndiDemoEAR/jndiDemoEJB/AidScheduler!ejava.examples.jndidemo.ejb.AidSchedulerLocal java:app/jndiDemoEJB/AidScheduler!ejava.examples.jndidemo.ejb.AidSchedulerLocal java:module/AidScheduler!ejava.examples.jndidemo.ejb.AidSchedulerLocal java:global/jndiDemoEAR/jndiDemoEJB/AidScheduler!ejava.examples.jndidemo.ejb.AidSchedulerRemote java:app/jndiDemoEJB/AidScheduler!ejava.examples.jndidemo.ejb.AidSchedulerRemote java:module/AidScheduler!ejava.examples.jndidemo.ejb.AidSchedulerRemote • (JBoss) External Names java:jboss/exported/jndiDemoEAR/jndiDemoEJB/AidScheduler!ejava.examples.jndidemo.ejb.AidSchedulerRemote
JNDI ENC JBoss Remoting • (JBoss) jndi.properties java.naming.factory.initial=org.jboss.naming.remote.client.InitialContextFactory java.naming.factory.url.pkgs= java.naming.provider.url=remote://127.0.0.1:4447 java.naming.security.principal=known java.naming.security.credentials=password jboss.naming.client.ejb.context=true • (JBoss) Client JNDI Name jndiDemoEAR/jndiDemoEJB/AidScheduler!ejava.examples.jndidemo.ejb.AidSchedulerRemote
JNDI ENC JBoss EJB Client • (JBoss) jndi.properties java.naming.factory.initial= java.naming.factory.url.pkgs=org.jboss.ejb.client.naming java.naming.provider.url= java.naming.security.principal= java.naming.security.credentials= • jboss-ejb3.properties remote.connections=default remote.connection.default.host=127.0.0.1 remote.connection.default.port=4447 remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false • (JBoss) Client JNDI Name • ejb:jndiDemoEAR/jndiDemoEJB//AidScheduler!ejava.examples.jndidemo.ejb.AidSchedulerRemote • ejb:jndiDemoEAR/jndiDemoEJB//AidScheduler!ejava.examples.jndidemo.ejb.AidSchedulerRemote?stateful
JNDI ENC Client Lookup String jndiName=… javax.naming.Context jndi = new javax.naming.InitialContext(); AidScheduerRemote scheduler = (AidSchedulerRemote)jndi.lookup(jndiName);
JNDI ENC Summary • Populate • XML • Annotations • CDI • Lookup • JNDI • SessionContext • Property Assignment • Lookup • Dependency Injection
JNDI ENC References • “Enterprise JavaBeans 3.0, 5th Edition”; Burke & Monsen-Haefel; ISBN 0-596-00978-X; O'Reilly • JSR 299: Contexts and Dependency Injection for the JavaTM EE platform • http://www.jcp.org/en/jsr/detail?id=299