ONJava.com    
 Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples


Resin: The Instant Application Server

by Daniel Solin
09/18/2002

Imagine a Java Web application server that runs on Unix, delivers incredible performance, is really easy to set up, and inexpensive to boot. Even crazier, imagine that this little app server offers all of the features you expect from a modern Java server, including JSP/servlets, XML/XSL, and EJB/CMP.

You can stop imagining. It actually exists, and it goes by the name of Resin. In this article, we will show you how to install Resin and get it running; we'll conclude with an EJB/CMP example that shows how Resin makes these techniques easily usable. If you have worked with installations of Java servers before, I think you will be amazed at how fast and simple Resin is. At an ISP I worked for, we had Resin up and running in a matter of minutes.

Getting And Installing Resin

We'll start out by installing Resin on our system. Since Resin is itself a Java application, it needs a Java environment to compile and run. If you don't already have them, you need to download and install both the Standard Edition (SE) and the Enterprise Edition (EE) of the JDK (version 1.3.1 or higher). See java.sun.com for instructions on how to accomplish this. Note that you will not be able to follow the steps later in this article if you don't have a working installation of JDK EE. This is because we will install the Enterprise Edition of Resin, which requires JDK EE to work.

With both the SE and EE JDKs set up, we can begin our adventure by downloading and unpacking the Resin source distribution, available here. At the time if this writing, the latest version of Resin-EE (Enterprise Edition) was 2.1.

When the file is on your local machine, just unpack it into your /usr/local directory.

root@localhost:~# resin-ee-2.1.4.tar.gz /usr/local
root@localhost:~# cd /usr/local
root@localhost:/usr/local# tar xvfz resin-2.1.4.tar.gz
root@localhost:/usr/local# ln -s resin-2.1.4 resin

Since we're going to run Resin as a standalone Web server, we need to change the port the server will listen on before we start it. This can be done by changing a line in /usr/local/resin/conf/resin.conf. Open resin.conf in an editor and locate the following line:

<http port='8080'/>

It's very common to use Resin in conjunction with Apache, letting Resin answer requests to JSP/servlets, and leaving the rest to Apache. This is why Resin is set to listen to port 8080 instead of 80, which is the standard port for Web servers. We are going to let Resin take care of all requests to our server (which it actually is very capable of!) so we will change the port to 80 in the above line. Save the file and exit the editor.

Now start Resin by executing the following:

root@localhost:~# /usr/local/resin/bin/httpd.sh

You should now see output that looks something like this:

Resin 2.1.4 (built Fri Aug 2 14:16:52 PDT 2002)
Copyright(c) 1998-2002 Caucho Technology. All rights reserved.

Starting Resin on Tue, 10 Sep 2002 09:31:46 +0200 (CET)
[2002-09-10 09:32:04.791] initializing application
http://localhost/quercus

[snip: loads of compilations]

[2002-09-10 09:36:34.618] initializing application 
            http://localhost/
[2002-09-10 09:36:34.619] initializing application 
            http://localhost/java_tut
[2002-09-10 09:36:34.620] initializing application 
            http://localhost/examples/basic
[2002-09-10 09:36:34.621] initializing application 
            http://localhost/examples/tags
[2002-09-10 09:36:34.622] initializing application 
            http://localhost/examples/tictactoe
[2002-09-10 09:36:34.624] initializing application 
            http://localhost/examples/navigation
[2002-09-10 09:36:34.625] initializing application 
            http://localhost/examples/xsl
[2002-09-10 09:36:34.626] initializing application 
            http://localhost/examples/templates
[2002-09-10 09:36:34.627] initializing application 
            http://localhost/examples/login
[2002-09-10 09:36:34.628] initializing application 
            http://localhost/cmp
http listening to *:80
srun listening to 127.0.0.1:6802

Now, point your browser to http://localhost. You should now see the default Resin home page, as shown in Figure 1.


Figure 1. Resin home page.

Deploying A Test Application

So you now have a robust Web application server up and running, but what can it actually do for you? In this section, we'll deploy a simple test application into our server, getting you started and giving you an overview of how Resin's most important features can make your Web development easier.

We will create a basic example of how one can use the Container-Manager Persistence (CMP) features of Resin to simplify and standardize the communication between a Java servlet and a MySQL database. For this, you also need to have a MySQL server running (or any other database server for which you have JDBC drivers). Execute the following SQL queries to create a test table and populate it with a few rows:

use test;
CREATE TABLE turtle
(
   turtle_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
   turtle_name VARCHAR(50),
   PRIMARY KEY(turtle_id)
);

INSERT INTO turtle VALUES(NULL,"Donatello");
INSERT INTO turtle VALUES(NULL,"Michaelangelo");
INSERT INTO turtle VALUES(NULL,"Raphael");
INSERT INTO turtle VALUES(NULL,"Leonardo");

As you can see, this table will be used by a turtle enthusiast for keeping track of his beloved creatures.

MySQL Reference Manual

Related Reading

MySQL Reference Manual
Documentation from the source
By Michael "Monty" Widenius, David Axmark, MySQL AB

For the representation of the table and its rows, we will create a total of three classes:

These three clases are listed below. (Tip: It would be wise to turn off Resin while fiddling with these files. Since Resin tries to compile and reload configuration changes on-the-fly, it's possible you'll get lots of annoying error messages on the screen while working.)

Example 1. Turtle.java.

package org.solin.web.Turtle;
import javax.ejb.*;

public interface Turtle extends EJBLocalObject
{
    String getTurtleId();
    String getTurtleName();
}

Example 2. TurtleHome.java.

package org.solin.web.Turtle;

import javax.ejb.*;
import java.util.Collection;

public interface TurtleHome extends EJBLocalHome
{
    Turtle findByPrimaryKey(Integer name)
        throws FinderException;

    Collection findAll()
        throws FinderException;
}

Example 3. TurtleBean.java.

package org.solin.web.Turtle;
import java.util.Collection;

public abstract class TurtleBean extends com.caucho.ejb.AbstractEntityBean
{
    public abstract String getTurtleId();
    public abstract String getTurtleName();
}

Basically, you can see here that TurtleHome will give us rows (turtles) from the table in the form of Turtle objects, and TurtleBean is the entity bean that will be used by the servlet to hold the actual data.

These files should be placed in the WEB-INF/classes subdirectory of your document root (default is <RESIN_HOME>/docs). For our entity bean (TurtleBean) to work, we need to create a deployment descriptor that describes the bean. Place the turtle.ejb file (shown in Example 4) in your WEB-INF directory:

Example 4. turtle.ejb.

<ejb-jar>
  <enterprise-beans>
    <entity>
      <ejb-name>TurtleBean</ejb-name>
      <local-home>org.solin.web.Turtle.TurtleHome</local-home>
      <local>org.solin.web.Turtle.Turtle</local>
      <ejb-class>org.solin.web.Turtle.TurtleBean</ejb-class>

      <prim-key-class>Integer</prim-key-class>
      <primkey-field>turtleId</primkey-field>

      <persistence-type>Container</persistence-type>
      <reentrant>True</reentrant>

      <abstract-schema-name>turtle</abstract-schema-name>
      <sql-table>turtle</sql-table>

      <cmp-field>
                
<field-name>turtleId</field-name>
      </cmp-field>

      <cmp-field>
                
<field-name>turtleName</field-name>
      </cmp-field>

      <query>
                
<query-method>
                    
<method-name>findAll</method-name>
                
</query-method>
                
<ejb-ql>SELECT o FROM turtle o</ejb-ql>
      </query>
    </entity>
  </enterprise-beans>
</ejb-jar>

In this file, we define the classes that are used as interfaces, and by what class the bean is represented. We also define what fields we want to be able to access, and a query for retrieving all rows in the table (defined in TurtleHome.findAll()). As usual with EJB, we also need to attach the bean to Resin with the web.xml file (located in WEB-INF). The code for doing this is listed in Example 5.

Example 5. web.xml.

<web-app>
  <resource-ref>
    <res-ref-name>jdbc/test</res-ref-name>
    <res-type>javax.sql.XADataSource</res-type>
    <driver-name>com.caucho.jdbc.mysql.Driver</driver-name>
    <url>jdbc:mysql_caucho://localhost:3306/test</url>
    <init-param user="root"/>
    <init-param password="secret"/>
  </resource-ref>
  <resource-ref>
    <res-ref-name>java:comp/env/cmp</res-ref-name>
    <class-name>com.caucho.ejb.EJBServer</class-name>
    <init-param data-source="java:comp/env/jdbc/test"/>
  </resource-ref>
</web-app>

In this example, we use the MySQL driver that comes with Resin, but you can, of course, change these parameters to better fit your setup. Finally, we also need a servlet to communicate with your browser. See Example 6 below.

Example 6. TurtleServlet.java.

package org.solin.web.Turtle;

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.naming.*;
import javax.ejb.*;

public class TurtleServlet extends HttpServlet
{
   private TurtleHome turtlehome = null;

   public void init() throws ServletException
   {
      try
      {
         Context cmp = (Context) new InitialContext().lookup("java:comp/env/cmp");
         turtlehome = (TurtleHome) cmp.lookup("TurtleBean");
      }
      catch(NamingException e)
      {
         throw new ServletException(e);
      }
   }

   public void doGet(HttpServletRequest req, HttpServletResponse res)
      throws IOException, ServletException
   {
      PrintWriter out = res.getWriter();
      res.setContentType("text/html");
      out.println("<h2>My Turtles</h2>");
      out.println("Below is a listing of my turtles, 
                   in no specific order.<br><br>");
      try
      {
          Collection c = turtlehome.findAll();
          Iterator iter = c.iterator();
          while( iter.hasNext() )
          {
             Turtle turtle = (Turtle) iter.next();            
             out.println(turtle.getTurtleId() + ". " + 
                        turtle.getTurtleName() + "<br>");
          }
       }
       catch( Exception e)
       {
          throw new ServletException(e);
       }
   }
}

Resin also needs to know about the servlet, so add the following lines to your resin.conf:

<web-app>
  <servlet-mapping url-pattern='/turtle' servlet-name='turtle-servlet'/>
  <servlet servlet-name='turtle-servlet' 
               servlet-class='org.solin.web.Turtle.TurtleServlet'>
    <init-param greeting='My turtles'/>
  </servlet>
</web-app>

Note that this needs to reside within the <host> tag. When all is done, start (or reload) Resin. All of your newly-added configuration and source files will now be automatically compiled and registered by the server. Actually, Resin checks for changes in the files all the time, and automatically recompiles and/or reloads a source file or configuration file as it gets updated. No more tedious server-restarting and manual recompiling!

OK, point your browser at http://localhost/turtle. It should show something similar to Figure 2.


Figure 2. Output of Turtles application.

Summary

You now have a working Resin installation and a running example of a database-driven Web application based on EJB/CMP. When mentioning these techniques, one usually thinks about heavily-loaded, large-scale sites, divided into several servers, but Resin makes this useful to us mortals as well. Rapid server installation and simplified database management is a good thing for everyone.

If you want to get deeper into Resin-CMP right away, take a look at this tutorial. As stated earlier, a very common setup is to use Resin side-by-side with Apache, letting Resin deal exclusively with the Java requests. You can find more information about that configuration and a few others in this document.

Apache Pocket Ref

Related Reading

Apache Pocket Ref
By Andrew Ford

When one has figured out the features and benefits of Resin, development usually gets both more fun and faster. Good luck!

Daniel Solin is a freelance writer and Linux consultant whose specialty is GUI programming. His first book, SAMS Teach Yourself Qt Programming in 24 hours, was published in May, 2000.


Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.