Add jndi docs to operations guide.

Signed-off-by: Jan Bartel <janb@webtide.com>
This commit is contained in:
Jan Bartel 2020-10-13 18:27:04 +02:00
parent e99f5835e9
commit 95998a2ee3
5 changed files with 401 additions and 47 deletions

View File

@ -22,7 +22,6 @@
Jetty supports `java:comp/env` lookups in webapps.
This is an optional feature for which some configuration is required.
include::quick-jndi-setup.adoc[]
include::using-jndi.adoc[]
include::jndi-configuration.adoc[]
include::jndi-embedded.adoc[]

View File

@ -1,45 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// forth in the Eclipse Public License, v. 2.0 are satisfied:
// the Apache License v2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
[[jndi-quick-setup]]
=== Quick Setup
If you are using the standard distribution of Jetty, you must enable the _JNDI_ link:#startup-modules[module] to obtain Jetty's JNDI implementation, and the *plus* link:#startup-modules[module] which provides classes for interacting with JNDI.
As the _plus_ module depends on the _JNDI_ module, you only need to enable the _plus_ module to enable both.
Assuming you have Jetty installed in `/opt/jetty`, and you have made a link:#startup-base-and-home[jetty base] in `/opt/jetty/my-base`, do:
[source,screen,subs="{sub-order}"]
....
$ cd /opt/jetty
$ cd my-base
$ java -jar $JETTY_HOME/start.jar --add-to-start=plus
....
You can now start Jetty and use JNDI within your webapps.
See link:#using-jndi[Using JNDI] for information on how to add entries to the JNDI environment that Jetty can look up within webapps.
If you have extra jars associated with your JNDI resources, for example a database driver jar, and you haven't made a custom link:#startup-modules[module] for it, you can put the jars into your `{$jetty base}ext/` directory.
You will then need to enable the _ext_ module to ensure the jars in the `ext/` directory are on the classpath.
Assuming you have Jetty installed in `/opt/jetty`, and you have made a link:#startup-base-and-home[jetty base] in `/opt/jetty/my-base`, do:
[source,screen,subs="{sub-order}"]
....
$ cd /opt/jetty
$ cd my-base
$ java -jar $JETTY_HOME/start.jar --add-to-start=ext
....

View File

@ -36,3 +36,4 @@ include::sessions/chapter.adoc[]
include::quickstart/chapter.adoc[]
include::annotations/chapter.adoc[]
include::jsp/chapter.adoc[]
include::jndi/chapter.adoc[]

View File

@ -34,6 +34,7 @@ If you know Eclipse Jetty already, jump to a feature:
* xref:og-quickstart[Faster Web Application Deployment]
* xref:og-annotations[Annotations]
* xref:og-jsp[JSP]
* xref:og-jndi[JNDI]
TODO

View File

@ -0,0 +1,398 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// forth in the Eclipse Public License, v. 2.0 are satisfied:
// the Apache License v2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
[[og-jndi]]
=== JNDI
Enable the `plus` module in order to be able to use JNDI resources in your webapp.
If you already have the `annotations` module enabled, then it will already be enabled.
If you have extra jars associated with your JNDI resources, eg database drivers etc, that are not located inside your webapp then you should place those jars into your `$jetty.base/lib/ext` directory.
If your base doesn't already contain this directory, then enable the `ext` module, and Jetty will create the directory for you and ensure its contents are on the server's classpath.
You can now declare JNDI resources and reference them within your webapps.
==== Declaring resources
You must declare the objects you want bound into the environment 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-env.xml` file is internal to your webapp.
See the section on link:#og-jndi-xml[Jetty XML files] for more information on how to choose in which XML file to place your declarations.
For now, let's look at _what_ you declare in the XML file, regardless of its location.
Declaring a JDNI resource to be referenced later in your webapp is accomplished by declaring new instances of the following types:
link:#og-jndi-env[`org.eclipse.jetty.plus.jndi.EnvEntry`]::
Used for `env-entry` type of entries
link:#og-jndi-resource[`org.eclipse.jetty.plus.jndi.Resource`]::
Used for most other type of resources
link:#og-jndi-tx[`org.eclipse.jetty.plus.jndi.Transaction`]::
For a JTA manager
link:#og-jndi-link[`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:
[source,xml,subs=verbatim]
----
<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 link:#og-jndi-scope[scope] of the resource.
<3> Specifies the name of the resource which will be looked up by the webapp relative to the `java:comp/env` namespace.
<4> Specifies the value of the resource.
[[og-jndi-env]]
===== 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:
[source,xml,subs=verbatim]
----
<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> link:#og-jndi-scope[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
* http://docs.oracle.com/javase/1.5.0/docs/api/javax/naming/Reference.html[`javax.naming.References`]
* http://docs.oracle.com/javase/1.5.0/docs/api/javax/naming/Referenceable.html[`javax.naming.Referenceables`]
Be aware that if you take advantage of this feature, your web application is __not portable__.
[[og-jndi-resource]]
===== 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.
Let's examine how to configure some of the most common types of resources.
====== DataSources
In this example, we'll configure a http://db.apache.org/derby[Derby] DataSource named `jdbc/myds`:
[source,xml,subs=verbatim]
----
<Configure id='wac' class="org.eclipse.jetty.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 linked into the webapps JNDI namespace via an entry in a `web.xml` like so:
[source,xml,subs=verbatim]
----
<resource-ref>
<res-ref-name>jdbc/myds</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
----
[NOTE]
====
When configuring Resources, 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.
Also note that the http://jcp.org/aboutJava/communityprocess/pr/jsr244/index.html[J2EE Specification] recommends storing DataSources relative to `jdbc/` and thus looked up by the application as `java:comp/env/jdbc/xxx`.
Eg The Datasource bound in Jetty as `jdbc/users` would be looked up by the application as `java:comp/env/jdbc/users`
====
//TODO For more examples of datasource configurations, see xref:jndi-datasource-examples[].
====== JMS Queues, Topics and ConnectionFactories
Jetty can bind any implementation of the JMS destinations and connection factories.
Here is an example of binding an http://activemq.apache.org[ActiveMQ] in-JVM connection factory:
[source,xml,subs=verbatim]
----
<Configure id='wac' class="org.eclipse.jetty.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:
[source,xml,subs=verbatim]
----
<resource-ref>
<res-ref-name>jms/connectionFactory</res-ref-name>
<res-type>javax.jms.ConnectionFactory</res-type>
<res-auth>Container</res-auth>
</resource-ref>
----
[NOTE]
====
The http://jcp.org/aboutJava/communityprocess/pr/jsr244/index.html[J2EE Specification] recommends storing JMS connection factories under `jms/`.
Eg The ConnectionFactory bound in Jetty as `jms/inqueue` would be looked up by the application as `java:comp/env/jms/inqueue`.
====
====== Mail
To configure access to `javax.mail.Session` from within a webapp, declare an `org.eclipse.jetty.plus.jndi.Resource` with an `org.eclipse.jetty.jndi.factories.MailSessionReference` that will hold the mail configuration and create the instance of the `Session` when it is referenced:
[source,xml,subs=verbatim]
----
<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
<New class="org.eclipse.jetty.plus.jndi.Resource">
<Arg><Ref refid="wac"/></Arg>
<Arg>mail/Session</Arg>
<Arg>
<New class="org.eclipse.jetty.jndi.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.jndi.factories.MailSessionReference` class to hold the configuration.
<2> Set the username for the mail instance.
<3> Set the password for the mail instance - use Jetty's secure password obfuscation to obscure 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.
[NOTE]
====
Jetty does not provide the `javax.mail` and `javax.activation` jars.
Note also that the http://jcp.org/aboutJava/communityprocess/pr/jsr244/index.html[J2EE Specification] recommends storing JavaMail connection factories under `mail/`.
Eg The `MailSessionReference` bound to jetty as `mail/smtp` would be looked up by the application as `java:comp/env/mail/smtp`.
====
[[og-jndi-tx]]
===== 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.
Use the link:{JDURL}/org/eclipse/jetty/plus/jndi/Transaction.html[org.eclipse.jetty.plus.jndi.Transaction] object in a link:#og-jndi-xml[Jetty XML file] to configure the JTA manager.
The following example configures the http://www.atomikos.com/[Atomikos] transaction manager:
[source,xml,subs=verbatim]
----
<New id="tx" class="org.eclipse.jetty.plus.jndi.Transaction">
<Arg>
<New class="com.atomikos.icatch.jta.J2eeUserTransaction"/>
</Arg>
</New>
----
Jetty will automatically bind this JTA manager to the webapp's JNDI namespace at `java:comp/UserTransaction`.
[[og-jndi-link]]
===== 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`.
Let's look at an example.
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-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`:
[source,xml,subs=verbatim]
----
<Configure id='wac' class="org.eclipse.jetty.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`:
[source,xml,subs=verbatim]
----
<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-env.xml` file with a `org.eclipse.jetty.plus.jndi.Link` to link these names together:
[source,xml,subs=verbatim]
----
<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.
[[og-jndi-xml]]
===== Jetty XML files
You can define naming resources in three places:
Server XML file::
Naming resources defined in a server XML file are link:#og-jndi-scope[scoped] at either the JVM level or the `org.eclipse.jetty.server.Server` level.
The classes for the resource _must_ be visible at the Jetty *container* level.
If instead the classes for the resource only exist inside your webapp, you must declare it in a `WEB-INF/jetty-env.xml` file.
WEB-INF/jetty-env.xml::
Naming resources in a `WEB-INF/jetty-env.xml` file are link:#og-jndi-scope[scoped] to the webapp in which the file resides.
While you can enter JVM or Server scopes if you choose, we do not recommend doing so.
The resources defined here may use classes from inside your webapp.
This is a Jetty-specific mechanism.
Context XML file::
Entries in a context XML file should be link:#og-jndi-scope[scoped] at the level of the webapp to which they apply (although it is possible to use a less strict scoping level of Server or JVM, but not recommended).
As with resources declared in a server XML file, classes associated with the resource _must_ be visible on the *container's* classpath.
[[og-jndi-scope]]
===== Resource scoping
Naming resources within Jetty belong to one of three 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:
[source,xml,subs=verbatim]
----
<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`.
*Server scope:*
The name is unique to a Server instance, and is only visible to applications associated with that instance.
This scope is represented by referencing the Server instance as the first parameter to the resource declaration.
For example:
[source,xml,subs=verbatim]
----
<New id="cf" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg><Ref refid="Server"/></Arg> <1>
<Arg>jms/connectionFactory</Arg>
<Arg>
<New class="org.apache.activemq.ActiveMQConnectionFactory">
<Arg>vm://localhost?broker.persistent=false</Arg>
</New>
</Arg>
</New>
----
<1> We refer to the id `Server` which identifies the default `org.eclipse.jetty.server.Server` instance.
*Webapp scope:*
The name is unique to the `org.eclipse.jetty.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:
[source,xml,subs=verbatim]
----
<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>
----
<1> We refer to an instance of an `org.eclipse.jetty.webapp.WebAppContext` which has been previously defined.