📄 jndi.xtp
字号:
<s1 title="JNDI: Resource Configuration"><summarylist/><p>Applications can store factory objects and configuration variablesin a global naming tree using the JNDI API. JNDI, the Java Naming andDirectory Interface, provides a global memory tree to store and lookupconfiguration objects. JNDI will typically contain configured Factoryobjects.</p><p>JNDI lets applications cleanly separate configuration from theimplementation. The application will grab the configuredfactory object using JNDI and use the factory to find and createthe resource objects. In a typical example, the application willgrab a database DataSource to create JDBC Connections. Because theconfiguration is left to the configuration files, it's easy forthe application to change databases for different customers.</p><p>Some typical factory objects include:<ul><li><a href="db-config.xtp">JDBC DataSource</a><li>EJB Home interfaces<li><a href="jms.xtp">Java Messaging Service (JMS)</a> connection factories<li>JavaMail connection factories<li>Global configuration constants</ul><s2 title="web-apps and JNDI Contexts"><p>Resin organizes its resources into a tree, rooted in thesystem classloader. Each Resin context is associated with a classloader,a JNDI context, and a set of resources (databases, JMS, EJB beans, etc.)</p><p>Child contexts inherit classes and resources fromthe parent contexts. For example, a database with a JNDI name"java:comp/env/jdbc/foo" belonging to the foo.com virtual host would beshared for all web-applications in that host.</p><p>When Resin detects class or configuration changes in a context, itwill reload that context and all child contexts. This is how Resinreloads an application when a servlet changes.</p><figure src="jndi_tree.gif"/><p>Each web-app gets its own JNDI copy. So a web-app named /quercusand a web-app named /cmp could each use java:comp/env/jdbc/test for adatabase pool, but would use unique pools (probably usingdifferent databases.)</p><p>This separation keeps web-apps from stepping on each other's toesand also lets each virtual host use different databases.</p><p>The web-apps can share JNDI configuration from its host, and thehosts can share JNDI configuration from the global server. Eachweb-app copies the host JNDI tree, and each host copies the serverJNDI tree. So the web-app can't affect the host's JNDI, but it canshare the host's pools.</p><p>In Resin's configuration, the context determines where the JNDIwill be shared. If the JNDI configuration is in the <host>, it willbe shared across the entire host. If it's in the <web-app>, itwill only be used in the web-app.</p><deftable><tr><th>context<th>scope<tr><td>http-server<td>shared across all applications<tr><td>host<td>shared across the virtual host<tr><td>web-app<td>specific to the servlet application (.war)</deftable><example title='host and web-app specific configuration'>...<host id='foo.com'> <resource-ref res-ref-name='jdbc/foo' res-type='javax.sql.DataSource'> <init-param driver-name="org.gjt.mm.mysql.Driver"/> <init-param url="jdbc:mysql://localhost:3306/foo"/> </resource-ref> <web-app id='/quercus'> <resource-ref res-ref-name='jdbc/quercus' res-type='javax.sql.DataSource'> <init-param driver-name="org.gjt.mm.mysql.Driver"/> <init-param url="jdbc:mysql://localhost:3306/quercus"/> </resource-ref> </web-app></host>...</example><p>In the previous example, the java:comp/env/jdbc/foo pool is sharedacross all web-apps in foo.com, but the java:comp/env/jdbc/quercuspool is only available in the /quercus web-app.</p></s2><s2 title='JNDI Names'><p>JNDI names look like URLs. A typical name for adatabase pool is java:comp/env/jdbc/test. The <var/java:/> scheme isa memory-based tree. <var/comp/env/> is the standard location forJava configuration objects and <var/jdbc/> is the standard locationfor database pools.</p><p>Other URL schemes are allowed as well, includingRMI (rmi://localhost:1099) and LDAP. Many applications, though willstick to the java:comp/env tree.</p><deftable><tr><th>name<th>meaning<tr><td>java:comp/env<td>Configuration environment<tr><td>java:comp/env/jdbc<td>JDBC DataSource pools<tr><td>java:comp/env/ejb<td>EJB remote home interfaces<tr><td>java:comp/env/cmp<td>EJB local home interfaces (non-standard)<tr><td>java:comp/env/jms<td>JMS connection factories<tr><td>java:comp/env/mail<td>JavaMail connection factories<tr><td>java:comp/env/url<td>URL connection factories<tr><td>java:comp/UserTransaction<td>UserTransaction interface</deftable></s2><s2 title='JNDI API'><p>The vast majority of applications will only need the following simplepattern to lookup objects using JNDI. Since the JNDI objects aretypically configured in the web.xml or resin.conf, servlets willtypically look up their DataSources or EJB objects once in the init()method. By looking up the object once, the application can avoid anyJNDI overhead for normal requests.</p><example title='Looking up a DataSource'>import javax.naming.InitialContext;import javax.naming.Context;...Context env = (Context) new InitialContext().lookup("java:comp/env");DataSource pool = (DataSource) env.lookup("jdbc/test");</example><p><var/new InitialContext()/> returns the initial context for thecurrent web-app. As explained above, each application has its ownindependent JNDI namespace. So applications and virtual hosts willnot conflict with each other's JNDI names.</p><p>The <var/lookup(subpath)/> call finds the object at the specifiedsubpath, like a filesystem lookup. Intermediate paths, like<var/env/> in the example above, are Context objects. There's astrong analogy between filesystem directories and JNDI Contextobjects.</p><deftable><tr><th>call<th>meaning<tr><td>new InitialContext()<td>A new pointer to the root context<tr><td>context.lookup("subpath")<td>Finds the object or context at the named path beneath the current context</deftable><p>Applications will generally cache the results of the JNDI lookup.Once configured, factory objects don't change so they can be saved to avoidthe JNDI lookup. For example, EJB Home and DataSource factoriesdon't change once they've been configured. A well-designed applicationwill lookup the DataSource once and cache it for the next call.Servlets, for example, will often lookup the DataSource or EJB Home in the<var/init()/> method and save them in servlet instance variables.</p><example title='Caching a DataSource in a Servlet init()'>package qa;import javax.servlet.*;import javax.naming.*;public class MyServlet extends GenericServlet { DataSource dataSource; public void init() throws ServletException { try { Context env = new InitialContext().lookup("java:comp/env"); dataSource = (DataSource) env.lookup("jdbc/test"); } catch (Exception e) { throw new ServletException(e); } } ...}</example></s2><s2 title="JNDI configuration"><s3 title="resource-ref"><p>Factory configuration, including configuration fordatabase pooling. <var/resource-ref/> putsthe DataSource in a JNDI context and also in the ServletContext.Each web-app can configure its own database pool. Resin can alsoshare a common pool by putting the resource-ref in the <host> or inthe <http-server>.</p><p>More details are in the <a href='db-config.xtp'>database config</a>page.</p><p>The driver can be in WEB-INF/lib or WEB-INF/classes, although it'sa better idea to put it in the global classpath or resin-2.0.x/lib.</p><deftable><tr><th>Attribute<th>Meaning<tr><td>res-ref-name<td>JNDI path attribute to store the pool. Thepath is relative to java:comp/env.<tr><td>res-type<td>javax.sql.DataSource or javax.sql.XADataSource for database pools<tr><td>init-param<td>initialization parameters (Resin 1.2)<tr><td>init-class<td>Class containing init params (Map or Hashtable) (Resin 1.2.4)<tr><td>bean-name<td>optional bean class to be used as a resource (Resin 1.2)</deftable><p><var/init-param/> sets bean properties of the data source.You can look at the com.caucho.sql.DBPool JavaDoc for its interface.Unknown parameters are used to set the driver properties. So you canset any driver-specific property in the init-param.</p></s3><s3 title="env-entry"><p>JNDI parameter configuration. The env-entry configurationis similar to the init-param for servlets, but is accessible to anyJava class in the application without needing to pass along a context.</p><deftable><tr><th>Attribute<th>Meaning<tr><td>env-entry-name<td>JNDI path attribute to store the variable. The path is relative to java:comp/env.<tr><td>env-entry-type<td>Java type of the variable<tr><td>env-entry-value<td>The variable value.</deftable><p>The example configuration stores a string in java:comp/env/greeting.Following the J2EE spec, the env-entry-name is relative tojava:comp/env. If the env-entry is in the <host> context, it willbe visible to all web-apps in the host.</p><example title="Example resin.conf fragment"><env-entry> <env-entry-name>greeting</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>Hello, World</env-entry-value></env-entry></example><p>The following servlet fragment is a typical use in a servlet. Theservlet only looks up the variable once and stores it for later use.</p><example title="GreetingServlet.java">import java.io.*;import javax.naming.*;import javax.servlet.*;import javax.servlet.http.*;public class TestServlet extends HttpServlet { private String greeting; public void init() throws ServletException { try { Context env = (Context) new InitialContext().lookup("java:comp/env"); greeting = (String) env.lookup("greeting"); } catch (NamingException e) { throw new ServletException(e); } } ...}</example></s3><defun title="jndi-link" version="Resin 1.2"><p>Links a foreign JNDI context to the Resin JNDI context.For example, you can use <var/jndi-link/> to link in client EJBs froma foreign EJB container.</p><deftable><tr><th>Attribute<th>Description.<tr><td>jndi-name<td>JNDI path attribute to bind the link<tr><td>property-file<td>jndi.property to use to obtain the Context.<tr><td>jndi-factory<td>Class name of an InitialContextFactory used tocreate the bean.<tr><td>init-param<td>Properties to be used to get the initialcontext.<tr><td>jndi-lookup<td>JNDI path for the foreign context.</deftable><example title="Linking a WebLogic EJB client bean"><jndi-link> <jndi-name>java:comp/env/ejb/traderHome</jndi-name> <jndi-factory>weblogic.jndi.WLInitialContextFactory</jndi-factory> <init-param java.naming.provider.url="t3://localhost:7001"/> <jndi-lookup>statelessSession.TraderHome</jndi-lookup></jndi-link></example></defun></s2><s2 title="Known JNDI Object Factories"><s3 title='javax.sql.DataSource'><p>Configures a non-transactional JDBC data sources. More details areavailable on the <a href="db-config.xtp">database configuration</a> page.</p><deftable title='init-param values'><tr><th>Attribute<th>Meaning<tr><td>driver-name<td>The Java classname of the driver.<tr><td>url<td>The driver specific database url.<tr><td>data-source<td>A reference to an XADataSource or PooledDataSource.</deftable><p>Here's a sample minimal resin.conf fragment to bind a DBPool-baseddatabase to the JNDI path "java:comp/env/jdbc/test". The examplesbelow show how that JNDI path will be used.</p><example title="Sample resin.conf fragment"><resource-ref> <res-ref-name>jdbc/test</res-ref-name> <res-type>javax.sql.DataSource</res-type> <init-param driver-name="com.caucho.jdbc.mysql.Driver"/> <init-param url="jdbc:mysql-caucho://localhost:3306/test"/></resource-ref></example></s3><s3 title='javax.sql.XADataSource'><p>Configures a transactional JDBC data sources. More details areavailable on the <a href="db-config.xtp">database configuration</a> page.</p><deftable title='init-param values'><tr><th>Attribute<th>Meaning<tr><td>driver-name<td>The Java classname of the driver.<tr><td>url<td>The driver specific database url.</deftable><p>Here's a sample minimal resin.conf fragment to bind a transactionalDBPool-based database to the JNDI path "java:comp/env/jdbc/test". The examplesbelow show how that JNDI path will be used.</p><example title="Sample resin.conf fragment"><resource-ref> <res-ref-name>jdbc/test</res-ref-name> <res-type>javax.sql.XADataSource</res-type> <init-param driver-name="com.caucho.jdbc.mysql.Driver"/> <init-param url="jdbc:mysql-caucho://localhost:3306/test"/></resource-ref></example></s3><s3 title='javax.mail.Session'><p>JavaMail sessions are configured with resource-ref. The session iscreated with <var/Session.getInstance/> using the propertiesdefined in the init-param.</p><example><resource-ref res-ref-name='mail/MySession' res-type='javax.mail.Session'> <init-param mail.transport.protocol='smtp'> <init-param mail.host='localhost'> <init-param mail.user='harry'></resource-ref></example></s3></s2><s2 title="Custom Factories"><p>The resource-ref element can configure any bean-based factory.A new instance of the bean will be created from the specifiedclass-name. To make this work, the factory class must have apublic zero-arg constructor.</p><p>The <var/init-param/> elements configure the factory'sproperties using introspection. A 'foo' property expects asetFoo method, and a 'foo-bar' property expects a setFooBar property:</p><example title='custom.MyBean'>package custom;public class MyBean { private String foo; private int bar; public void setFoo(String foo) { this.foo = foo; } public void setBar(int bar) { this.bar = bar; } ...}</example><example title='Configuration for custom.MyBean'><resource-ref res-ref-name='custom/MyBean' class-name='test.MyBean'> <init-param foo='a string'> <init-param bar='613'></resource-ref></example><p>Once configured, the application will lookup thefactory in <var/java:comp/env/custom/MyBean/> and use it to createany needed application objects. As long as the class follows thebean patterns, it can be configured in resource-ref.</p></s2></s1>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -