Using JNDI Resources with Jetty
java:comp/env lookups in webapps. This is an optional feature, and as such some setup needs to be done. We'll show you how to do it, although we have provided jetty configuration files that already have JNDI enabled to help you get going faster. More on that later.
Firstly, to enable JNDI for a web application, you need to configure the WebAppContext to parse the web.xml file and perform the
java:comp/env linkages. The class that does this is
org.mortbay.jetty.plus.webapp.Configuration, and we specify its name in the list of configurations to be applied to the webapp when we define the
org.mortbay.jetty.webapp.WebAppContext for it. The following example enables naming services for the
Or, more conveniently, you can specify that these configurations are applied to all webapps deployed by the WebAppDeployer :
You may now configure naming resources that can be referenced in a web.xml file and accessed from within the
java:comp/env naming environment of the webapp during execution. Specifically, you may configure support for the following web.xml elements:
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
Furthermore, it is possible to 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:
- jvm scope - the name is unique within the jvm
- server scope - the name is unique to the Server 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.
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
There are 3 types of objects that can be bound into Jetty's JNDI:
- an ordinary POJO instance
- a java.naming.Reference instance
- an object instance that implements the java.naming.Referenceable interface
The binding for all of these object types generally follows the same pattern:
type of naming entry can be:
"org.mortbay.naming.plus.Resource"for all other type of resources
"org.mortbay.plus.naming.Transaction"for a JTA manager. We'll take a closer look at this in the Configuring XA Transactions section).
There are 3 places in which you can define naming entries:
- context xml file
Naming entries defined in a jetty.xml file will generally be scoped at either the jvm level or the Server level. Naming entries in a jetty-env.xml 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.
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
<env-entry>. In this case, you can use
org.mortbay.jetty.plus.naming.EnvEntry and even configure them to override an entry of the same name in web.xml.
This example will define a virtual
mySpecialValue with value
4000 that is unique within the whole jvm. It will be put into JNDI at
java:comp/env/mySpecialValue. 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
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
However, Jetty is a little more flexible and will also allow you to bind custom POJOs, javax.naming.References and javax.naming.Referenceables. Be aware 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:
Configuring resource-refs and resource-env-refs
Any type of resource that you want to refer to in a web.xml file as a
<resource-env-ref> can be configured using the
org.mortbay.naming.plus.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 are 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:
Name in jetty.xml
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 Derby relational database, but you can use any implementation of a
javax.sql.DataSource. In this example, we'll configure it as scoped to a webapp with the id of 'wac':
The above would create an instance of
org.apache.derby.jdbc.EmbeddedDataSource, call the two setter methods
setCreateDatabase("create"); 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
To lookup your DataSource in your servlet/filter/etc do:
Configuring JMS Queues, Topics and ConnectionFactory-s
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 ActiveMQ in-JVM connection factory:
Jetty also provides infrastructure for providing access to javax.mail.Sessions from within an application:
The setup above creates an instance of the
org.mortbay.naming.factories.MailSessionReference class, calls it's setter methods
setPassword("OBF:1xmk1w261z0f1w1c1xmq"); 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
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.
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
java:comp/UserTransaction 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
org.mortbay.jetty.plus.naming.Transaction object in a jetty config file. In the following example, we will configure the Atomikos transaction manager:
See also the instructions for how to configure JOTM. Contributions of instructions for other transaction managers are welcome.
Global or scoped to a webapp
If you place any of the naming resources discussed in the next sections in a jetty configuration file, they will be used by all webapps to resolve
You can instead make naming resources that are only resolvable by a particular webapp. For instance, you might want to do this if one of the objects you want to bind can only be loaded from the webapp's classloader.
Here's how to do it. Create a
WEB-INF/jetty-env.xml file in your webapp. An example might look like:
That's all you need to do. Jetty will automatically check for a file of this name and add any naming resources in the appropriate scope for resolution of
web.xml references. You may define any naming resources in this file, but it would usually be undesirable to define a
Transaction, because this is intended to be a container-level resource.
Demo Web Application
There is a demonstration webapp which sets up examples of all of the JNDI resources we've discussed so far.
In order to run this demonstration, you will 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
As the demo webapp is not pre-built with the distribution, you first have to build it. It is located in
examples/test-jndi-webapp. There is a
README.txt file in there which explains how to build it, and how to add support for different transaction managers.
- run "mvn clean install" to build it
- then edit contexts/test-jndi.xml and uncomment one of the transaction manager setups
- then 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, 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
You run the demo like so:
The URL for the demonstration is at:
Adding Support for a Different Transaction Manager
- 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.
- 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.
- 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.