![]() Version: 9.3.11.M0 |
private support for your internal/customer projects ... custom extensions and distributions ... versioned snapshots for indefinite support ... scalability guidance for your apps and Ajax/Comet projects ... development services for sponsored feature development
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 org.eclipse.jetty.plus.jndi.EnvEntry
, and even 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 scoped to the JVM. It is put
into JNDI at ` java:comp/env/mySpecialValue` for every web app
deployed. Moreover, the boolean argument indicates that this value
overrides an env-entry
of the same name in web.xml
. If you don’t
want to override, omit this argument, or set it to false
.
The Servlet Specification allows binding only the following object types
to an env-entry
:
That being said, Jetty is a little more flexible and allows you to also
bind custom POJOs,
javax.naming.References
and
javax.naming.Referenceables
.
Be aware that if you take advantage of this feature, your web
application is not portable.
To use the env-entry
configured above, use code in your
servlet/filter/etc.
, such as:
import javax.naming.InitialContext;
public class MyClass {
public void myMethod() {
InitialContext ic = new InitialContext();
Integer mySpecialValue = (Integer)ic.lookup("java:comp/env/mySpecialValue");
...
}
}
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 storing DataSources 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:
Table 11.1. DataSource Declaration Conventions
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 |
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 web
app 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 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>
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 web app. If you do not have the
appropriate resource-ref
set up in your web.xml
, it is available
from application lookups as `
java:comp/env/jdbc/myds`.
Here’s an example web.xml
declaration for the datasource above:
<resource-ref>
<res-ref-name>jdbc/myds</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
To look up your DataSource in your servlet/filter/etc.
:
import javax.naming.InitialContext;
import javax.sql.DataSource;
public class MyClass {
public void myMethod() {
InitialContext ic = new InitialContext();
DataSource myDS = (DataSource)ic.lookup("java:comp/env/jdbc/myds");
...
}
}
Note
Careful! 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 thejavax.sql.DataSource
interface.
For more examples of datasource configurations, see Datasource Examples.
Jetty can 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 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 entry in web.xml
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>
TODO: put in an example of a QUEUE from progress demo
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 refid="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>
This setup creates an instance of the `
org.eclipse.jetty.jndi.factories.MailSessionReference` class, calls
its setter methods 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 look up ` 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 Secure Password Obfuscation (OBF:) mechanism to make the config file a little more secure from prying eyes. Remember that you cannot use the other Jetty encryption mechanisms of MD5 and Crypt because they do not allow you to recover the original password, which the mail system requires.
If you want to perform distributed transactions with your resources, you
need a transaction manager that supports the JTA interfaces, and that
you can look up as java:comp/UserTransaction
in your webapp. Jetty
does not ship with one as standard, but you can plug in the one you
prefer. You can configure a transaction manager using the
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>
Generally, the name you set for your Resource
should be the same 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 refid="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 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>
However, 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
. For the example above, you can refer
to the jdbc/mydatasource
resource as `
jdbc/mydatasource1` as follows:
In a context xml file declare jdbc/mydatasource
:
<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
<New id="myds" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg><Ref refid="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>
Then in a WEB-INF/jetty-env.xml
file, link the name
jdbc/mydatasource
to the name you want to reference it as in
web.xml
, which in this case is jdbc/mydatasource1
:
<New id="map1" class="org.eclipse.jetty.plus.jndi.Link">
<Arg><Ref refid='wac'/></Arg>
<Arg>jdbc/mydatasource1</Arg> <!-- name in web.xml -->
<Arg>jdbc/mydatasource</Arg> <!-- name in container environment -->
</New>
Now you can refer to jdbc/mydatasource1
in the web.xml
like this:
<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 a JNDI resource directly in
the web.xml
but need to link it to a specific resource in your
deployment environment.