I no longer use Resin.

The projects that I have been working on recently have all used the Tomcat Java application server, which is available from the Apache project. Tomcat is widely used and, when we were using it, was more reliable than Resin. The Tomcat documentation was also better. Because there is a big community of Tomcat users there is a better chance of getting questions answered.

Notes on Resin and Java Servlets

Contents
What is Resin
A bit of history
I love Resin
I hate Resin
The Resin experts are at Caucho
The problem at hand
Installing Resin on Linux
Configuring Resin to use openSSL
Running the Hello World servlet
Servlet mapping
Resin and servlets beats old style socket based client/server code
Starting a servlet when Resin starts up
The EchoServlet and the EchoClient
An HTTP POST Client implemented with the Apache Commons HttpClient classes
Unresolved issues

What is Resin

In this case Resin is not...

A class of organic products either natural or synthetic in origin, generally having high molecular weight. Most uncured resins used in open molding are liquids. Generally resins are used to surround and hold fibers. When catalyzed, the resin cures going through a polymerization process transforming the liquid resin into a solid. The cured resin and reinforcement creates a composite material with mechanical properties that exceed those of the individual components.

Resin is commercial Java software available from Caucho Technology, a small software company.

Resin supports a number of functions:

A bit of history

This web page originally attempted to document the setup of Resin 2.x and the Apache Axis software which supports SOAP transactions. Set up of Resin and Axis is obscure (more on this below), so I hoped that these notes would be useful to me, and perhaps the Web community in general.

At the time of this writing, Resin has moved to version 3.0, so there are a number of configuration differences. Also, looking back on my notes, I found them relatively useless. I deleted the old set of notes and started over. This second attempt appears to be more useful.

I love Resin

Despite the poor documentation, Resin is easier to install than Apache or Apache Tomcat (the Apache Project's Java application server). Resin supports servlets, which are a powerful way to implement server applications. Resin also supports JSPs, which can be used to create dynamic web pages that will report status information for servlet applications.

Caucho, the company that sells Resin, has a great developer policy. Resin is free for use during development. For small independing software developers like bearcave.com, this is a great policy. Caucho's license fees are also very reasonable: $500 per copy, with discounts for multiple copies at a site. This means that Resin is very affordable for my customers.

I hate Resin

One of my colleagues was looking at the Caucho site and reading through the documentation. He commented that he thought that the Caucho folk were not native english speakers, since the documentation was poorly written. While I don't know if the people at Caucho are native english speakers or not, they are located in La Jolla, California (a town next to San Diego and the home of my alma mater, the University of California at San Diego).

My colleague is right: the documentation for Resin is terrible. The people who wrote it seem to have few clues of how to go about explaining how to configure their software. While they do provide examples, the examples for the same feature differ on different web pages, without explaination. As with many web sites, the Caucho site seems to have grown organically over time. No one has stepped in and gone through the material to make it consistent. Instead there is a collection of web pages on various topics. It is difficult to understand how to configure Resin and to assure that Resin properly supports security.

I have wasted hours and hours as a result of the poor documentation. Sadly the only book I've found on Resin got very bad reviews on Amazon. It is sad that the quality and care that has gone into the software is not reflected in the documentation.

The Resin experts are at Caucho

I'm not a Resin expert. This is my second try at writing some useful notes on installing Resin and application software that runs under Resin. The first try did not yield very useful material. One problem was that I mixed Axis configuration with Resin configuration. Another problem was that I had a product that I had to get out, so I spent as little time on Resin configuration as possible. In my experience, Resin can be a huge time waster as I've spent hours trying to understand how to set up configuration files and in which directories I should place my software. I hope that these notes will make life easier next time I work with Resin and servlets. I hope that these notes will be useful to my readers as well. But the real experts are at Caucho and I'm not trying to supplant their expertise.

The problem at hand

I am in the process of developing Java software to support trading in financial markets (e.g., stocks, options, etc...) This will be a servlet based application. Servlets are attractive because provide an easy way to implement a server for HTTP transactions. Java Server Pages (JSPs) provide an easy way to display status information about the application, portfolios etc...

Installing Resin on Linux

I downloaded Resin 3.0.8 from Caucho.

I would like the environment I use to reflect the actual production environment that the trading software will run in. Currently this is the Linux operating system and Java. Since there may be multiple users, I don't want to install Resin in a user directory. So I've installed Resin in /usr/local, as root, under /usr/local/resin-3.0.8. I created the symbol link /usr/local/resin to this directory. This allows a reference to /usr/local/resin which will not change as the version is upgraded.

Under /usr/local/resin I created a logs directory for the resin stdout.log and the access.log. I made this directory readable, writable and executable by all users. I also wanted user level Java servlet to be executed, so I made the directory /usr/local/resin/webapps/WEB-INF readable, writable and executable by all users. Under this directory there is a classes directory where Java servlets can be placed. I also made this directory globally accessible.

With this configuration any user should be able execute the Resin application server and add a Java servlet.

Turning on the logs

The directory /usr/local/resin/conf (on my system) contains the resin.config file, which is XML that controls the Resin configuration. I added entries for the stdout.log and the stderr.logs under the host XML tag:

 <host id=''>
        <stdout-log path='/usr/local/resin/logs/stdout.log'
              rollover-period='1D'/>
        <stderr-log path='/usr/local/resin/logs/stderr.log'
              rollover-period='1D'/>
      <document-directory>doc</document-directory>
      ...
 </host>

As you can see from the log path definition, these logs will be placed in the directory /usr/local/resin/logs. As noted above, this directory has been made globally accessible (a+rwx). The logs will roll over each day.

Configuring Resin to use openSSL

SSL is the Secure Socket Layer protocol. SSL encrypts HTTP traffic so that information is not disclosed if the traffic is intercepted. SSL is used by e-commerce sites like Amazon for secure credit card transactions. When SSL is active most browsers display a small padlock icon with the hasp closed at the bottom of the browser frame.

Resin can be configured to support SSL. On this web page I've been critical of Caucho's documentation. However, the documentation for installing openSSL (an open source SSL implementation) is better than the documentation for other features.

The first step is downloading the openSSL software from The OpenSSL project. The openSSL software is distributed in source form, so you will have to build it. The build and install instructions are pretty clear. The first step is running the config script which generates the build configuration. To build for Resin you use the threads argument. I wanted to install openSSL in /usr/local/openssl so I included the other arguments.

   config threads --prefix=/usr/local --openssldir=/usr/local/openssl

Since I installed openSSL in /usr/local su'ed to root and ran make install. My Linux distribution already had openssl in /usr/bin and the openSSL includes in /usr/include/openssl. I replaced these with symbolic links to /usr/local/bin/openssl and /usr/local/include/openssl respectively. This may not have been needed for the Resin installation, but it assured that the version of openSSL that I installed would be used.

I untarred my resin installation again and rebuilt Resin. First rebuilding the configuration as shown below, and then running make.

   configure --with-openssl=/usr/local/openssl

I ran the Resin install as root. I'm happy to say that Resin replaced the Resin Java ".jar" files and did not write over the configuration files I changed.

The SSL with Resin web page under Security in the Resin documentation does a pretty good job of explaining how to make a keys directory, create an SSL key and an SSL certificate. An XML entry like the one shown below needs to be included in the resin.conf file (of course I've filled in my-password for the certificate password in this example).

       <http port="8443">
          <openssl>
            <certificate-file>keys/tradeengines.crt</certificate-file>
            <certificate-key-file>keys/tradeengines.key</certificate-key-file>
            <password>my-password</password>
          </openssl>
       </http>

I used a port number over 1000 because these are user level mapped ports on Linux.

The simplest way to start resin is $RESIN_HOME/bin/httpd.sh (on Linux/UNIX). When the Resin Java application server starts up you should see something like:

  [22:34:18.585] Loaded Socket JNI library.
  [22:34:18.585] http listening to *:8080
  OpenSSL support compiled for OpenSSL 0.9.7d 17 Mar 2004
  [22:34:18.931] https listening to *:8443
  [22:34:18.963] ServletServer[] starting
  [22:34:18.983] hmux listening to ursus:6802

To test Resin and SSL you can use the following command:

   openssl s_client -connect localhost:8443 -prexit

Running the Hello World servlet

A simple "Hello world" servlet is shown below. I placed this Java code in the file /usr/local/resin/webapps/WEB-INF/webapps/WEB-INF/classes/HelloWorldServlet.java and compiled it.

/**
 * HelloWorldServlet
 * Sep 28, 2004
 * 
 * @author Ian Kaplan, www.bearcave.com, iank@bearcave.com
 */
public class HelloWorldServlet extends HttpServlet {

    /**
     * 
     */
    public HelloWorldServlet() {
        super();
    }

    public void doGet( HttpServletRequest req,
                       HttpServletResponse res )
        throws ServletException, IOException
    {
        if (! req.getMethod().equals("HEAD")) {
            PrintWriter out = res.getWriter();
            out.println("<HTML>");
            out.println("<HEAD>");
            out.println("<TITLE>Hello world!</TITLE>");
            out.println("</HEAD>");
            out.println("<BODY
                       background=\"http://www.bearcave.com/images/paperbk.gif\">");
            out.println("<br/>");
            out.println("<h1>");
            out.println("<i>");
            out.println("Hello world!");
            out.println("</i>"); 
            out.println("</h1>");
            out.println("</BODY>");
            out.println("</HTML>");
        }
    } // doGet
}

I executed the Resin server by entering /usr/local/resin/bin/httpd.sh. By default this starts the Resin server which acts as a local web server on port 8080. To execute the servlet I brought up a Web browser (Firefox) and entered http://localhost:8080/servlet/HelloWorldServlet.

Servlet mapping

The web.xml file can provide a mapping between the an abstract name used in the browser URL dialog and actual servlets on the local system. So rather than requiring http://localhost:8080/servlet/HelloWorldServlet to run the HelloWorldServlet, the name could be mapped to http://localhost:8080/test/hello.

In the Resin documentation Caucho notes that the web.xml file is placed in the WEB-INF directories. However, when I tried putting web.xml in /usr/local/resin/webapps/WEB-INF it did not work. Looking at the A Hello, World Servelt tutorial (http://localhost:8080/resin-doc/servlet/tutorial/helloworld/index.xtp on my installation) gave some hints on how to make the name mapping work.

Apparently an application name is needed. For this example, the application will be called test. Following the application base name would be the name mapped to the servlet. For example http://localhost:8080/test/hello.

The first thing to do is to create a directory /usr/local/resin/webapps/test/WEB-INF/ (note that /usr/local/resin/webapps is the root of the web application directory for resin). The web.xml file is placed in the WEB-INF directory under the test directory. A simple web.xml for this directory is shown below:


<web-app xmlns="http://caucho.com/ns/resin">
  <servlet servlet-name="hello"
           servlet-class="HelloWorldServlet"/>
  <servlet-mapping url-pattern="/hello"
                   servlet-name="hello"/>
</web-app>

This web.xml file maps the name /hello to the servlet whose class is HelloWorldServlet. In this case the servlet will be /usr/local/resin/webapps/WEB-INF/classes/HelloWorldServlet.java. Apparently the Java root path used by Resin is /usr/local/resin/webapps/WEB-INF/classes/

Note that there is nothing else in the directory /usr/local/resin/webapps/test/WEB-INF/ but the web.xml file.

Multiple names can be associated with different classes in the web.xml file. Here is another version of web.xml (again, in the /usr/local/resin/webapps/test/WEB-INF/ directory). Here hello is mapped to the Java object /usr/local/resin/webapps/WEB-INF/classes/HelloWorldServlet.java and yello is mapped to /usr/local/resin/webapps/WEB-INF/classes/example/HelloWorldServlet.java


<web-app xmlns="http://caucho.com/ns/resin">
  <servlet servlet-name="hello"
           servlet-class="HelloWorldServlet"/>
  <servlet servlet-name="yello"
           servlet-class="example.HelloWorldServlet"/>
  <servlet-mapping url-pattern="/hello"
                   servlet-name="hello"/>
  <servlet-mapping url-pattern="/yello"
                   servlet-name="yello"/>
</web-app>

The URLs are

http://localhost:8080/test/hello
http://localhost:8080/test/yello

Apparently there is a W3C standard that defines the web.xml file (and presumably an XML schema somewhere. Many of the Resin examples use a compact form of the web.xml XML. Apparently the same definition can be written using element tags (instead of attributes). This is shown below (modeled after Example 2-6 in Java Servlet Programming, 2nd Edition, by Hunter).


<web-app>
   <servlet>
      <servlet-name>
          hello
      </servlet-name>
      <servlet-class>
          HelloWorldServlet
      </servlet-class>
   </servlet>
   <servlet-mapping>
      <servlet-name>
          hello
      </servlet-name>
      <url-pattern>
         /hello
      </url-pattern>
   </servlet-mapping>
</web-app>

Resin will process this definition as well as the attribute form. Here again the class that /hello is mapped to is /usr/local/resin/webapps/WEB-INF/classes/HelloWorldServlet.java

Resin and servlets beats old style socket based client/server code

Servlets and a Java application server like Resin provide a powerful way to implement client/server software. Servlets naturally support HTTP transactions. Unlike socket based (TCP/IP) servers, the servlet writer does not have to write thread or process code to handle multiple concurrent transactions. Resin, as the Java application server, takes care of this. Of course the servlet writer does have to manage any shared resources (e.g., memory or database connections). By including the right information in the web.xml file (see below) the Java application server can start the servlets. The servlets will respond to HTTP URL references (e.g., they can act like a web page) and can be written to display their status. This makes servlets a much easier to manage environment that the classic UNIX shell script (to start processes) and socket based client/server software.

Starting a servlet when Resin starts up

The Resin documentation does discuss how to start a servlet when Resin starts. But what I did not see discussed was what Resin does on start up. Apparently, resin searches the directory tree rooted at $RESIN/webapps and finds the web.xml files. For my installation this is /usr/local/resin/webapps/. For this example, my web.xml file is in /usr/local/resin/webapps/test/WEB-INF/web.xml. By placing the web.xml file in this directory, I can have a URL like http://localhost:8080/test/echo to reference my echo servlet (see below).

By including the <local-on-startup/> tag in the servlet defintion section the servlet will be started when Resin starts. The contents of the web.xml file is shown below. The servlet specification includes the servlet name and class definitions, as shown above, and definitions for the initialization parameters that Resin provides to the servlet. In this case these parameters are nonsense (foo is associated with maggie and bar is associated with morgan), but they could be meaningful values used to initialize the servlet.


<web-app>
   <servlet>
      <servlet-name>
          echo
      </servlet-name>
      <servlet-class>
          example.EchoServlet
      </servlet-class>
      <init-param>
         <param-name>
             foo
         </param-name>
         <param-value>
             maggie
         </param-value>
      </init-param>
      <init-param>
         <param-name>
             bar
         </param-name>
         <param-value>
             morgan
         </param-value>
      </init-param>
      <load-on-startup/>
   </servlet>
   <servlet-mapping>
      <servlet-name>
          echo
      </servlet-name>
      <url-pattern>
         /echo
      </url-pattern>
   </servlet-mapping>
</web-app>

The EchoServlet and the EchoClient

The URL for the servlet above is http://localhost:8080/test/echo. The location of the servlet class file (EchoServlet.class) is, in my installation, /usr/local/resin/webapps/WEB-INF/classes/example/EchoServlet.class (note that the class path in the web.xml file is example.EchoServlet.class). Example Java code is linked to below:

An HTTP Client that uses the Apache Commons HttpClient classes

I wrote the SynchronousHttp class before I learned about the Apache Commons HttpClient classes. These classes abstract many of the low level details that are exposed in the SynchronousHttp class. This HTTP client also handles HTTP timeout. Like the EchoClient, above, the HttpClient sends messages to the EchoServlet.

Unresolved issues

Security and Starting Resin when Linux boots

In a production environment it could be useful to have the Resin web server startup when Linux boots. This is documented to some degree on the Caucho web page How to start Resin when Linux Boots

Processes that are started at boot time are, as far as I know, run at the root level. I am concerned that if Resin runs at the Root level, then so will servlets, JSPs etc... If this were the case it could be a huge security hole.

In the resin.conf file a definition can be provided for the user name and the group name:

  <!--
     - If starting bin/resin as root on Unix, specify the user name
     - and group name for the web server user.
     -
    -->
     <user-name>resin</user-name>
     <group-name>resin</group-name>
 
     Note that normally user-name and group-name are commented out

I added a resin user and a resin group to my Linux system. I uncommented the tags for user-name and group-name, as shown above. I then tried starting resin as root and got the error shown below:

Starting Resin on Sat, 02 Oct 2004 10:06:03 -0700 (PDT)
 
[10:06:05.409] Loaded Socket JNI library.
[10:06:05.409] http listening to *:8080
java.io.IOException: Linux 2.4.21-15.0.3.ELcustom can't use setuid
with bin/httpd.sh.  Either use bin/resin or see the documentation for
alternative ways of handling protected ports.The  tag
requires Linux kernel 2.5 or later.
        at com.caucho.util.CauchoSystem.setUserNative(Native Method)
        at com.caucho.util.CauchoSystem.setUser(CauchoSystem.java:427)
        at
	com.caucho.server.resin.ResinServer.start(ResinServer.java:420)
        at com.caucho.server.resin.Resin.init(Resin.java:279)
        at com.caucho.server.resin.Resin.main(Resin.java:474)

In their documentation on the user-name tag, Caucho notes

Configures the Unix setuid user name used after Resin binds the reserved ports as root.

Note, Linux requires the new thread package (e.g. RedHat 9.0 or later) to support user-name.

Perhaps it's a Linux version problem. However, I'm running a "While Box Linux" kernel, which is supposed to track the Red Hat 3.0 kernel, so I don't think that this is the problem. What ever the issue is, it would seem that a solution to the issue of running Resin as root is needed.

References

Ian Kaplan, May 2003
Totally rewritten: October 2004
Last revised:


back to Java page