J[ava] S[erver] P[ages]
Anything Jetty/JBoss specific.
I'm not going to waste bandwidth talking all about standard J2EE
- there are 1001 books and websites where you can find this.
I will touch on proprietary Jetty features, but usually with a
link back to the Jetty website where there is a wealth of
I will also touch on proprietary JBoss features, but once again,
the JBoss Project would be a better place to look
for this sort of documentation.
Now that we have narrowed it down a bit - let's begin....
A pure Java, HTTP1.1 httpd, Servlet 2.3 & JSP 1.2
WebContainer. In short a 100% pure Java and elegant solution to
serving static and dynamic web content. See jetty.mortbay.org
for more information.
A very thin bridging layer - JBossWeb is the JBoss Web Service -
currently implemented using a tailored Jetty instance.
Tomcat and Jetty's missions are very different. Tomcat's is to
define the standard behaviour of a J2EE-compliant
web-container. Jetty's is to deliver this behaviour in as fast,
lightweight, and embeddable solution as possible.
I happen to think that Jetty's mission fits better with JBoss'
requirements. The Jetty developer community see it as a priority
to integrate as tightly and as usefully as possible with JBoss,
whilst continuing to provide standalone Jetty to a wider
audience with similar requirements for an embedded Java HTTP
server and Web-Container. Tomcat's priorities probably lie
Take your pick....
Provided that you have not used any proprietary features, you
should experience no difference. The two provide implementations
of the same APIs and both are tested against jakarta-watchdog, a
suite of hundreds of test cases, to ensure compliance. If, by
mischance, you do happen to come across a difference in behaviour
between the two, mail
email@example.com with a clear and specific
explanation of this difference and the Jetty development team will
do their best to resolve it.
If you have taken advantage of Tomcat proprietary features, you
should browse through the Jetty doc. You will find that most of
them can be reproduced via proprietary configuration of Jetty. If
you find an important one that con't - please tell us.
Just start JBoss3. Jetty should deploy from the jbossweb.sar. The
HTTP server will be on 8080 by default. Try hitting
http://localhost:8080/. This and other proprietary features are
configurable in META-INF/jboss-service.xml which you will find in
...deploy/jbossweb.sar. Edit it, save it. JBoss will notice,
reload and restart Jetty with it's new configuration.
Alternatively, for more ephemeral alterations you can use the JMX
Jetty has a long history and was around well before Servlet 2.2?
when we finally got a standard deployment descriptor
(web.xml). Therefore it has a proprietary configuration format
(held in etc/jetty.xml in standalone Jetty and
Whilst this mechanism can be used to actually deploy webapps,
doing so will FORFEIT all advantages of the Jetty/JBoss
integration, since it bypasses them. These include support for
ENC JNDI bindings, optimised web-ejb calls, JBoss aware JSP
classpath amd much, much more. Only use this mechanism to deploy
webapps if you fully understand what you are doing.
So, deploy your webapps through the standard J2EE/JBoss
mechanisms, by putting them in a war or ear and dropping them
into your deploy dir etc...
In order to configure proprietary aspects of Jetty not covered
by the servlet or jsp specs, feel free to dip into the configuration
mechanism. You will need the Jetty javadoc
to hand, and a little patience to start with, since the xml is
simply a veneer directly over Jetty's java API, which just
introspects and calls methods on the underlying objects as it is
parsed. You WILL grow to love this, as short of an embedded
language (which this actually amounts to) you will find no more
powerful way to configure your server.
The jbossweb.sar also contains a webdefault.xml. This is written
in terms of a standard J2EE web.xml and is applied to every
webapp before it's own web.xml. It contains default settings for
e.g. the invoker servlet and the JSP engine.
Aswell as the standard WEB-INF/web.xml Jetty will read a
WEB-INF/jetty-web.xml (or web-jetty.xml). This is written in
Jetty's proprietary configuration format and will be applied
directly to your webapp's Context before it is started. This
allows you very fine-grained control over such things as
Because it is a useful way of encapsulating all the components
that form the Jetty service.
If you really don't like it, move all the jars inside into ./lib
and the jboss-service.xml to e.g. ./deploy/jbossweb-service.xml
Rather than wait for a new JBoss release, you can probably just
pull down the new Jetty release and substitute the jars you
currently have in .../deploy/jbossweb.sar with the ones in the new
release. Pay attention to any notes about API changes as these may
affect either the integration code (in which case you will have to
wait for me to update JBoss cvs) or the Jetty/JBoss configuration
(in which case, if you are feeling brave, you should be able to
fix your own configuration). Now you are living on the edge !
N.B. Standalone Jetty's MANIFEST.MF points to various jars in
it's distrib. These are all already available to the JBoss
classloader and the hint from MANIFEST.MF will generate a
warning that can be safely ignored, since the jars will not be
in the expected place. If you don't like the warnings, simply
edit the MANIFEST.MF to remove the dependencies.
Copy it to server/<configuration>/deploy where
<configuration> is your configuration (probably "default" if
you don't know what I am talking about). JBoss will see it and
deploy it to Jetty automagically.
You can also deploy it unpacked i.e. make a directory called
e.g. my.war/, go into it and unjar your webapp then symlink/copy
the whole directory into deploy/ as above. It should be treated
in exctly the same way as above.
If you update/touch the packed WAR or the unpacked
<WAR>/WEB-INF/web.xml Jetty/JBoss will undeploy the old
copy of your webapp and load the new one.
This is all standard JBoss stuff and will work for anything that
JBoss knows how to deploy.
If you are deploying the war by itself (no ear) you can simply
name it <context-root>.war (where <context-root> is
the context-root that you require) and deploy it. This is
problematic if you want to use the '/' context-root - see the next
item on remaining ways to specify context-root.
When I deploy my app foo.war to JBoss, it gets installed at
/foo. I want it at /.
You have two choices.
1. The standard J2EE way - wrap your .war in an .ear and in the
.ear's application.xml you can specify the required
<context-root> - Here is the DTD:.application_1_3.dtd
2. The proprietary JBoss extension - put a jboss-web.xml into
your .war's WEB-INF directory and specify the
<context-root> in that. - Here is the DTD: jboss-web_3_0.dtd
N.B. Standalone Jetty supports a Tomcat-ism. Call the file
ROOT.war and deploy this standalone - i.e. without a surrounding
ear. (This is CASE-SENSITIVE - careful on Windoze). HOWEVER THIS
WILL NOT WORK WITH JBOSS/JETTY. The integration code bypasses
this Jetty code and (currently) makes no attempt to replace
it. (CHECK THIS).
Note that a context path specification in a
META-INF/application.xml file will take precedence over the
We expect to support this feature very soon - watch this space.
There are two main standard ways that a browser/servlet-container
cooperate to maintain session attachment. Url-rewriting and
To force Jetty not to use a Cookie for this purpose, there is a
setUsingCookies method that needs to be called on the
WebApplicationHandler object. This can be called from the XML in
a WEB-INF/jetty-web.xml file:
<?xml version="1.0" encoding="ISO-8859-1"?>
An HttpSession is an object used in a WebApp to isolate and
maintain conversational state between requests.
A WebApp may be described as 'distributable' in it's
The J2EE spec requires that a 'distributable' webapp's sessions
may be 'migrated' between nodes of a cluster - i.e. dynamically
moved from one webapp instance to another running in a different
Many AppServers extend this fn-ality from simply allowing
explicit migration to providing failover i.e. If one node
undergoes a catastrophic failure it's sessions will still be
available to other instances of the same WebApp within the
cluster. Thus these conversations may be reprised by other nodes
with the relevant client.
Currently JavaGroups is the favoured medium for Jetty
Ensure that your network allows JavaGroups to multicast as
required - see docs on the JavaGroups site. (HINT - JBoss clustering also
uses JavaGroups, so if this is working, you are OK).
Ensure that you are running the 'all' JBoss configuration
(run.sh -c all) as 'default' and 'minimal' do not ship with the
Uncomment the JGStore section (a) in your
Ensure that you have a <distributable/> tag in the right
place in your webapp's WEB-INF/web.xml. Check the DTD.
Support for distributable functionality is a [deliberately]
poorly spec-ed area and as such supported by different vendors
in different ways. There will shortly be comprehensive, for-pay
documentation about Mort Bay's implementation for Jetty
available from this site. Watch this space.
You may need to unpack the plugin.sar to get at the
jboss-service.xml. You do not need to repack it, if you think you will
be reediting it - just make a directory called deploy/jbossweb.sar
and unjar the contents of the sar into it - JBoss will understand it
in just the same way as the packed sar.
(the jbossweb.sar/jetty-plugin.sar was shipped jarred in early 3.0.x
Virtual hosts are an area currently not (AFAIK) addressed by the
J2EE spec (1.3). However this is supported as of JBoss2.4.5 via a
proprietary extension mechanism.
To define a virtual host, add a line of the following form to
your webapp's WEB-INF/jboss-web.xml file. Here is the DTD: jboss-web_3_0.dtd
Note that you will also need your system configured appropriately
to map this name to your machines IP address.
Unfortunately the proprietary JBoss descriptor
(WEB-INF/jboss-web.xml) does not yet support this.
Fortunately the proprietary Jetty descriptor
(WEB-INF/jetty-web.xml) does - since it is just a thin XML
veneer over the Java classes API.
Try a WEB-INF/jetty-web.xml something like this :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure 1.2//EN" "http://jetty.mortbay.org/configure_1_2.dtd">
Initial integration of JBoss JSR77 support and Jetty internals has
been checked into the 3.2 and 4.0 branches. Access to the JSR77
MBeans should be possible from the jmx-console or web-console.
The integration creates an MBean for each servlet. If you are
deploying large numbers of servlets over and over again, in e.g. a
development iteration, this can be time-consuming. To disable this
feature, set the SupportJSR77 attribute in your
jbossweb.sar/META-INF/jboss-service.xml to false.
Jetty, being a good java citizen, respects the 'java.io.tmpdir'
property (defaults to /tmp on Unix). Try setting this as you start
up JBoss (see the following item) to your required directory
start jboss something like this :
If you are on Windoze, figure out how to pass the above
properties into your JVM....
ConfigurationElement to reflect your needs.
Have a look here
Have a look here
The latest version of the AJP Connector will receive it's
jvmRoute attribute from mod_jk (if you are doing sticky
load-balancing). It should no longer be set manually via your
The Java language spec says a ClassLoader should always check it's
parent for a class it is asked for (delegate up). The servlet spec
implies that it should try to find the class locally (i.e. in the
.war file) first.
These different requirements cannot be reconciled and lead to
Jetty allows you to choose the strategy you require via this
Look in the jbossweb.sar/META-INF/jboss-service.xml file for an
example of how to configure an SSL listener for Jetty. You will
also find some useful tips in the Jetty
FAQ and Jetty SSL demo
If you require JAAS authentication,
The name of the request attribute in which you expect to find the
JAAS active subject may be configured at the server level for the
JettyService by editing the SubjectAttributeName attribute in
jboss-service.xml (see above), or via the jmx-console or
web-console. The attribute's value defaults to j_subject.
Initial SSO support has just gone into Jetty-4.2.10pre0 and will
shortly be rolled into a JBoss release. Drill down here.
JBoss comes with no root webapp preinstalled, so starting it up
and hitting localhost:8080/ may result in your receiving a "404
Not Found" error, although more recent versions of Jetty
(4.2.4rc0+) now trap this and return a more useful page. This is
NOT a problem with your installation. It IS correct behaviour. If
you want to see something there, deploy something.
You probably have a process periodically sweeping old files out of
e.g /tmp. See the item above.
Here is a MacOSX-specific solution:
Q: JBoss3/Jetty on Mac OS X stops serving JSPs and displays an
directory listing instead of my site. What's going on?
A: On Mac OS X, a file called "/etc/periodic/daily/500.daily"
describes how often /tmp files are to be cleaned up. By default,
it wipes files after three days.
If you do not specify a temporary directory explicitly for
Jetty/JBoss with the startup parameter "java.io.tmpdir" for
Jetty to unpack to, it will default to the temp directory for
the system. On Mac OS X, this is "/tmp".
Modify your JBoss startup script "run.sh" to include a
"java.io.tmpdir" system property:
JAVA_OPTS="$JAVA_OPTS -Dprogram.name=$PROGNAME -Djava.io.tmpdir=$JBOSS_HOME/server/default/tmp"
(or wherever you want that is not being wiped clean regularly.)
... but my webapp deploys on ANOther webcontainer. What is going on ?
The XML parser is being strict about the ordering of elements (as per spec).
Look at web-app_2_3.dtd and ensure that the elements in
your web.xml appear in exactly the same order.
You are now assured of MAXIMUM portability for your webapp.
Or, set the system property : org.mortbay.xml.XmlParser.NotValidating to "true".
This is because JBoss started to read and deploy the file before
the copy had finished. For 100% safe deployment, copy your file to
a temporary space on the same filesystem as the deploy dir, then
move/rename it into the deploy dir. This will be an atomic
operation for your filesystem, so JBoss will see the whole file
appear in one go, not a file gradually increasing in
size. Alternatively, you can use the JMX interface to pass the url
of the app that you want deployed - see JBoss doc.
Your webapp is described as distributable in it's WEB-INF/web.xml -
you should be sure that this is intended as distributing HttpSessions
adds considerable overhead to their use...
You have NOT uncommented the JGStore block in
Why is this commented out ?
...because it requires JavaGroups, which is only available in the
'all' server configuration.
So you will need to either 'run.sh -c all' or copy the JavaGroups jar
into whichever configuration you are using.
Look at JettyWithJikes. Then read the comments in and
(the examples in this item are for Jasper1 - pre JBoss-3.2. I have not
yet tried precompilation with Jasper2).
If you include a .jsp in your .war and hit it, Jasper (the JSP engine)
will find the JSP, transform it into a .java, compile that into a
.class, load and run it, returning the output. The .class file is then
cached and reused on subsequent hits.
This can lead to at least 4 problems.
1). You might prefer to be notified of compile errors during
your development cycle - rather than post deployment.
2). The first person to hit the page will have to wait a while
whilst this process is carried out.
3). If you are deploying into a heavily loaded site, it is
possible that a page may be hit again before the first hit has
finished it's on-the-fly preparation. This may result in more
than one concurrent attempt at compiling the page, resulting in
unecessary load on the server and more than one user waiting a
long time for the resource that they have requested.
4). The more jars JBoss contains/has-deployed, the longer each
JSP compilation may take, since to be sure that the JSP is
seeing the classes that it expects to find, I have to put every
class known to JBoss on the classpath. It looks as if there are
related memory and file-descriptor leaks - caveat emptor.
The way out of all these problems is to PRECOMPILE YOUR JSPs -
i.e. Do what Jasper would do lazily, preemptively during your
Doing this results in the further following advantages:
- your production site may consider the presence of a compiler a
security breach. Precompiled JSPs do not need one.
- dispatch of request to servlet is simpler and therefore
quicker since it goes direct from Jetty->Servlet and not
Here is a mail I sent to jboss-user to help someone who wanted
to do this:
I have just fixed up the JBoss website to precompile JSPs.
This is a diff showing the code I added to the build.xml and this is a diff showing what I
added to the web.xml web.xml
The comment line in the web.xml MUST be after the last
<servlet/> and before the first
JspC will generate some xml <servlet/> and
<servlet-mapping/> elements which I substitute in at this
The rest you will have to figure out for yourself - it is well
You will probably not need some of the workarounds I have had to
Since adding this item I have found the following :
1). Throwing a lot of concurrent requests at compile-on-the-fly
JSPs can make Jasper simply fall about and complain about files
not existing. Remove the load and hit the same page and it is
returned no problem - conclusion compile-on-the-fly is simply
not an option for enterprise level sites.
2). The JspC stuff referenced above fails to take into account
welcome-files. Jetty will look for a file of the same name
(e.g. index.jsp) (so you should make sure something is there -
even if it is an empty file) and, if it exists, redirect the
request to it. - Of course, you could probably remove the
welcome-file directive and map your servlet directly.
Since writing this item I have discovered a very useful Ant task
- xmltask (www.oopsconsultancy.com) which enables you to
cut and paste elements between XML files etc. It is particularly
useful for reconstituting your web.xml after precompilation.
There are many reports that Jasper2 does not preserve your JSP
directory hierarchy in the resulting package hierarchy - I am
awaiting a good solution (there may be a -p option to JspC?). A
client of mine has recently sponsored the application of a patch
to resolve this issue. It should make it's way into a Tomcat
release very soon.
Giving your include-only JSPs a suffix other than .jsp has been
suggested, to avoid having JspC fail to compile them and then
generate spurious elements for your web.xml...
This item needs rationalisation - volunteers ?
Frode Halvorsen posted this example jetty-web.xml to firstname.lastname@example.org :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure 1.2//EN" "http://jetty.mortbay.org/configure_1_2.dtd">
This should be put in .war/WEB-INF/jetty-web.xml.
It effectively hardwires your app to always use the same dir for
precompilation. Bouncing JBoss would normally result in the
undeploying and redeploying of your webapp, which would clean up
all associated working dirs...
N.B. Some sites run periodic jobs to clean up old files in /tmp
- so it might be advisable to choose somewhere else to site this
dir...(See this item).
JSPs should appear as <name>$jsp.java.
JSPs will implicitly create HttpSession objects for you. If you
have a heavily loaded site, carrying thousands of sessions which
you do not need can impose a substantial overhead. To avoid this,
you can be explicit about your lack of need for an HttpSession
by adding the following attribute to your JSP's 'page' directive.
The contents of the Jetty.xml in Jetty/JBoss are now embedded in
jbossweb.sar/META-INF/jboss-service.xml. They are the value of the
Jetty is currently deployed as an <UNPACKED> SAR (jboss
Service ARchive) of configuration and implementation. This has
caused some consternation in various quarters, where it is felt
that these should be separated. I shall try to list the pros and
cons of both approaches.
because the configuration is buried in
deploy/jbossweb.sar/META-INF/jboss-service.xml it is not as easy
to find as say : deploy/mail-service.xml.
you have to keep unpacking/repacking the sar - NO YOU
DON'T. JETTY IS NOW DEPLOYED UNPACKED.
New releases of Jetty can be distributed as a single drop-in
The sar (being a jar) can be signed
If you are running a farm, having jetty packaged in sar means
that you can upgrade the service across the whole cluster just
by replacing your current sar with the new one.
I think that a sar is more J2EE - that is the configuration is
held in a descriptor, which is in the deployable, with it's
implementation, exactly where you would expect to find it.
The jury is still out...
To serve external content, you can step outside the J2EE way of
doing things and use Jetty's proprietary configuration mechanism
to tell it to serve pages from anywhere on your disc.
Add something like this to the ConfigurationElement in
jbossweb.sar/META-INF/jboss-service.xml, to serve static pages:
This example maps the context /documents to the directory
/docroot, so to retrieve e.g. /docroot/myfile.html you would hit
For CGI, see below...
For other dynamic content, you can do the same sort of thing,
but add servlet handlers etc. to the context.
Look at the JBoss.Net. I believe it packages up Axis and a
WebService aware deployer so that you can just bundle your classes
and descriptor and drop them into deploy. They will be deployed
into Axis running on Jetty and you can get on with developing the
application instead of fiddling around with the plumbing.
Close integration with Jetty enables it to deliver EJB
2.1/WebService features in JBoss4.0.
Jetty comes equipped with a CGI Servlet, which you should be able
to add either to your webapp's standard web.xml like this (I'm not
sure that this is working correctly. If not, use the proprietary
or the server-wide, proprietary ConfigurationElement in
jboss-service.xml like this:
<Arg>Common Gateway Interface</Arg>
<!-- Set initParams for CGI -->
<!-- <Put name="commandPrefix">perl</Put> -->
This is fine on Unix (on which I developed this servlet), on
Windows you should be alright as long as you are running
.exes. If you want to run scripts I believe that there is an
issue with the way that Java execs subprocesses which will try
to run the script direct without the interpreter (hence the
optional commandPrefix attribute which allows you to specify an
BTW - This will not be as fast as using e.g. mod_perl in Apache (which
caches it's Perl interpreters?), since it fires off a fresh process
everytime it is hit....
Whilst there are obvious advantages to running web & EJB tiers within
the same VM, you may find that your architecture requires the
separation of these two tiers into remote processes.
Currently the only way to achieve this is to sacrifice the work that
has been done on the Jetty/JBoss integration (which is in-VM) and
simply run stand-alone Jetty instances which are configured to use a
remote JBoss instance as their JNDI server. Thus your web-content
becomes a standard EJB client.
Jetty JNDI can be persuaded to use a JBoss instance for it's
InitialContext's in two ways:
1. Specify System properties as you start Jetty e.g.
2. Specify System properties in a config file.
Create a file called jndi.properties with the following two
lines (and put the jndi.properties file into the classpath of
I suspect, although have not tried, that the second solution
would be the better one - since you may be able to package the
jndi.properties file in your.war/WEB-INF/classes (it depends on
whether InitialContext uses
Thread.currentThread().getContextClassLoader() to find the
I hope, when I have time, to write a RemoteJettyService which
will behave just like the local one....
(Thanks to the JBoss FAQ for these solutions).
Jetty provides a CodeMBean available through the JMX HTML
Adaptor. Switching on debug here (with a verbosity level of e.g. '9')
will cause Jetty debug output to be passed to JBoss. If JBoss debug
output is not enabled you will see no Jetty debug output. JBoss debug
output is echoed into server/<configuration>/logs/server.log by
There is a 'devel' target in the build.xml which should rebuild and
deploy the plugin then (perhaps) run the WebIntegration test
suite. You need a JBoss up and running.
Mail your contribution to me (email@example.com) or firstname.lastname@example.org - thanks.
"Jetty/JBoss is great, but there is one piece of missing fn-ality
that my project requires. I would like to sponsor it's development
and addition to the project..."
Please drop me a mail and tell me about it... :-)
Please contact Core Developers Network's Sales Department.
If you have any further questions about the integration which
you feel should be discussed in this document, please let me