Here are some rough instructions for installing the Java Runtime Environment (JRE):
First, make sure you're in your home directory, or wherever you want to put the JRE directory. Copy the compressed archive to here, uncompress, and then unarchive.
cp /l/www/classes/a202-ewennstr/software/jdk-8u11-linux-x64.tar.gz .
gunzip jdk-8u11-linux-x64.tar.gz
tar xvf jdk-8u11-linux-x64.tar
That's actually all there is to it!
Now we'll do the same thing for Apache Tomcat.
Copy, uncompress, unarchive:
cp /l/www/classes/a202-ewennstr/software/apache-tomcat-7.0.54.tar.gz .
gunzip apache-tomcat-7.0.54.tar.gz
tar xvf apache-tomcat-7.0.54.tar
We need to do some configuration changes to make sure that our servers don't bump into each other. You should have two different port numbers for Tomcat: a "server port" and a "connector port". They're listed on the port numbers page. Don't get them mixed up!
Now we should move into the Tomcat configuration directory and edit the server configuration file so that Tomcat knows what our ports are:
cd apache-tomcat-7.0.54
cd conf
pico -w server.xml
Find the line that looks like this: <Server port="SomeNumber" shutdown="SHUTDOWN">
and change SomeNumber to your Tomcat server port. Next, find the line that says <Connector port="SomeNumber" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
and change SomeNumber to your Tomcat connector port.
Save the file, and go back to your home directory (and it has to be your home directory, even if you're putting everything else in a subdirectory). We're going to edit a hidden shell script called .bashrc
. So type in pico -w .bashrc
(note the period!) and add the following lines to the end.
JRE_HOME=/u/username/jdk1.8.0_11
export JRE_HOME
CATALINA_HOME=/u/username/apache-tomcat-7.0.54
export CATALINA_HOME
CLASSPATH=.:$CATALINA_HOME/lib/servlet-api.jar
export CLASSPATH
Exit and save. Since we changed it, we need to run this shell script.
source .bashrc
Now start Tomcat to make sure it works.
~/apache-tomcat-7.0.54/bin/startup.sh
Open a web browser and go to the site http://silo.soic.indiana.edu:ConnectorPort
. This is your Tomcat connector port, not the server port.
It should work, but we don't have access to the manager app because our installation has not managers. Let's fix that.
Shut Tomcat down. Then edit the users configuration file.
~/apache-tomcat-7.0.54/bin/shutdown.sh
pico -w edit ~/apache-tomcat-7.0.54/conf/tomcat-users.xml
Find the Tomcat Users section (between the tags <tomcat-users> and </tomcat-users>) and add the following line, putting in the username and password you want to use for Tomcat.
<user username="username" password="password" roles="manager-gui"/>
Exit and save. Then start up Tomcat again, access the web page, and click on the manager app button. Hopefully you can now log in. Go back to the main page and click on "Examples" to see if it's working properly with the JRE we just installed.
A servlet is a web application written in Java and that runs on the server. This is different from an applet, which runs on the user's computer. With a servlet, all the user sees is a web page written in HTML. All the computation happens invisibly on the server.
To create a servlet to be served up by Apache Tomcat, we first need to create a context for the servlet to run in. Head to the webapps
subdirectory (which is a lot like the htdocs
subdirectory for Apache) of the Tomcat installation and create a directory called greeter
. Our "app" is just going to be a simple Hello World app that serves a static web page.
cd $CATALINA_HOME/webapps
mkdir greeter
cd greeter
You don't have to use the script variable $CATALINA_HOME
, but I used it here just to demonstrate how you can use the variables we defined in .bashrc
.
This directory greeter
forms the context for the web app we're about to create. If you put any html files in here, they'll appear on your web page. But this isn't where we'll put the Java files because we don't want the users to be able to see them directly. So we create a subdirectory named WEB-INF
, and give it two subsubdirectories named classes
and lib
.
mkdir WEB-INF
mkdir WEB-INF/classes
mkdir WEB-INF/lib
The classes
directory is where we'll put the compiled Java classes to run our servlet. The lib
directory is where we'd put any extra Java packages or modules that we'll need to run our page (we don't have any of those right now). We'll also put a special .xml
file here in WEB-INF
to tell Tomcat where to find the servlet code, what to call it, and what URL's should call it up.
Let's write the servlet class now. We can write the source code anywhere, as long as we put the compiled .class
files into the classes
directory. I'm going to create the .java
source code file in there too, so I don't have to move the .class
file over after I compile it. So make a file called GreeterServlet.java
and put this (or something similar) in the file:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class GreeterServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
PrintWriter w = response.getWriter();
response.setContentType("text/html");
w.println("<html><head><title>Hello</title></head><body>");
w.println("<h1>Hello!</h1>");
w.println("</body></html>");
}
}
Some of this should look familiar, and some of it is probably new. But let's go through it to make sure it's clear what's going on.
Let's start at the top with the packages we imported. We need java.io
to create the PrintWriter
and to deal with IOExceptions
. The package javax.servlet
defines things for servlets in general, including the ServletException
error. And javax.servlet.http
gives the specifics for HTTP servlets, including the classes HttpServlet
, HttpServletRequest
, and HttpServletResponse
.
We want our servlet to be a subclass of HTTP servlet, we say that GreeterServlet extends HttpServlet
.
Now we're not going to run this class directly from the command line or anything, so we don't need to have a main()
function. The Tomcat server waits for a user to request a web page. If the user's browser requests a URL that we've told Tomcat about*, then it calls up the appropriate servlet and accesses it using the appropriate servlet method. Most of the time (when a URL is submitted using the GET method, that appropriate method is the doGet()
method. If the web page uses a form that specifies the POST method, then the doPost()
method should be called instead. Since GET is the default method for most websites, we've only written rules for doGet()
.
*We haven't told Tomcat anything about this yet. That's what the web.xml
file will do, when we define it in a few minutes.
doGet()
doesn't return anything, but it does take two special arguments: a request object (of type HttpServletRequest
) and a response object (of type HttpServletResponse
). The request object contains information and methods related to the request sent from by the browser. Of particular interest is the getParameter()
method, which allows us to get the value of an environment variable. But that's not something we'll need to worry about (until today's Lab, anyway).
The response object contains information and methods related to sending information back to the browser. The most important response method for us right now is getWriter()
, which returns a PrintWriter
object that we can use to send our output to the browser, just as if we were writing to a file or to System.out
. In fact, getting that PrintWriter
and giving it a name (w
, in this case) is the first thing we did in the body of the method. We also used the response method setContentType()
to let the browser know to expect the coming information to be defining an HTML web page. Notice how this differs from when we used PHP (where it was already assumed that this was an HTML file) and Python (where we made sure that the first printed line contained that information).
Speaking of PrintWriter
objects, you'll remember from yesterday's lecture and homework assignment that we always have to account for the possibility of an input/output exception. The same is true here, only we also have to worry about the possibility of a servlet-related exception too. Fortunately, we don't have to worry too much. Tomcat knows how to handle those kinds of exceptions gracefully, so all we have to do is acknowledge that the errors are possible and whenever they appear, doGet()
just passes them along up the line to Tomcat. That's why "throws IOException, ServletException
" appears way up in the declaration for the method doGet()
.*
*Note that throws
is completely different tan throw
. The keyword throws
shows up in the declaration of the method to indicate that any exceptions that happen to appear should just be passed along to the function that called the method. On the other hand, the keyword throw
is placed inside of a method definition when we want to create a new exception.
The rest of the code is just "printing" the HTML code for the page we want to be displayed. Feel free to change this part of the program to display something else, if you like.
Now that we've written the servlet, we just need to compile it, and to tell Tomcat what to do with it. Compile the file as usual (javac GreeterServlet.java
), and then go back up to the WEB-INF
directory and create a file named web.xml
. Put the following contents into that file.
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app>
<servlet>
<servlet-name>Greeter</servlet-name>
<servlet-class>GreeterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Greeter</servlet-name>
<url-pattern>/hello.html</url-pattern>
</servlet-mapping>
</web-app>
We've seen XML files before, but we haven't really talked about them. XML is a standard for storing data in a text format. You can probably see lots of similarities to HTML. That's because properly written* HTML is a special kind of XML. XML doesn't describe what most of those tags (like <web-app><...web-app> or <br/>) mean, but it does tell you how to format them. (It also describes what comments look like, and what that <?xml ... ?> header means.) The details of what <web-app> and <servlet> mean are determined by Tomcat.
*Web browsers are really lazy about whether HTML is properly written or not. For example, you can get away with leaving some tags open (for example, many people use <p> to begin a new paragraph without ending the previous paragraph with </p>). And XML dictates that stand-alone tags (like ) are supposed to have a slash before they close off the angle brackets, but you can usually leave them out of an HTML file and everything will display just fine.
In any case, all this complicated-looking XML file is telling us is that we're defining a thing called a web-app
, and that web-app
has something called a servlet
and something called a servlet-mapping
. The servlet
has a servlet-name
and a servlet-class
. The servlet-mapping
also has a servlet-name
and also a url-pattern
. That's all the XML tells us (besides the fact that this is XML version 1.0, using the standard ISO-8859-1 text encoding).
Now here's what Tomcat does with that information. The servlet definition tells Tomcat that we have a servlet defined by the GreeterServlet
class and that we want to call it /greeter/hello.html
, it should run the servlet named Greeter
. Actually, web.xml
just gives it the /hello.html
part. It knows about the /greeter
part because these files are all in the greeter
subdirectory of webapps
.
As soon as you create and save the web.xml
file, Tomcat will be ready to intercept any URL requests that match the URL pattern defined in that file. It will send those requests to the Java servlet we defined. However, any time we recompile that servlet, we need to let Tomcat know to reload it. There are a number of ways of doing this. One would be to shutdown and restart Tomcat. But it's easier to use the manager app on the main web page. Go to http://silo.soic.indiana.edu:ConnectorPort
and open the "manager webapp". Log in with the username and password we created for Tomcat, and look for the the web app with Path /greeter
. Click on the "Reload" button for that app to reload everything there. If the "Reload" button isn't clickable, then there's probably a typo in your web.xml
file.
After reloading the servlet, we can now test it out. Send your browser to http://silo.soic.indiana.edu:ConnectorPort/greeter/hello.html
and see the fruits of your labor!