Difference between revisions of "Jetty/Feature/JNDI"

From Eclipsepedia

< Jetty‎ | Feature
Jump to: navigation, search
m
m
Line 1: Line 1:
 
{{Jetty Feature  
 
{{Jetty Feature  
 
| introduction =  
 
| introduction =  
Jetty supports <code>java:comp/env</code> lookups in webapps. This is an optional feature, and as such some setup needs to be done. However, if you're using the [[http://dist.codehaus.org/jetty Hightide]] distribution of jetty, then this feature is already fully enabled for you, so you can skip any setup steps, and read the section on how to put objects into jetty's JNDI so that you can retrieve them at runtime.
+
Jetty supports <code>java:comp/env</code> lookups in webapps. This is an optional feature; as such, you need to do some setup. However, if you are using the [[http://dist.codehaus.org/jetty Hightide]] distribution of Jetty, this feature is already fully enabled, so you can skip any setup steps, and read the section on how to put objects into Jetty's JNDI so that you can retrieve them at runtime.
  
 
| body =
 
| body =
Line 7: Line 7:
 
== Setup ==
 
== Setup ==
  
=== Deployment-time configuration ===
+
=== Deployment-time Configuration ===
  
Skip this step if you are using the Hightide distribution of jetty as JNDI is automatically enabled for you. For non-Hightide distributions, you may enable JNDI either for a particular web app or you can enable it by default for all webapps. In either case, we need to re-define the list of configurations that can be applied to a WebAppContext on deployment:
+
Skip this step if you are using the Hightide distribution of Jetty, because JNDI is automatically enabled. For non-Hightide distributions, you can enable JNDI either for a particular web app or you can enable it by default for all webapps. In either case, you need to re-define the list of configurations that can apply to a WebAppContext on deployment:
 
<source lang="xml">
 
<source lang="xml">
 
<Array id="plusConfig" type="java.lang.String">
 
<Array id="plusConfig" type="java.lang.String">
Line 23: Line 23:
 
</source>
 
</source>
  
Now, to apply this to a single webapp, we create a context xml file that describes the setup of that particular webapp and instruct it to apply these special configurations on deployment:
+
To apply this list to a single webapp, create a context XML file that describes the setup of the particular webapp, and instruct it to apply these special configurations on deployment:
 
<source lang="xml">
 
<source lang="xml">
 
<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
 
<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
Line 44: Line 44:
 
</source>
 
</source>
  
Alternatively, we could apply these configurations to every webapp that is deployed. To do that, we edit the <code>$JETTY_HOME/etc/jetty.xml</code> file (or create a new new file and put it on the runline or put it in <code>start.ini</code>) to add:
+
Alternatively, you can apply these configurations to every webapp that is deployed. To do so, edit the <code>$JETTY_HOME/etc/jetty.xml</code> file (or create a new new file and put it on the runline or put it in <code>start.ini</code>) to add:
  
 
<source lang="xml">
 
<source lang="xml">
Line 67: Line 67:
 
</source>
 
</source>
 
{{tip|Tip:|
 
{{tip|Tip:|
We have included the <code>etc/jetty-plus.xml</code> configuration file that configures a WebAppDeployer to deploy all webapps in the <code>webapps-plus</code> directory with JNDI. You can modify this file as desired, or merge it with your <code>etc/jetty.xml</code> file.}}
+
This example includes the <code>etc/jetty-plus.xml</code> configuration file that configures a WebAppDeployer to deploy all webapps in the <code>webapps-plus</code> directory with JNDI. You can modify this file as desired, or merge it with your <code>etc/jetty.xml</code> file.}}
  
=== Classpath jars ===
+
=== Classpath Jars ===
  
Now that we have the JNDI configuration for the webapp(s) set up, we need to ensure that the JNDI implementation jars are on jetty's classpath. These jars are optional, so won't be there by default. We add these into the classpath by using startup time OPTIONS:
+
Now that you have the JNDI configuration for the webapp(s) set up, you need to ensure that the JNDI implementation jars are on Jetty's classpath. These jars are optional, so won't be there by default. You add these into the classpath by using startup time OPTIONS:
  
 
<source lang="bash">
 
<source lang="bash">
Line 78: Line 78:
  
 
{{tip|Tip:|If you prefer, you can edit the <code>start.ini</code> file and add "plus" to the default OPTIONS to lessen the verbosity of the runline.}}
 
{{tip|Tip:|If you prefer, you can edit the <code>start.ini</code> file and add "plus" to the default OPTIONS to lessen the verbosity of the runline.}}
You may now configure naming resources that can be referenced in a web.xml file and accessed from within the <code>java:comp/env</code> naming environment of the webapp during execution. Specifically, you may configure support for the following web.xml elements:
+
You can now configure naming resources to reference in a web.xml file and access from within the <code>java:comp/env</code> naming environment of the webapp during execution. Specifically, you can configure support for the following web.xml elements:
  
 
<source lang="xml">
 
<source lang="xml">
Line 88: Line 88:
 
[[#Configuring env-entrys]] shows you how to set up overrides for <code><env-entry></code> elements in web.xml. [[#Configuring resource-refs and resource-env-refs]] discusses how to configure support resources such as <code>javax.sql.DataSource</code>.
 
[[#Configuring env-entrys]] shows you how to set up overrides for <code><env-entry></code> elements in web.xml. [[#Configuring resource-refs and resource-env-refs]] discusses how to configure support resources such as <code>javax.sql.DataSource</code>.
  
Furthermore, it is possible to plug a JTA <code>javax.transaction.UserTransaction</code> implementation into Jetty so that webapps can lookup <code>java:comp/UserTransaction</code> to obtain a distributed transaction manager. See [[#Configuring XA Transactions]].
+
You can also plug a JTA <code>javax.transaction.UserTransaction</code> implementation into Jetty so that webapps can lookup <code>java:comp/UserTransaction</code> to obtain a distributed transaction manager. See [[#Configuring XA Transactions]].
  
 
You can define your naming resources with 3 scopes:
 
You can define your naming resources with 3 scopes:
  
# jvm scope - the name is unique within the jvm
+
# jvm scope–the name is unique within the jvm
# server scope - the name is unique to the Server instance
+
# server scope–the name is unique to the Server instance
# webapp scope - the name is unique to the WebAppContext instance
+
# webapp scope–the name is unique to the WebAppContext instance
  
The section [[#Global or scoped to a webapp]] explains what scoping is, and shows you how to use it. Essentially, scoping ensures that JNDI bindings from one webapp do not interfere with the JNDI bindings of another - unless of course you wish them to.
+
The section [[#Global or scoped to a webapp]] explains ''scoping'', and shows you how to use it. Essentially, scoping ensures that JNDI bindings from one webapp do not interfere with the JNDI bindings of another–unless of course you want them to.
  
Before we go any further, lets take a look at what kind of things can be bound into JNDI with Jetty.
 
  
=== What can be bound and general overview ===
+
=== What Can Be Bound and General Overview ===
  
There are 4 types of objects that can be bound into Jetty's JNDI:
+
Four types of objects can be bound into Jetty JNDI:
  
* an ordinary POJO instance
+
* An ordinary POJO instance
* a [http://java.sun.com/j2se/1.5.0/docs/api/javax/naming/Reference.html java.naming.Reference] instance
+
* A [http://java.sun.com/j2se/1.5.0/docs/api/javax/naming/Reference.html java.naming.Reference] instance
* an object instance that implements the [http://java.sun.com/j2se/1.5.0/docs/api/javax/naming/Referenceable.html java.naming.Referenceable] interface
+
* An object instance that implements the [http://java.sun.com/j2se/1.5.0/docs/api/javax/naming/Referenceable.html java.naming.Referenceable] interface
* a linkage between a name as referenced in web.xml and as referenced in the environment
+
* A linkage between a name as referenced in web.xml and as referenced in the environment
  
 
The binding for all of these object types generally follows the same pattern:
 
The binding for all of these object types generally follows the same pattern:
Line 126: Line 125:
 
* <code>"org.eclipse.jetty.plus.jndi.Link"</code> for link between a web.xml resource name and a NamingEntry. See Configuring Links section for more info.
 
* <code>"org.eclipse.jetty.plus.jndi.Link"</code> for link between a web.xml resource name and a NamingEntry. See Configuring Links section for more info.
  
There are 3 places in which you can define naming entries:
+
There are three places in which you can define naming entries:
  
 
# <code>jetty.xml</code>
 
# <code>jetty.xml</code>
Line 132: Line 131:
 
# context xml file
 
# context xml file
  
Naming entries defined in a <code>jetty.xml</code> file will generally be scoped at either the jvm level or the Server level. Naming entries in a <code>jetty-env.xml</code> file will generally be scoped to the webapp in which the file resides, although you are able to enter jvm or Server scopes if you wish, that is not really recommended. In most cases you will define all naming entries that you want visible to a particular Server instance, or to the jvm as a whole in a jetty.xml file. Entries in a context xml file will generally be scoped at the level of the webapp to which it applies, although once again, you can supply a less strict scoping level of Server or JVM if you want.
+
Naming entries defined in a <code>jetty.xml</code> file are scoped at either the jvm level or the Server level. Naming entries in a <code>jetty-env.xml</code> file are scoped to the webapp in which the file resides; although you can enter jvm or Server scopes if you choose, we do not recommend doing so. In most cases you define all naming entries that you want visible to a particular Server instance, or to the jvm as a whole in a jetty.xml file. Entries in a context xml file are scoped at the level of the webapp to which they apply, although once again, you can supply a less strict scoping level of Server or JVM if you choose.
  
 
=== Configuring env-entrys ===
 
=== Configuring env-entrys ===
Sometimes it is useful to be able to pass configuration information to a webapp at runtime that either cannot be or is not convenient to be coded into a web.xml <code><env-entry></code>. In this case, you can use <code>org.eclipse.jetty.plus.naming.EnvEntry</code> and even configure them to override an entry of the same name in web.xml.
+
Sometimes it is useful to be able to pass configuration information to a webapp at runtime that you either cannot or cannot conveniently code into a web.xml <code><env-entry></code>. In this case, you can use <code>org.eclipse.jetty.plus.naming.EnvEntry</code>, and even configure them to override an entry of the same name in web.xml.
  
 
<source lang="xml">
 
<source lang="xml">
Line 146: Line 145:
 
</source>
 
</source>
  
This example will define a virtual <code><env-entry></code> called <code>mySpecialValue</code> with value <code>4000</code> that is unique within the whole jvm. It will be put into JNDI at <code>java:comp/env/mySpecialValue</code> for _every_ webapp deployed. Moreover, the boolean argument indicates that this value should override an <code>env-entry</code> of the same name in web.xml. If you don't want to override, then omit this argument or set it to <code>false</code>.
+
This example defines a virtual <code><env-entry></code> called <code>mySpecialValue</code> with value <code>4000</code> that is unique within the whole jvm. It is put into JNDI at <code>java:comp/env/mySpecialValue</code> for _every_ webapp deployed. Moreover, the boolean argument indicates that this value should override an <code>env-entry</code> of the same name in web.xml. If you don't want to override, then omit this argument, or set it to <code>false</code>.
  
 
See [[#Global or scoped to a webapp]] for more information on other scopes.
 
See [[#Global or scoped to a webapp]] for more information on other scopes.
Line 162: Line 161:
 
* java.lang.Boolean
 
* java.lang.Boolean
  
However, Jetty is a little more flexible and will also allow you to bind custom POJOs, [http://java.sun.com/j2se/1.5.0/docs/api/javax/naming/Reference.html javax.naming.Reference's] and [http://java.sun.com/j2se/1.5.0/docs/api/javax/naming/Referenceable.html javax.naming.Referenceable's]. Be aware if you take advantage of this feature that your web application will *not be portable*.
+
However, Jetty is a little more flexible and also allows you to bind custom POJOs, [http://java.sun.com/j2se/1.5.0/docs/api/javax/naming/Reference.html javax.naming.Reference's] and [http://java.sun.com/j2se/1.5.0/docs/api/javax/naming/Referenceable.html javax.naming.Referenceable's]. Be aware that if you take advantage of this feature that your web application will *not be portable*.
  
To use the <code>EnvEntry</code> configured above, use code in your servlet/filter/etc such as:
+
To use the <code>EnvEntry</code> configured above, use code in your servlet/filter/etc, such as:
  
 
<source lang="java">
 
<source lang="java">
Line 175: Line 174:
 
=== Configuring resource-refs and resource-env-refs ===
 
=== Configuring resource-refs and resource-env-refs ===
  
Any type of resource that you want to refer to in a web.xml file as a <code><resource-ref></code> or <code><resource-env-ref></code> can be configured using the <code>org.eclipse.jetty.plus.jndi.Resource</code> type of naming entry. You provide the scope, the name of the object (relative to <code>java:comp/env</code>) and a POJO instance or a  javax.naming.Reference instance or javax.naming.Referenceable instance.
+
You can configure any type of resource that you want to refer to in a web.xml file as a <code><resource-ref></code> or <code><resource-env-ref></code> using the <code>org.eclipse.jetty.plus.jndi.Resource</code> type of naming entry. You provide the scope, the name of the object (relative to <code>java:comp/env</code>) and a POJO instance or a  javax.naming.Reference instance or javax.naming.Referenceable instance.
  
The [http://jcp.org/aboutJava/communityprocess/pr/jsr244/index.html J2EE Specification] recommends that DataSources are stored in <code>java:comp/env/jdbc</code>, JMS connection factories under <code>java:comp/env/jms</code>, JavaMail connection factories under <code>java:comp/env/mail</code> and URL connection factories under <code>java:comp/env/url</code>. For example:
+
The [http://jcp.org/aboutJava/communityprocess/pr/jsr244/index.html J2EE Specification] recommends that DataSources be stored in <code>java:comp/env/jdbc</code>, JMS connection factories under <code>java:comp/env/jms</code>, JavaMail connection factories under <code>java:comp/env/mail</code> and URL connection factories under <code>java:comp/env/url</code>. For example:
  
 
<table>
 
<table>
Line 188: Line 187:
 
=== Configuring DataSources ===
 
=== Configuring DataSources ===
  
Lets look at an example of configuring a javax.sql.DataSource. Jetty can use any DataSource implementation available on it's classpath. In our example, we'll use a DataSource from the [http://db.apache.org/derby Derby] relational database, but you can use any implementation of a <code>javax.sql.DataSource</code>. In this example, we'll configure it as scoped to a webapp with the id of 'wac':
+
Here is an example of configuring a javax.sql.DataSource. Jetty can use any DataSource implementation available on its classpath. In this example, the DataSource is from the [http://db.apache.org/derby Derby] relational database, but you can use any implementation of a <code>javax.sql.DataSource</code>. This example, configures it as scoped to a webapp with the id of 'wac':
  
 
<source lang="xml">
 
<source lang="xml">
Line 206: Line 205:
 
</source>
 
</source>
  
The above would create an instance of <code>org.apache.derby.jdbc.EmbeddedDataSource</code>, call the two setter methods <code>setDatabaseName("test");</code> and <code>setCreateDatabase("create");</code> and bind it into the JNDI scope for the webapp. If you have the appropriate <resource-ref> setup in your web.xml, then it will be available from application lookups as <code>java:comp/env/jdbc/myds</code>.
+
The code above creates an instance of <code>org.apache.derby.jdbc.EmbeddedDataSource</code>, calls the two setter methods <code>setDatabaseName("test");</code> and <code>setCreateDatabase("create");</code> and binds it into the JNDI scope for the webapp. If you have the appropriate <resource-ref> setup in your web.xml, then it is available from application lookups as <code>java:comp/env/jdbc/myds</code>.
  
To lookup your DataSource in your servlet/filter/etc do:
+
To lookup your DataSource in your servlet/filter/etc:
  
 
<source lang="java">
 
<source lang="java">
Line 218: Line 217:
 
</source>
 
</source>
  
{{note|Careful!|When configuring Resources, you need to ensure that the type of object you configure matches the type of object you expect to lookup in <code>java:comp/env</code>. For database connection factories, this means that the object you register as a Resource *must* implement the <code>javax.sql.DataSource</code> interface.}}
+
{{note|Careful!|When configuring Resources, you need to ensure that the type of object you configure matches the type of object you expect to look up in <code>java:comp/env</code>. For database connection factories, this means that the object you register as a Resource *must* implement the <code>javax.sql.DataSource</code> interface.}}
  
 
=== Configuring JMS Queues, Topics and ConnectionFactories ===
 
=== Configuring JMS Queues, Topics and ConnectionFactories ===
  
Jetty is able to bind any implementation of the JMS destinations and connection factories. You just need to ensure the implementation jars are available on Jetty's classpath.
+
Jetty is able to bind any implementation of the JMS destinations and connection factories. You just need to ensure the implementation Jars are available on Jetty's classpath.
  
Here's an example of binding an [http://www.activemq.org ActiveMQ] in-JVM connection factory:
+
Here is an example of binding an [http://www.activemq.org ActiveMQ] in-JVM connection factory:
  
 
<source lang="xml">
 
<source lang="xml">
Line 241: Line 240:
 
</source>
 
</source>
  
There is more information about [http://www.activemq.org ActiveMQ] and Jetty [[Integrating with ActiveMQ]].
+
For more information, see [http://www.activemq.org ActiveMQ] and Jetty [[Integrating with ActiveMQ]].
  
 
=== Configuring Mail ===
 
=== Configuring Mail ===
  
Jetty also provides infrastructure for providing access to javax.mail.Sessions from within an application:
+
Jetty also provides infrastructure for access to javax.mail.Sessions from within an application:
  
 
<source lang="xml">
 
<source lang="xml">
Line 270: Line 269:
 
</source>
 
</source>
  
The setup above creates an instance of the <code>org.eclipse.jetty.jndi.factories.MailSessionReference</code> class, calls it's setter methods <code>setUser("fred");</code>, <code>setPassword("OBF:1xmk1w261z0f1w1c1xmq");</code> to set up the authentication for the mail system, then populates a set of Properties, setting them on the MailSessionReference instance. The result of this is that an application can lookup <code>java:comp/env/mail/Session</code> at runtime and obtain access to a <code>javax.mail.Session</code> that has the necessary configuration to permit it to send email via SMTP.
+
The setup above creates an instance of the <code>org.eclipse.jetty.jndi.factories.MailSessionReference</code> class, calls its setter methods <code>setUser("fred");</code>, <code>setPassword("OBF:1xmk1w261z0f1w1c1xmq");</code> to set up the authentication for the mail system, and populates a set of Properties, setting them on the MailSessionReference instance. The result is that an application can lookup <code>java:comp/env/mail/Session</code> at runtime and obtain access to a <code>javax.mail.Session</code> that has the necessary configuration to permit it to send email via SMTP.
  
 
{tip}
 
{tip}
You can set the password to be plain text, or use Jetty's [[Jetty/Howto/Secure Passwords|password obfuscation]] mechanism to make the config file more secure from prying eyes. Note that the other Jetty encryption mechanisms of MD5 and Crypt cannot be used as the original password cannot be recovered, which is necessary for the mail system.
+
You can set the password to be plain text, or use Jetty's [[Jetty/Howto/Secure Passwords|password obfuscation]] mechanism to make the config file more secure from prying eyes. Note that you cannot use the other Jetty encryption mechanisms of MD5 and Crypt because the original password cannot be recovered, which is necessary for the mail system.
 
{tip}
 
{tip}
  
We will be adding more examples of configuring database datasources (eg using [http://xapool.experlog.com XAPool] and [http://jakarta.apache.org/commons/dbcp DBCP]) and jms connection factories, so check back regularly. Contributions are also welcome.
+
We will be adding more examples of configuring database datasources (for example, using [http://xapool.experlog.com XAPool] and [http://jakarta.apache.org/commons/dbcp DBCP]) and jms connection factories, so check back. Contributions are also welcome.
  
 
=== Configuring XA Transactions ===
 
=== Configuring XA Transactions ===
  
If you want to be able to perform distributed transactions with your resources, you will need a transaction manager that supports the JTA interfaces that you can lookup as <code>java:comp/UserTransaction</code> in your webapp. Jetty does not ship with one, rather you may plug in the one of your preference. You can configure the one of your choice using the <code>org.eclipse.jetty.plus.jndi.Transaction</code> object in a jetty config file. In the following example, we will configure the [http://www.atomikos.com Atomikos] transaction manager:
+
If you want to perform distributed transactions with your resources, you need a transaction manager that supports the JTA interfaces that you can look up as <code>java:comp/UserTransaction</code> in your webapp. Jetty does not ship with one, but you can plug in the one you prefer. You can configure a transaction manager using the <code>org.eclipse.jetty.plus.jndi.Transaction</code> object in a Jetty config file. The following example configures the [http://www.atomikos.com Atomikos] transaction manager:
  
 
<source lang="xml">
 
<source lang="xml">
Line 290: Line 289:
 
</source>
 
</source>
  
{{tip|Hint:|To use the Atomikos transaction manager, you need to download it and install it. There are instructions [[http://docs.codehaus.org/display/JETTY/Atomikos here]] on how to configure it for jetty6.}}
+
{{tip|Hint:|To use the Atomikos transaction manager, you need to download it and install it. Instructions [[http://docs.codehaus.org/display/JETTY/Atomikos here]] describe how to configure it for jetty6.}}
  
 
See also the instructions for how to configure [[JOTM]]. Contributions of instructions for other transaction managers are welcome.
 
See also the instructions for how to configure [[JOTM]]. Contributions of instructions for other transaction managers are welcome.
Line 296: Line 295:
 
=== Configuring Links ===
 
=== Configuring Links ===
  
Usually, the name you configure for your NamingEntry should be the same as the name you refer to it as in you web.xml. For example:
+
The name you set for your NamingEntry should be the same as the name you use for it in web.xml. For example:
  
 
<source lang="xml">
 
<source lang="xml">
Line 330: Line 329:
 
</source>
 
</source>
  
If you wish, you can refer to it in web.xml by a different name, and link it to the name in your org.eclipse.jetty.plus.jndi.Resource by using an org.eclipse.jetty.plus.jndi.Link type of NamingEntry. For the example above, we could refer to the <code>jdbc/mydatasource</code> resource as <code>jdbc/mydatasource1</code> by doing:
+
You can refer to it in web.xml by a different name, and link it to the name in your org.eclipse.jetty.plus.jndi.Resource by using an org.eclipse.jetty.plus.jndi.Link type of NamingEntry. For the example above, you can refer to the <code>jdbc/mydatasource</code> resource as <code>jdbc/mydatasource1</code> as follows:
  
 
In a context xml file:
 
In a context xml file:
Line 374: Line 373:
 
This can be useful when you cannot change web.xml but need to link it to a resource in your deployment environment.
 
This can be useful when you cannot change web.xml but need to link it to a resource in your deployment environment.
  
=== Global or scoped to a webapp ===
+
=== Global or Scoped to a webapp ===
As we said before, you can control the visibility of your JNDI naming entries within your jvm, Server and WebAppContext instances. Naming entries at the _jvm scope_ are visible by any application code, and are available to be bound to <code>java:comp/env</code>. Naming entries at the _Server scope_ will not interfere with entries of the same name in a different Server instance, and are avilable to be bound to java:comp/env of any webapps deployed to that Server instance. Finally, the most specific scope are entries at the _webapp scope_. These are only available to be bound to java:comp/env of the webapp in which it is defined.
+
As previously stated, you can control the visibility of your JNDI naming entries within your jvm, Server and WebAppContext instances. Naming entries at the _jvm scope_ are visible by any application code, and are available to be bound to <code>java:comp/env</code>. Naming entries at the _Server scope_ do not interfere with entries of the same name in a different Server instance, and are available to be bound to java:comp/env of any webapps deployed to that Server instance. Finally, the most specific scope are entries at the _webapp scope_. These are only available to be bound to java:comp/env of the webapp in which it is defined.
  
The scope is controlled by the 1st parameter to the NamingEntry.
+
The scope is controlled by the first parameter to the NamingEntry.
  
 
The jvm scope is represented by a null parameter:
 
The jvm scope is represented by a null parameter:
Line 424: Line 423:
 
</source>
 
</source>
  
As you can see, the most natural config files in which to declare naming entries of each scope are:
+
As you can see, the most natural configuration files in which to declare naming entries of each scope are:
 
* <code>etc/jetty.xml</code> - jvm or Server scope
 
* <code>etc/jetty.xml</code> - jvm or Server scope
 
* <code>WEB-INF/jetty-env.xml</code> or a context xml file - webapp scope
 
* <code>WEB-INF/jetty-env.xml</code> or a context xml file - webapp scope
Line 431: Line 430:
 
== Demo Web Application ==
 
== Demo Web Application ==
  
There is a demonstration webapp which sets up examples of all of the JNDI resources we've discussed so far.
+
There is a demonstration webapp which sets up examples of all of the JNDI resources discussed so far.
  
To run this demonstration, you need to download the transaction manager of your choice and [http://db.apache.org/derby Derby] . At the time of writing, the webapp has been tested with both [http://jotm.objectweb.org JOTM] and with [http://www.atomikos.com Atomikos] transaction managers.
+
To run this demonstration, you need to download the transaction manager of your choice and [http://db.apache.org/derby Derby]. At the time of writing, the webapp has been tested with both [http://jotm.objectweb.org JOTM] and with [http://www.atomikos.com Atomikos] transaction managers.
  
 
=== Building the Demo ===
 
=== Building the Demo ===
  
The demo webapp is included with Jetty Hightide distribution. Alternatively, it can be built from sources located in <code>examples/test-jndi-webapp</code>. There is a <code>README.txt</code> file in there which explains how to build it, and how to add support for different transaction managers.
+
The demo webapp is included with Jetty Hightide distribution. Alternatively, you can be build it from sources located in <code>examples/test-jndi-webapp</code>. A <code>README.txt</code> file there explains how to build it, and how to add support for different transaction managers.
  
* run <code>mvn clean install</code> to build it
+
* Run <code>mvn clean install</code> to build it.
* then edit <code>contexts/test-jndi.xml</code> and uncomment one of the transaction manager setups
+
* Edit <code>contexts/test-jndi.xml</code> and uncomment one of the transaction manager setups.
* then edit <code>contexts/test-jndi.d/WEB-INF/jetty-env.xml</code> and uncomment one of the transaction manager setups
+
* Edit <code>contexts/test-jndi.d/WEB-INF/jetty-env.xml</code> and uncomment one of the transaction manager setups.
* copy a <code>derby.jar</code> to the jetty <code>lib/</code> directory, as well as copy all the necessary jars for the flavour of transaction manager you are using. There are instructions for some of the popular transaction managers on the wiki at JNDI.
+
* Copy a <code>derby.jar</code> to the jetty <code>lib/</code> directory, and also copy all the necessary Jars for the flavor of transaction manager you are using. Instructions for some popular transaction managers are on the wiki at JNDI.
  
You run the demo like so:
+
Run the demo:
  
 
<source lang="bash">
 
<source lang="bash">
Line 456: Line 455:
 
=== Adding Support for a Different Transaction Manager ===
 
=== Adding Support for a Different Transaction Manager ===
  
# Edit the <code>src/etc/templates/filter.properties</code> file and add a new set of token and replacement strings following the pattern established for ATOMIKOS and JOTM.
+
# Edit the <code>src/etc/templates/filter.properties</code> file, and add a new set of token and replacement strings following the pattern established for ATOMIKOS and JOTM.
# Edit the <code>src/etc/templates/jetty-env.xml</code> file and add configuration for new transaction manager following the pattern established for the other transaction managers.
+
# Edit the <code>src/etc/templates/jetty-env.xml</code> file, and add configuration for new transaction manager following the pattern established for the other transaction managers.
# Edit the <code>src/etc/templates/jetty-test-jndi.xml</code> file and add configuration for the new transaction manager following the pattern established for the other transaction managers.
+
# Edit the <code>src/etc/templates/jetty-test-jndi.xml</code> file, and add configuration for the new transaction manager following the pattern established for the other transaction managers.
 
| more =
 
| more =
For more information on setting up a JNDI datasource please see [[Jetty/Howto/Configure JNDI Datasource|How to Configure JNDI Datasource]] page.
+
For more information on setting up a JNDI datasource, see [[Jetty/Howto/Configure JNDI Datasource|How to Configure JNDI Datasource]] page.
  
For documentation on how to configure <tt>jetty-env.xml</tt>, please consult the [[Jetty/Reference/jetty-env.xml|reference guide]].
+
For documentation on how to configure <tt>jetty-env.xml</tt>, consult the [[Jetty/Reference/jetty-env.xml|reference guide]].
 
}}
 
}}

Revision as of 19:14, 10 January 2011



Contents

Introduction

Jetty supports java:comp/env lookups in webapps. This is an optional feature; as such, you need to do some setup. However, if you are using the [Hightide] distribution of Jetty, this feature is already fully enabled, so you can skip any setup steps, and read the section on how to put objects into Jetty's JNDI so that you can retrieve them at runtime.

Feature

Setup

Deployment-time Configuration

Skip this step if you are using the Hightide distribution of Jetty, because JNDI is automatically enabled. For non-Hightide distributions, you can enable JNDI either for a particular web app or you can enable it by default for all webapps. In either case, you need to re-define the list of configurations that can apply to a WebAppContext on deployment:

<Array id="plusConfig" type="java.lang.String">
  <Item>org.eclipse.jetty.webapp.WebInfConfiguration</Item>
  <Item>org.eclipse.jetty.webapp.WebXmlConfiguration</Item>
  <Item>org.eclipse.jetty.webapp.MetaInfConfiguration</Item>
  <Item>org.eclipse.jetty.webapp.FragmentConfiguration</Item>
  <Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item> <!-- add -->
  <Item>org.eclipse.jetty.plus.webapp.Configuration</Item>    <!-- add -->
  <Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item>
  <Item>org.eclipse.jetty.webapp.TagLibConfiguration</Item>
</Array>

To apply this list to a single webapp, create a context XML file that describes the setup of the particular webapp, and instruct it to apply these special configurations on deployment:

<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
 
  <Array id="plusConfig" type="java.lang.String">
    <Item>org.eclipse.jetty.webapp.WebInfConfiguration</Item>
    <Item>org.eclipse.jetty.webapp.WebXmlConfiguration</Item>
    <Item>org.eclipse.jetty.webapp.MetaInfConfiguration</Item>
    <Item>org.eclipse.jetty.webapp.FragmentConfiguration</Item>
    <Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item> <!-- add for JNDI -->
    <Item>org.eclipse.jetty.plus.webapp.Configuration</Item>    <!-- add for JNDI -->
    <Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item>
    <Item>org.eclipse.jetty.webapp.TagLibConfiguration</Item>
  </Array>
 
  <Set name="war"><SystemProperty name="jetty.home" default="."/>/webapps/my-cool-webapp</Set>
  <Set name="configurationClasses"><Ref id="plusConfig"/></Set>
 
</Configure>

Alternatively, you can apply these configurations to every webapp that is deployed. To do so, edit the $JETTY_HOME/etc/jetty.xml file (or create a new new file and put it on the runline or put it in start.ini) to add:

<Configure id="Server" class="org.eclipse.jetty.server.Server">
 
    <Call name="setAttribute">
      <Arg>org.eclipse.jetty.webapp.configuration</Arg>
      <Arg>
          <Array type="java.lang.String">
              <Item>org.eclipse.jetty.webapp.WebInfConfiguration</Item>
              <Item>org.eclipse.jetty.webapp.WebXmlConfiguration</Item>
              <Item>org.eclipse.jetty.webapp.MetaInfConfiguration</Item>
              <Item>org.eclipse.jetty.webapp.FragmentConfiguration</Item>
              <Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item>
              <Item>org.eclipse.jetty.plus.webapp.Configuration</Item>
              <Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item>
              <Item>org.eclipse.jetty.webapp.TagLibConfiguration</Item>
          </Array>
      </Arg>
    </Call>
</Configure>
Idea.png
Tip:
This example includes the etc/jetty-plus.xml configuration file that configures a WebAppDeployer to deploy all webapps in the webapps-plus directory with JNDI. You can modify this file as desired, or merge it with your etc/jetty.xml file.


Classpath Jars

Now that you have the JNDI configuration for the webapp(s) set up, you need to ensure that the JNDI implementation jars are on Jetty's classpath. These jars are optional, so won't be there by default. You add these into the classpath by using startup time OPTIONS:

java -jar start.jar OPTIONS=plus
Idea.png
Tip:
If you prefer, you can edit the start.ini file and add "plus" to the default OPTIONS to lessen the verbosity of the runline.

You can now configure naming resources to reference in a web.xml file and access from within the java:comp/env naming environment of the webapp during execution. Specifically, you can configure support for the following web.xml elements:

<env-entry/>
<resource-ref/>
<resource-env-ref/>

#Configuring env-entrys shows you how to set up overrides for <env-entry> elements in web.xml. #Configuring resource-refs and resource-env-refs discusses how to configure support resources such as javax.sql.DataSource.

You can also plug a JTA javax.transaction.UserTransaction implementation into Jetty so that webapps can lookup java:comp/UserTransaction to obtain a distributed transaction manager. See #Configuring XA Transactions.

You can define your naming resources with 3 scopes:

  1. jvm scope–the name is unique within the jvm
  2. server scope–the name is unique to the Server instance
  3. webapp scope–the name is unique to the WebAppContext instance

The section #Global or scoped to a webapp explains scoping, and shows you how to use it. Essentially, scoping ensures that JNDI bindings from one webapp do not interfere with the JNDI bindings of another–unless of course you want them to.


What Can Be Bound and General Overview

Four types of objects can be bound into Jetty JNDI:

The binding for all of these object types generally follows the same pattern:

<New class=type of naming entry>
  <Arg>scope</Arg>
  <Arg>name to bind as</Arg>
  <Arg>the object to bind</Arg>
</New>

The type of naming entry can be:

  • "org.eclipse.jetty.plus.jndi.EnvEntry" for <env-entry>s
  • "org.eclipse.jetty.plus.jndi.Resource" for all other type of resources
  • "org.eclipse.jetty.plus.jndi.Transaction" for a JTA manager. We'll take a closer look at this in the #Configuring XA Transactions section.
  • "org.eclipse.jetty.plus.jndi.Link" for link between a web.xml resource name and a NamingEntry. See Configuring Links section for more info.

There are three places in which you can define naming entries:

  1. jetty.xml
  2. WEB-INF/jetty-env.xml
  3. context xml file

Naming entries defined in a jetty.xml file are scoped at either the jvm level or the Server level. Naming entries in a jetty-env.xml file are scoped to the webapp in which the file resides; although you can enter jvm or Server scopes if you choose, we do not recommend doing so. In most cases you define all naming entries that you want visible to a particular Server instance, or to the jvm as a whole in a jetty.xml file. Entries in a context xml file are scoped at the level of the webapp to which they apply, although once again, you can supply a less strict scoping level of Server or JVM if you choose.

Configuring env-entrys

Sometimes it is useful to be able to pass configuration information to a webapp at runtime that you either cannot or cannot conveniently code into a web.xml <env-entry>. In this case, you can use org.eclipse.jetty.plus.naming.EnvEntry, and even configure them to override an entry of the same name in web.xml.

<New class="org.eclipse.jetty.plus.jndi.EnvEntry">
  <Arg></Arg>
  <Arg>mySpecialValue</Arg>
  <Arg type="java.lang.Integer">4000</Arg>
  <Arg type="boolean">true</Arg>
</New>

This example defines a virtual <env-entry> called mySpecialValue with value 4000 that is unique within the whole jvm. It is put into JNDI at java:comp/env/mySpecialValue for _every_ webapp deployed. Moreover, the boolean argument indicates that this value should override an env-entry of the same name in web.xml. If you don't want to override, then omit this argument, or set it to false.

See #Global or scoped to a webapp for more information on other scopes.

Note that the Servlet Specification only allows the following types of object to be bound to an env-entry:

  • java.lang.String
  • java.lang.Integer
  • java.lang.Float
  • java.lang.Double
  • java.lang.Long
  • java.lang.Short
  • java.lang.Character
  • java.lang.Byte
  • java.lang.Boolean

However, Jetty is a little more flexible and also allows you to bind custom POJOs, javax.naming.Reference's and javax.naming.Referenceable's. Be aware that if you take advantage of this feature that your web application will *not be portable*.

To use the EnvEntry configured above, use code in your servlet/filter/etc, such as:

import javax.naming.InitialContext;
 
InitialContext ic = new InitialContext();
Integer mySpecialValue = (Integer)ic.lookup("java:comp/env/mySpecialValue");

Configuring resource-refs and resource-env-refs

You can configure any type of resource that you want to refer to in a web.xml file as a <resource-ref> or <resource-env-ref> using the org.eclipse.jetty.plus.jndi.Resource type of naming entry. You provide the scope, the name of the object (relative to java:comp/env) and a POJO instance or a javax.naming.Reference instance or javax.naming.Referenceable instance.

The J2EE Specification recommends that DataSources be stored in java:comp/env/jdbc, JMS connection factories under java:comp/env/jms, JavaMail connection factories under java:comp/env/mail and URL connection factories under java:comp/env/url. For example:

Resource Type Name in jetty.xml Environment Lookup
javax.sql.DataSource jdbc/myDB java:comp/env/jdbc/myDB
javax.jms.QueueConnectionFactory jms/myQueue java:comp/env/jms/myQueue
javax.mail.Session mail/myMailService java:comp/env/mail/myMailService

Configuring DataSources

Here is an example of configuring a javax.sql.DataSource. Jetty can use any DataSource implementation available on its classpath. In this example, the DataSource is from the Derby relational database, but you can use any implementation of a javax.sql.DataSource. This example, configures it as scoped to a webapp with the id of 'wac':

<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
...
<New id="myds" class="org.eclipse.jetty.plus.jndi.Resource">
  <Arg><Ref id="wac"/></Arg>
  <Arg>jdbc/myds</Arg>
  <Arg>
    <New class="org.apache.derby.jdbc.EmbeddedDataSource">
      <Set name="DatabaseName">test</Set>
      <Set name="createDatabase">create</Set>
    </New>
  </Arg>
</New>
</Configure>

The code above creates an instance of org.apache.derby.jdbc.EmbeddedDataSource, calls the two setter methods setDatabaseName("test"); and setCreateDatabase("create"); and binds it into the JNDI scope for the webapp. If you have the appropriate <resource-ref> setup in your web.xml, then it is available from application lookups as java:comp/env/jdbc/myds.

To lookup your DataSource in your servlet/filter/etc:

import javax.naming.InitialContext;
import javax.sql.DataSource;
 
InitialContext ic = new InitialContext();
DataSource myDS = (DataSource)ic.lookup("java:comp/env/jdbc/myds");
Note.png
Careful!
When configuring Resources, you need to ensure that the type of object you configure matches the type of object you expect to look up in java:comp/env. For database connection factories, this means that the object you register as a Resource *must* implement the javax.sql.DataSource interface.


Configuring JMS Queues, Topics and ConnectionFactories

Jetty is able to bind any implementation of the JMS destinations and connection factories. You just need to ensure the implementation Jars are available on Jetty's classpath.

Here is an example of binding an ActiveMQ in-JVM connection factory:

<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
...
<New id="cf" class="org.eclipse.jetty.plus.jndi.Resource">
  <Arg><Ref id='wac'/></Arg>
  <Arg>jms/connectionFactory</Arg>
  <Arg>
    <New class="org.apache.activemq.ActiveMQConnectionFactory">
       <Arg>vm://localhost?broker.persistent=false</Arg>
    </New>
  </Arg>
</New>
</Configure>

For more information, see ActiveMQ and Jetty Integrating with ActiveMQ.

Configuring Mail

Jetty also provides infrastructure for access to javax.mail.Sessions from within an application:

<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
...
<New id="mail" class="org.eclipse.jetty.plus.jndi.Resource">
     <Arg><Ref id="wac"/></Arg>
     <Arg>mail/Session</Arg>
     <Arg>
       <New class="org.eclipse.jetty.jndi.factories.MailSessionReference">
         <Set name="user">fred</Set>
         <Set name="password">OBF:1xmk1w261z0f1w1c1xmq</Set>
         <Set name="properties">
           <New class="java.util.Properties">
             <Put name="mail.smtp.host">XXX</Put>
             <Put name="mail.from">me@me</Put>
             <Put name="mail.debug">true</Put>
           </New>
          </Set>
       </New>
     </Arg>
</New>
</Configure>

The setup above creates an instance of the org.eclipse.jetty.jndi.factories.MailSessionReference class, calls its setter methods setUser("fred");, setPassword("OBF:1xmk1w261z0f1w1c1xmq"); to set up the authentication for the mail system, and populates a set of Properties, setting them on the MailSessionReference instance. The result is that an application can lookup java:comp/env/mail/Session at runtime and obtain access to a javax.mail.Session that has the necessary configuration to permit it to send email via SMTP.

{tip} You can set the password to be plain text, or use Jetty's password obfuscation mechanism to make the config file more secure from prying eyes. Note that you cannot use the other Jetty encryption mechanisms of MD5 and Crypt because the original password cannot be recovered, which is necessary for the mail system. {tip}

We will be adding more examples of configuring database datasources (for example, using XAPool and DBCP) and jms connection factories, so check back. Contributions are also welcome.

Configuring XA Transactions

If you want to perform distributed transactions with your resources, you need a transaction manager that supports the JTA interfaces that you can look up as java:comp/UserTransaction in your webapp. Jetty does not ship with one, but you can plug in the one you prefer. You can configure a transaction manager using the org.eclipse.jetty.plus.jndi.Transaction object in a Jetty config file. The following example configures the Atomikos transaction manager:

<New id="tx" class="org.eclipse.jetty.plus.jndi.Transaction">
  <Arg>
    <New class="com.atomikos.icatch.jta.J2eeUserTransaction"/>
  </Arg>
</New>
Idea.png
Hint:
To use the Atomikos transaction manager, you need to download it and install it. Instructions [here] describe how to configure it for jetty6.


See also the instructions for how to configure JOTM. Contributions of instructions for other transaction managers are welcome.

Configuring Links

The name you set for your NamingEntry should be the same as the name you use for it in web.xml. For example:

In a context xml file:
 
<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
...
<New id="myds" class="org.eclipse.jetty.plus.jndi.Resource">
  <Arg><Ref id="wac"/></Arg>
  <Arg>jdbc/mydatasource</Arg>
  <Arg>
    <New class="org.apache.derby.jdbc.EmbeddedDataSource">
      <Set name="DatabaseName">test</Set>
      <Set name="createDatabase">create</Set>
    </New>
  </Arg>
</New>
</Configure>

and in web.xml:

  <resource-ref>
    <res-ref-name>jdbc/mydatasource</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    <injection-target>
      <injection-target-class>com.acme.JNDITest</injection-target-class>
      <injection-target-name>myDatasource</injection-target-name>
    </injection-target>
  </resource-ref>

You can refer to it in web.xml by a different name, and link it to the name in your org.eclipse.jetty.plus.jndi.Resource by using an org.eclipse.jetty.plus.jndi.Link type of NamingEntry. For the example above, you can refer to the jdbc/mydatasource resource as jdbc/mydatasource1 as follows:

In a context xml file:

<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
...
<New id="myds" class="org.eclipse.jetty.plus.jndi.Resource">
  <Arg><Ref id="wac"/></Arg>
  <Arg>jdbc/mydatasource</Arg>
  <Arg>
    <New class="org.apache.derby.jdbc.EmbeddedDataSource">
      <Set name="DatabaseName">test</Set>
      <Set name="createDatabase">create</Set>
    </New>
  </Arg>
</New>
</Configure>
 
 
in a jetty-env.xml file:
<source lang="xml">
  <New id="map1" class="org.eclipse.jetty.plus.jndi.Link">
    <Arg><Ref id='wac'/></Arg>
    <Arg>jdbc/mydatasource1</Arg> <!-- name in web.xml -->
    <Arg>jdbc/mydatasource</Arg>  <!-- name in container environment -->
  </New>

and in web.xml:

  <resource-ref>
    <res-ref-name>jdbc/mydatasource1</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    <injection-target>
      <injection-target-class>com.acme.JNDITest</injection-target-class>
      <injection-target-name>myDatasource</injection-target-name>
    </injection-target>
  </resource-ref>

This can be useful when you cannot change web.xml but need to link it to a resource in your deployment environment.

Global or Scoped to a webapp

As previously stated, you can control the visibility of your JNDI naming entries within your jvm, Server and WebAppContext instances. Naming entries at the _jvm scope_ are visible by any application code, and are available to be bound to java:comp/env. Naming entries at the _Server scope_ do not interfere with entries of the same name in a different Server instance, and are available to be bound to java:comp/env of any webapps deployed to that Server instance. Finally, the most specific scope are entries at the _webapp scope_. These are only available to be bound to java:comp/env of the webapp in which it is defined.

The scope is controlled by the first parameter to the NamingEntry.

The jvm scope is represented by a null parameter:

<New id="cf" class="org.eclipse.jetty.plus.jndi.Resource">
  <Arg></Arg>
  <Arg>jms/connectionFactory</Arg>
  <Arg>
    <New class="org.apache.activemq.ActiveMQConnectionFactory">
       <Arg>vm://localhost?broker.persistent=false</Arg>
    </New>
  </Arg>
</New>

The Server scope is represented by referencing the related Server object:

<Configure id="Server" class="org.eclipse.jetty.Server">
...
<New id="cf" class="org.eclipse.jetty.plus.jndi.Resource">
  <Arg><Ref id="Server"/></Arg>
  <Arg>jms/connectionFactory</Arg>
  <Arg>
    <New class="org.apache.activemq.ActiveMQConnectionFactory">
       <Arg>vm://localhost?broker.persistent=false</Arg>
    </New>
  </Arg>
</New>
</Configure>

The webapp scope is represented by referencing the related WebAppContext object:

<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
...
<New id="cf" class="org.eclipse.jetty.plus.jndi.Resource">
  <Arg><Ref id='wac'/></Arg>
  <Arg>jms/connectionFactory</Arg>
  <Arg>
    <New class="org.apache.activemq.ActiveMQConnectionFactory">
       <Arg>vm://localhost?broker.persistent=false</Arg>
    </New>
  </Arg>
</New>
</Configure>

As you can see, the most natural configuration files in which to declare naming entries of each scope are:

  • etc/jetty.xml - jvm or Server scope
  • WEB-INF/jetty-env.xml or a context xml file - webapp scope


Demo Web Application

There is a demonstration webapp which sets up examples of all of the JNDI resources discussed so far.

To run this demonstration, you need to download the transaction manager of your choice and Derby. At the time of writing, the webapp has been tested with both JOTM and with Atomikos transaction managers.

Building the Demo

The demo webapp is included with Jetty Hightide distribution. Alternatively, you can be build it from sources located in examples/test-jndi-webapp. A README.txt file there explains how to build it, and how to add support for different transaction managers.

  • Run mvn clean install to build it.
  • Edit contexts/test-jndi.xml and uncomment one of the transaction manager setups.
  • Edit contexts/test-jndi.d/WEB-INF/jetty-env.xml and uncomment one of the transaction manager setups.
  • Copy a derby.jar to the jetty lib/ directory, and also copy all the necessary Jars for the flavor of transaction manager you are using. Instructions for some popular transaction managers are on the wiki at JNDI.

Run the demo:

java -jar start.jar OPTIONS=plus

The URL for the demonstration is at:

http://localhost:8080/test-jndi

Adding Support for a Different Transaction Manager

  1. Edit the src/etc/templates/filter.properties file, and add a new set of token and replacement strings following the pattern established for ATOMIKOS and JOTM.
  2. Edit the src/etc/templates/jetty-env.xml file, and add configuration for new transaction manager following the pattern established for the other transaction managers.
  3. Edit the src/etc/templates/jetty-test-jndi.xml file, and add configuration for the new transaction manager following the pattern established for the other transaction managers.

Additional Resources

For more information on setting up a JNDI datasource, see How to Configure JNDI Datasource page.

For documentation on how to configure jetty-env.xml, consult the reference guide.