JNDI
For each specific Jakarta EE environment there is a specific plus
module that you must enable in order to use JNDI resources in your webapp:
-
For Java EE 8,
ee8-plus
-
For Java EE 9,
ee9-plus
-
For Java EE 10,
ee10-plus
If you have already enabled an annotations
module suitable for your EE environment, an appropriate plus
module will already have been enabled and you do not need to explicitly enable a plus
module.
If you have extra jars associated with your JNDI resources, eg database drivers etc, that are not located inside your webapp then you must ensure they are on either the container classpath or a Jakarta EE environment classpath.
You can enable the ext
module and place your jars in ${jetty.base}/lib/ext
to make them visible on the container classpath.
To make them visible on an EE environment classpath you should create a custom, EE environment-specific module.
You can now declare JNDI resources and reference them within your webapps.
Declaring resources
You must declare the objects you want bound so that you can then hook them into your webapp via env-entry
, resource-ref
and resource-env-refs
in web.xml
, web-fragment.xml
or override-web.xml
.
You make these declarations in Jetty XML files that are either external or internal to your webapp.
A server or context XML file is external to your webapp.
The special WEB-INF/jetty-ee{8,9,10}-env.xml
file is internal to your webapp.
It is good practice to name the file according to the environment into which your webapp is deployed. This way you can supply a file for each environment into which you deploy the webapp . If you only ever deploy to a single environment, you may omit the environment from the name, however be aware that you cannot change environments without updating the contents of the file to match.
|
See the section on Jetty XML files for more information on how to choose in which XML file to place your declarations.
Regardless of its location, the XML file contains declarations of JNDI resources that can be referenced later within your webapp.
The declarations are new instances of the following types:
org.eclipse.jetty.plus.jndi.EnvEntry
-
Used for
env-entry
type of entries org.eclipse.jetty.plus.jndi.Resource
-
Used for most other type of resources
org.eclipse.jetty.plus.jndi.Transaction
-
For a JTA manager
org.eclipse.jetty.plus.jndi.Link
-
For the link between a
web.xml
resource name and a naming entry
Declarations of each of these types follow a similar pattern:
<New class="org.eclipse.jetty.plus.jndi.xxxx"> (1)
<Arg><!-- scope --></Arg> (2)
<Arg><!-- name --></Arg> (3)
<Arg><!-- value --></Arg> (4)
</New>
1 | Defines a resource to Jetty. |
2 | Specifies the scope of the resource. |
3 | Specifies the name of the resource which will be looked up by the webapp relative to the java:comp/ or java:comp/env namespace. |
4 | Specifies the value of the resource. |
org.eclipse.jetty.plus.jndi.EnvEntry
Sometimes it is useful to pass configuration information to a webapp at runtime that you either cannot or cannot conveniently code into a web.xml
<env-entry>
.
In such cases, you can use the org.eclipse.jetty.plus.jndi.EnvEntry
class, and optionally even override an entry of the same name in web.xml
.
Here’s an example that defines the equivalent of an env-entry
called mySpecialValue
with value 4000
that overrides an <env-entry>
declaration of the same name in web.xml:
<New class="org.eclipse.jetty.plus.jndi.EnvEntry"> (1)
<Arg></Arg> (2)
<Arg>mySpecialValue</Arg> (3)
<Arg type="java.lang.Integer">4000</Arg> (4)
<Arg type="boolean">true</Arg> (5)
</New>
1 | Define an EnvEntry that corresponds to an <env-entry> . |
2 | Scoped at the JVM level. |
3 | The name of the entry, corresponding to a lookup by the webapp of java:comp/env/mySpecialValue . |
4 | The value of the entry, in this case the integer value 4000 . |
5 | true means to override the value of an <env-entry> of the same name in web.xml . |
Note that if you don’t want to override the web.xml
value, simply omit the last argument, or set it to false
.
The Servlet Specification allows binding only the following object types 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
Jetty is a little more flexible and allows you to also bind:
-
custom POJOs
Be aware that if you take advantage of this feature, your web application is not portable.
org.eclipse.jetty.plus.jndi.Resource
You can configure any type of resource that you want to refer to in web.xml
via a resource-ref
or resource-env-ref
by 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, javax.naming.Reference
or javax.naming.Referenceable
instance.
DataSources
This example configures a Derby DataSource named jdbc/myds
:
<Configure id='wac' class="org.eclipse.jetty.ee10.webapp.WebAppContext">
<New class="org.eclipse.jetty.plus.jndi.Resource">
<Arg><Ref refid="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>
This would be linked into the webapp’s JNDI namespace via an entry in a web.xml
like so:
<resource-ref>
<res-ref-name>jdbc/myds</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
When configuring Resources, ensure that the type of object you configure matches the type of object you expect to look up in Also note that the J2EE Specification recommends storing DataSources relative to |
JMS Queues, Topics and ConnectionFactories
Jetty can bind any implementation of the JMS destinations and connection factories.
Here is an example of binding an ActiveMQ in-JVM connection factory:
<Configure id='wac' class="org.eclipse.jetty.ee10.webapp.WebAppContext">
<New class="org.eclipse.jetty.plus.jndi.Resource">
<Arg><Ref refid='wac'/></Arg>
<Arg>jms/connectionFactory</Arg>
<Arg>
<New class="org.apache.activemq.ActiveMQConnectionFactory">
<Arg>vm://localhost?broker.persistent=false</Arg>
</New>
</Arg>
</New>
</Configure>
The corresponding entry in web.xml
to bind the ConnectionFactory into the webapp’s JNDI namespace would be:
<resource-ref>
<res-ref-name>jms/connectionFactory</res-ref-name>
<res-type>javax.jms.ConnectionFactory</res-type>
<res-auth>Container</res-auth>
</resource-ref>
The J2EE Specification recommends storing JMS connection factories under |
To configure access to javax.mail.Session
from within a webapp, declare an org.eclipse.jetty.plus.jndi.Resource
with an org.eclipse.jetty.ee{8,9,10}.jndi.factories.MailSessionReference
that will hold the mail configuration and create the instance of the Session
when it is referenced:
<Configure id='wac' class="org.eclipse.jetty.ee10.webapp.WebAppContext">
<New class="org.eclipse.jetty.ee10.jndi.Resource">
<Arg><Ref refid="wac"/></Arg>
<Arg>mail/Session</Arg>
<Arg>
<New class="org.eclipse.jetty.ee10.factories.MailSessionReference"> (1)
<Set name="user">fred</Set> (2)
<Set name="password">OBF:1xmk1w261z0f1w1c1xmq</Set> (3)
<Set name="properties"> (4)
<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>
1 | Use the org.eclipse.jetty.ee10.factories.MailSessionReference class to hold the configuration. |
2 | Set the username for the mail instance. |
3 | Set the password for the mail instance — use the Jetty Password tool to obfuscate the password. |
4 | Set all other applicable properties. |
The webapp performs a lookup for java:comp/env/mail/Session
at runtime and obtains a javax.mail.Session
that has the correct configuration to permit it to send email via SMTP.
Jetty does not provide the Note also that the J2EE Specification recommends storing JavaMail connection factories under |
org.eclipse.jetty.plus.jndi.Transaction
To perform distributed transactions with your resources, a transaction manager that supports the JTA interfaces is required.
The transaction manager is looked up by the application as java:comp/UserTransaction
.
Jetty does not ship with a JTA manager, but does provide the infrastructure to plug in the JTA manager of your choice.
If your JTA library’s implementation of UserTransaction
implements javax.naming.Reference
, then you should use the org.eclipse.jetty.plus.jndi.Transaction
object in a Jetty XML file to register it in JNDI:
<New id="tx" class="org.eclipse.jetty.plus.jndi.Transaction">
<Arg><Property name="environment" default="ee10"/></Arg>
<Arg>
<New class="org.example.MyUserTransactionReference" />
</Arg>
</New>
If your JTA library’s implementation of UserTransaction
does not implement javax.naming.Reference
, then you should use the Jakarta EE specific Jetty class to register it in JNDI:
<New id="tx" class="org.eclipse.jetty.ee10.plus.jndi.Transaction">
<Arg><Property name="environment" default="ee10"/></Arg>
<Arg>
<New class="org.example.MyUserTransaction" />
</Arg>
</New>
Jetty will automatically bind this JTA manager to the webapp’s JNDI namespace at java:comp/UserTransaction
.
org.eclipse.jetty.plus.jndi.Link
Usually, the name you provide for the org.eclipse.jetty.plus.jndi.Resource
is the same name you reference in web.xml
.
This ensures that the two are linked together and thus accessible to your webapp.
However, if the names cannot be the same, then it is possible to effectively alias one to another using an org.eclipse.jetty.plus.jndi.Link
.
Supposing you have a declaration for a Datasource named jdbc/workforce
in a Jetty context XML file, but your web.xml wants to link to a <resource-ref>
named jdbc/employees
, and you cannot edit the web.xml.
You can create a WEB-INF/jetty-ee{8,9,10}-env.xml
file with an org.eclipse.jetty.plus.jndi.Link
that ties together the names jdbc/workforce
and jdbc/employees
:
The context XML file declares jdbc/workforce
:
<Configure id='wac' class="org.eclipse.jetty.ee10.webapp.WebAppContext">
<New class="org.eclipse.jetty.plus.jndi.Resource">
<Arg><Ref refid="wac"/></Arg>
<Arg>jdbc/workforce</Arg>
<Arg>
<New class="org.apache.derby.jdbc.EmbeddedDataSource">
<Set name="DatabaseName">test</Set>
<Set name="createDatabase">create</Set>
</New>
</Arg>
</New>
</Configure>
The web.xml
refers to it as jdbc/employees
:
<resource-ref>
<res-ref-name>jdbc/employees</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Create a WEB-INF/jetty-ee{8,9,10}-env.xml
file with a org.eclipse.jetty.plus.jndi.Link
to link these names together:
<New class="org.eclipse.jetty.plus.jndi.Link">
<Arg><Ref refid='wac'/></Arg>
<Arg>jdbc/employees</Arg> (1)
<Arg>jdbc/workforce</Arg> (2)
</New>
1 | The name as referenced in the web.xml file. |
2 | The name as referenced in the context XML file. |
Jetty XML files
You can define naming resources in three places:
- Server XML file
-
Naming resources defined in a server XML file are scoped at the JVM,
org.eclipse.jetty.server.Server
or environment level. Note that the classes for the resource must be visible at the point in time that the XML executes. For example, environment level resources should be declared in an XML file that is referenced by a custom module that contains an[environment]
clause at the matching environment level to ensure the classpath for that environment is available. - Context XML file
-
Entries in a context XML file should be scoped at the level of the webapp to which they apply (it is possible to use a less strict scoping level of Server or JVM, but not recommended). As a context XML file executes before the webapp’s classes are available, the classes for your resource must be external to the webapp and on either the container or environment classpath.
- WEB-INF/jetty-ee{8,9,10}-env.xml
-
Naming resources in a
WEB-INF/jetty-ee{8,9,10}-env.xml
file are scoped to the webapp in which the file resides. The resources defined here may use classes from inside your webapp.
Resource scoping
Naming resources within Jetty belong to different scopes, in increasing order of restrictiveness:
JVM scope:
The name is unique across the JVM instance, and is visible to all application code.
This scope is represented by a null
first parameter to the resource declaration.
For example:
<New id="cf" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg></Arg> (1)
<Arg>jms/connectionFactory</Arg>
<Arg>
<New class="org.apache.activemq.ActiveMQConnectionFactory">
<Arg>vm://localhost?broker.persistent=false</Arg>
</New>
</Arg>
</New>
1 | Empty first arg equates to JVM scope for the object bound to name jms/connectionFactory . |
Environment scope: The name is unique within a Jetty environment. It is represented by referencing the name of the Jakarta EE environment as the first parameter to the resource declaration. For example:
<New id="cf" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg>ee10</Arg> (1)
<Arg>jms/connectionFactory</Arg>
<Arg>
<New class="org.apache.activemq.ActiveMQConnectionFactory">
<Arg>vm://localhost?broker.persistent=false</Arg>
</New>
</Arg>
</New>
Webapp scope:
The name is unique to the org.eclipse.jetty.ee{8,9,10}.webapp.WebAppContext
instance, and is only visible to that application.
This scope is represented by referencing the instance as the first parameter to the resource declaration.
For example:
<New class="org.eclipse.jetty.plus.jndi.Resource">
<Arg><Ref refid='wac'/></Arg> (1)
<Arg>jms/connectionFactory</Arg>
<Arg>
<New class="org.apache.activemq.ActiveMQConnectionFactory">
<Arg>vm://localhost?broker.persistent=false</Arg>
</New>
</Arg>
</New>