Frequently Asked Questions

Questions
General

Servlets

Installation

Common Mistakes

Administration

 

Answers
How do I make hits on 'http://www.myserver.com/' go to a servlet?

There are various approaches to this. Several involve 'mod_rewrite', so check out the docs for that if the following does not suite you. Another possibility is to use JServSSI in conjunction with the DirectoryIndex directive (in srm.conf, or a local '.htaccess' file)
DirectoryIndex index.jhtml
index.jhtml: 
<SERVLET CODE="com.myserver.www.HomepageServlet">
Error! Page not parsed.
</SERVLET>
When will next release of Apache JServ be ready?

As of today there were exactly 39.342 unidentified bugs. Identified bugs have mostly been fixed, though. Since then 9.34 bugs have been fixed. Assuming that there are at least 10 unidentified bugs for every identified one, that leaves us with 39.342 - 9.32 + 10 * 9.34 = 123.402 unidentified bugs. If we follow this to its logical conclusion we will have an infinite number of unidentified bugs before the number of bugs can start to diminish, at which point the program will be bug-free. Since this is a computer program infinity = 3.4028e+38 if you don't insist on double-precision. At the current rate of bug discovery we should expect to achieve this point in 3.37e+27 years. I guess we'd better plan on passing this thing on to our children....

- paraphrased from the 'fvwm2' man page. ;)

In short, we don't know, but if you'd like to see it happen faster, you're welcome to join the development group.

When I try to startup Apache JServ I get an error message starting with "java.lang.NoClassDefFoundError:  javax/servlet/...". What's wrong?

You need to have the JavaSoft Java Servlet Development Kit 2.0 installed and jsdk.jar visible in your classpath when Apache JServ starts. These classes are the definitions of the Servlet API and you need to download them directly from the servlets web site.
Why do I get 'Connection from host/address refused due to authentication failure'?

One common cause for this is people attempting to connect to Apache JServ with their web browser. Apache JServ is not an HTTP server. You cannot connect directly to it with a web browser by adding the Apache JServ port number to the URL. You must configure a web server to relay requests for servlets to the Apache JServ engine. At present, the only supported web server is Apache, but the protocol used between the web server and Apache JServ is well-defined, so adding support for other web servers is possible.

Another common cause is people not configuring their security environment properly. For security reasons, connection authentication is enabled by default. Then, in order to correctly perform the connection authentication, both the module and the servlet engine must share a common secret key that must be exactly the same. Another issue is the IP address filtering that is performed automatically by Apache JServ to avoid risks of denial of service attacks. You must enable at least one host to be able to communicate with Apache JServ.

Where can I find examples of session management?

JavaSoft have written a write paper on how they designed the JDC. This can be found at http://developer.java.sun.com/developer/technicalArticles/#jdc.
What methods/packages exist to enhance the presentation of my servlet site?

Simple servlets will contain something like:
  PrintWriter out = req.getWriter();
  out.println("<HTML>");
  ...
  out.println("</HTML>");

For larger servlets, where presentation is important, this is not ideal for many reasons. For example, if a web designer was tasked with designing the look and feel of the site, they may not be comfortable editing and compiling Java servlet programs. There are two mainstream solutions to this problem:

Page Compilation is when servlets are compiled and run on-the-fly by the web server from Java code embedded in the web page. JSP is described at http://java.sun.com/products/jsp/index.html. GnuJSP is a free implementation of the JSP standard. You might want to check it out at http://www.nmg.nl/~vinny/gnujsp/. Another implementation called GSP, can be found at http://www.bitmechanic.com/projects/gsp/.

Template System, is when you base your page layout in an HTML template. A few Java Apache members have created a template package, which has not yet been packaged and released. It can be checked out using anonymous CVS from the same repository as Apache JServ as the module 'jserv_utils'. See the CVS instructions on the Java Apache Project web site for more information on this.

How do I create different work areas for several developers?

Using servlet zones, you can map a different directory and set of servlet repositories and class paths for each user, e.g.,
www.urlstuff.com/bob/<bob-servlets>
www.urlstuff.com/alice/<alice-servlets>
etc. 

The different developers will share a single jserv.properties file, which is actually pretty convenient since this contains stuff that typically doesn't need to vary. Each servlet zone gets its own configuration file.

You could also setup separate virtual hosts, in which case each developer would have an even more separate environment in which to run cgi, servlets, etc. it's really easy to setup virtual hosts, and it's how I do my own work even as the sole user of my machine. The different virtual hosts would still need to share the jserv.properties file.

For more information on servlet zones and how to mount them on different network environments, go here.

Why do I get class not found errors for servlet classes in javax.* when compiling Apache JServ even though my classpath is correct?

Some java compilers can't handle compressed jar files. The solution is to decompress the jar file:
  jar xf jsdk.jar
  jar cf0 jsdk-uncompressed.jar javax sun

(that's a zero after "cf", not the letter "O") then update your makefiles to point to the uncompressed jar

When my servlet gets following URL http://www.server.com/servlets/cal?name=foo+bar+&calsystem=foobar&cal=foo@bar and I try to make sense of it in servlet's doGet(req,res) method with HttpUtils.parseQueryString(), I get {calsystem=[Ljava.lang.String;@1dce128e, cal=[Ljava.lang.String;@1dce127c,name=[Ljava.lang.String;@1dce12a8} - the key values look just fine, but the value fields seems to have something wrong. What is it?

As you can see from the parseQueryString source (below), the value of each hashtable entry is an array of one or more strings. If you do this:
Hashtable params = HttpUtils.parseQueryString(req.getQueryString()); 
String name = ((String[]) (params.get("name")))[0]; 

you should attain your heart's desire. The javadoc for this function is wrong, in that it implies that arrays will only be used if a parameter is repeated. In my opinion, it's better to always return String[]s and have then be length 1 in some cases, rather than make people check every time whether they got an array or a single object. The string "[Ljava.lang.String;@1dce128" means "an array of Strings", which should provide a hint as to what is going wrong.

What do I put in my Apache Configuration file for the module line?

 
  Apache JServ 0.9.x Apache JServ 1.0.x
Apache 1.2.x Module jserv_module mod_jserv.o Module jserv_module modules/jserv/mod_jserv.o
Apache 1.3.x AddModule jserv_module mod_jserv.o AddModule jserv_module modules/jserv/mod_jserv.o

Note: If you're using Apache 1.3 and you use APACI, you can do this simply by adding a "--add-module=modules/jserv/mod_jserv.o" option to your command line invocation of 'configure'. And if you build Apache JServ as a DSO, you don't need to recompile Apache.

I have a directory within my servlets directory and things break when I try to use http://www.server.com/servlets/test/TestServlet, but when I put TestServlet directly in the servlets directory and remove the "test" from the URL, things work just fine. Is this a bug?

No, this is not a bug but a wanted feature. This problem derives from the way Java structures classes into subdirectories per package name. People suffer similar problems writing non-servlet code. (we have a love-hate relationship with this approach: it's clean, but it creates deep directory trees.) Java would expect a file called $DIR/test/SimpleServlet to have the fully-qualified classname test.SimpleServlet. It looks in the 'test' subdirectory of each directory in the classpath for files in the 'test' package.

The module currently converts a request for test/SimpleServlet into a request for the class test.SimpleServlet. It finds the class file, but gets confused because the file actually contains a definition of the file 'SimpleServlet'. In short: make sure the package name declared in the class matches the directory structure where the class file is located.

To fix this particular problem: declare the servlet using a proper package name: org.dummy.test.SimpleServlet, compile it into $ROOT/servlets/org/dummy/test/SimpleServlet.class, and make your ServletPath $ROOT/servlets. Add an alias or servlet.simple.code property to generate a shorter URL if you like. (Thanks to Martin Pool)
Where can I get more information on servlets (JSDK, specification, sample code, case studies, tutorials, examples)?

JavaSoft servlet web site is the best place since it has updated link to almost all servlet resources worldwide.
Why servlet API classes were removed from JDK 1.2beta3 on?

To allow faster update cycles.
Why do I get lots of errors when I try to build Apache JServ?

Try to update to a recent version of GNU Make.
I see a lot of CPU usage even though I'm not running any servlets. Can I change this?

This is caused by a problem due to the combination of green threads scheduling and asynchronous garbage collecting. If you are using a platform that have a native thread implementation JVM (like Solaris 2.6 for example), you should consider upgrading. If you are stuck with a green thread implementation then you may try to turn off asynchronous garbage collection by adding a
wrapper.bin.parameters=-noasyncgc 

directive to your jserv.properties file. This lower considerably the CPU usage (0% when idle). On the other hand, when memory is low, the garbage collector runs synchronously and decreases performance. (Thanks to Francis J. Lacoste)

I have Solaris and all the Java classes have compiled correctly, but a "make install" fails miserably. What's wrong?

Make sure your path is using /usr/ucb/install
Why my classes are not reloaded even if autoreloading is enabled?

Probably because Apache JServ finds them in your classpath and any class found in the classpath is considered a system class and cannot be reloaded.
Why Apache JServ log file gets so big?

You may want to disable some log channels in your jserv.properties to avoid request and response tracing which are usually very wordy.
Why do I keep getting UnsatisfiedLinkError? (or) Why won't my servlets using native code run?

Servlets using native libraries must be put in the classpath, otherwise you will get a java.lang.UnsatisfiedLinkError because in JDK1.1 a class with native methods can't be loaded by custom class loaders (servlet class loader).
Can I use different UIDs/GIDs for different servlets or virtual hosts?

Yes, you can! The complete separation between the web server and the server engine allows you to connect multiple servlet engines to the same web server. If these servlet engines are started in standalone mode using the wrapper with different UID/GID, you end up having multiple secured servlet environments. Of course, this requires a different JVM for each secured servlet environment. For this reason, future releases will include a servlet sandbox to guarantee a comfortable security level without requiring multiple JVMs.
Which one is the right name: JServ, mod_jserv or Apache-JServ or Apache JServ?

Apache JServ is the right name. Please, avoid the use of other denominations because "JServ" is a registered trademark we don't own and "mod_jserv" is somehow misleading since it should be used to refer only to the Apache module used to communicate with Apache JServ.
Why the JSDK is not redistributed with Apache JServ even if the license says it is freely redistributable?

We know this sucks but there are some claims in Sun's license that simply don't fit with our open source model because we may get sued for problems found in their code even if we didn't touch it. To avoid eventual legal problems we decided not to ship it.
So, why didn't you implement your own servlet API classes following the spec?

Well, we thought about it but we decided to stick with JavaSoft's to avoid platform incompatibility.
How can I use simple load-balancing for my servlets?

This can be done with optional mod_rewrite module, a a rule-based rewriting engine to rewrite requested URLs on the fly. The idea is to rewrite incoming URL with different Servlet mount points in order to be able to distribute requests on different Apache JServ's.

In the following sample, a random load-balancing is performed on 3 servlet engines (but mod_rewrite can make more for you).

  1. Enable the mod_rewrite module in the server build Configuration file making sure that mod_jserv stands before the mod_rewrite's line, as module's as module's execution order is dependant of the (reverse) order in this file.

    AddModule modules/jserv/mod_jserv.o
    ../..
    AddModule modules/standard/mod_rewrite.o

    For win32 systems, you just need to uncomment the mod_rewrite directive up on top of httpd.conf

    LoadModule rewrite_module modules/ApacheModuleRewrite.dll

  2. Rebuild apache (not needed for win32 systems).
  3. Configure Apache to start Apache JServ manually (in httpd.conf)

    ApJServManual on

  4. Configure Apache to distribute servlet execution over different servlet engines depending on URL

    ApJServMount /servlet1 ajpv11://host1:port/zone
    ApJServMount /servlet2 ajpv11://host2:port/zone
    ApJServMount /servlet3 ajpv11://host3:port/zone
    ApJServMount /defservlet ajpv11://host1:port/zone

  5. Create the load-balancing config file (/usr/local/apache/conf/load_balancer.txt)

    jserv servlet1|servlet2|servlet3

  6. Configure Apache to enable URL rewriting

    RewriteEngine on
    RewriteLog "/usr/local/apache/logs/rewrite.log"
    RewriteLogLevel 9

    RewriteMap mountservlet rnd:/usr/local/apache/conf/load_balancer.txt
    RewriteRule /servlets/(.*)$ /${mountservlet:jserv|defservlet}/$1 [PT]

Note: this load balancing method works only for stateless servlets. If sessions are created by the servlet, there is the chance that requests on the same session are handled by different servlet engines which, by now, have no way of sharing sessions between them. A complete load balancing schema will be implemented in future versions of Apache JServ and won't use external programs/modules but they will be handled internally. (Thanks to Jean-luc Rochat)

How can I use tricky load-balancing/fail-over/manageability for my servlets?

Use the previous sample, and create a "watchdog program", that is able to delete an entry in the load_balancer.txt file.
After Apache JServ is installed, I can't get servlets to run. I get this error message: "Received empty servlet name" or "Status: 400 Bad Request Servlet-Error" or hangs for a long time. What's wrong?

Two common mistakes may generate such behavior:
  1. you are trying to connect directly to the port Apache JServ is listening on (usually 8007). Eg. the following is usually wrong:

    http://host:8007/servlets/HelloWorldServlet

    This is doesn't work because Apache JServ is not an HTTP server, but an AJP server (see Apache JServ Protocol for more information) and does not understand HTTP requests on that port. You should request servlet directly to your web server using the HTTP port for your virtual host (usually the default HTTP port 80), in this case

    http://host/servlets/HelloWorldServlet

  2. if the above doesn't apply or doesn't correct the problem, make sure authentication settings (enabled/disabled) are matched on the two sides. In fact, if the two sides don't match, this generates AJP fault states and bad-request type errors.
I want to enable connection authentication. How do I generate the needed secret keys?

You don't need any special tool but just a little fantasy. A secret key could be any file (even an image could do the job) with any length that should be really hard to guess and protected from untrusted access. The authentication procedure needs to compute an MD5 hash for that file and it's complexity (time of execution) is linear with the length of the secret key file. For this reason, as long as the size of the secret key is not known, even a few dozen bytes would do the job perfectly without security hazards and will reduce the authentication overhead. Note that both the module and the servlet engine must use exactly the same secret key (binary copy).
How do I create an image with a servlet, for example, a graph out of a list of values?

Servlets allow you to specify the content type of the response. This ability let you generate dynamic images simply mapping the <img> tag with the proper servlet URL. To do this, you need to generate an off-screen image object and send it encoded in your favorite image format. Free GIF image encoders are not available due to patent restrictions, while JDK 1.2 contains a JPG image encoder (and few others like PNG may be added in the future).

To create an off-screen image you could follow these guidelines:

Frame f = new Frame();

f.addNotify() // <-- this creates a "frame peer", which makes it all work

Image img = f.createImage();
doMyPaintImage(img.getGraphics());

(etc.)

Note that it apparently needs to be a Frame since Canvas doesn't seem to work. It probably just calls for the toplevel window component to do the job. (Thanks to Bjorn Sandberg).

When I call HttpUtils.parsePostData() all the POST data is eaten by Apache Jserv. Is this a bug?

A servlet engine is only supposed to read (and thus eat) the POST data by calling parsePostData() when parsePostData() would actually be able to handle it, i.e. the content-type is "application/x-www-urlencoded". If the content-type is something else, like "multipart/form-data" (or "text/html" when a HTML document is PUT from Netscape Composer), the POST data should be left to the servlet itself to handle. (Thanks for Vincent Partington)
How come I don't get any log messages even if I enabled tracing and all trace channels?

In the latest releases, the directive trace was replaced with log, along with all other instances of trace in the jserv.properties configuration file. You should change any directives that contains "trace." with "log."
Note: if you have a question that should be listed here (even if you don't have the answer) or have a better answer for one of these questions, let us know it on the mailing lists. Every possible help is greatly appreciated. Thanks in advance.

Copyright (c) 1997-98 The Java Apache Project.
$Id: FAQ.html,v 1.14 1998/12/05 11:31:33 stefano Exp $
All rights reserved.