Integrating Tomcat Web Services With Our Site

As we saw earlier, Tomcat will generally be hosted on a different port from your main web site. In other words, you will have two web servers running on the same machine at the same time with one hosting Tomcat on one port; and the other hosting Apache on the standard web ports.

So what’s the big deal you might ask?  There are several problems with this outside of our development world; but here are the top two:

  • Let’s say that we have Tomcat running on port 8080 and our Apache web site running on port 80.  We could serve up content from our port 80 and have the javascript/ajax code we write make the requests to our server on port 8080 but we’d then have a problem with the cross-domain security issues that browsers implement to protect us.  In other words, the browser in general won’t allow this to happen.  Yes, we could roll out JsonP to get around the cross-domain issues.  However, we’d have another problem:  typical network security.
  • Many corporate firewalls will block all traffic to and from the Internet except for web traffic over the standard web ports: 80 and 443.  If we attempted to make the web service call to our Tomcat server over port 8080 even using JsonP, we’d be blocked at the firewall and our web service call would fail.

One solution we might want to deploy is to just use the Tomcat application server for both our web services and static content.  We could do that; however, the Tomcat platform is not as robust as Apache and this is not an ideal solution.  We should use the right tools for the job.

This lesson will provide a recipe for how we can configure a proxy so that our primary web site can run under Apache web server; and Tomcat, our application layer, will run it’s own web services on a different port on the same server.

To make this interesting, we’ll build an actual solution using this framework beginning in the next chapter.  This will be a great transition as we now move to Chapters and Lessons showing how to build solutions using our web platform.

To get a taste of what’s in store, let me describe the requirements for my new site which will use the new integrated web services layer we are configuring:

The Requirements

We want to offer a web page that will let our visitor see current weather data for their particular location.  That is, we will retrieve some great weather information from The Weather Underground’s web API.

I have signed up for the free developer level and the folks at the Weather Underground allow me and my visitors to make a few web service calls each day; but, if I exceed that count then I have to pay for the requests.  Therefore, I have an interest in minimizing the number of requests made through my solution.

Weather Underground provides great information as to how to make their web service calls from JavaScript; but, JavaScript running in our clients’ browsers is wide open.  That means anyone could grab my API key and use it on their web site and I would have to pay for their web service calls.

To eliminate this problem, I will place all of the Weather Underground web service calls via my web services layer.  Therefore, my credentials (my API key) will not be visible to my web visitors since they won’t be directly involved in the requests..  Plus, I can “scrub” the returning data and combine it with other data.  For example, I don’t really want to burden my users by having them key in their location.  So why don’t I just use the location for their IP address and give them the Weather Underground for that location without asking?

So here’s what I want to build:

  • My users will come to a web page and see an immediate welcome banner.
  • As they read the welcome banner, the page will make an asynchronous web service request to my Tomcat web server.
  • The Java code on the web server will then make two web service calls.  The first will be to a web site that will use the caller’s IP address to tell me from which city the caller is located (or perhaps their VPN).  We will read the IP address from the request headers that the client has sent the server.  Then using that city, we will make a second web service call to Weather Underground to pull the current weather data for the city.
  • We need to limit the number of web service calls to each public web service and so we will not allow users to key in a different city.
  • To reduce the number of public web service calls, we’ll also cache the return values so that subsequent requests for the same city within a given time period will be served from our local cache and not from new/more web service calls.  This would also eliminate the possibility that someone could crank up our charges by hitting refresh over and over on our web page.

In the next lesson, I’ll walk through the code for this; but for now, let’s get our machine configured to provide an integrated web and web services platform on which we can build the solution.

Integrating Tomcat and Apache

In order to have our Apache serve up Tomcat web services, we’ll use the Reverse Proxy as described in the Apache docs here

Let’s use our Mint VM and take this step by step.

  1. Verify that Tomcat is running on port 8080.  In the browser on the VM, key in:  http://localhost:8080 and confirm that the Tomcat splash page is visible.  If not, you will need to change the port in the following steps to point to your Tomcat port.
  2. We’ll illustrate the steps using our http://mydevweb.local site which currently only hosts our splash page…”Success! The MyDevWeb.local virtual host is working!”
  3. We need to build our Web Application Archive (“WAR”) file from Netbeans.
    1. Open the Netbeans IDE and Clean and Build your project.  That is, right-click the SimpleWebService project name on the top left panel and select the Clean and Build option from there.
    2. Next, right-click again on the project and this time select the Deploy menu item.
    3. You should now see a dist option under the project.  Click to expand and there should be a brand new SimpleWebService.war file.
  4. Now let’s deploy it to Tomcat.
    1. Open the Tomcat splash page at http://localhost:8080 and click the button for the Manager app.
    2. Key in the username and password you set from this lesson:  admin password  (No, you would never do this outside your development box).
    3. Down in the WAR file to deploy, chose your new SimpleWebService.war file and then Deploy it.
    4. Let’s test it:
      1. From the Tomcat Manager, click on the /SimpleWebService link: 
      2. You should see our test web page asking for the mrn.  Key in 12345 and confirm that it’s wired up correctly … that you see the alert with the value of 7777
      3. Now, let’s call our web service directly.  If you look at the index.html file (either directly from Netbeans, or by selecting view source from the browser making the web service call), you will see that the url for our web service call is SimpleServlet.  This is the relative path to our web page but we need the full URL.  Let’s add that to our base to get: http://localhost:8080/SimpleWebService/SimpleServlet  You should see the warning about the mrn not being supplied.  You can play with this if you want.  Try:  localhost:8080/SimpleWebService/SimpleServlet?mrn=12345 and you should see the json result with our 7777 value
  5. Now that we have our web service up and running, let’s configure our proxy.  The first thing we need to do is to enable the proxy module in Apache.
    1. Execute the following command: sudo a2enmod proxy_http
    2. Open the site configuration file:  /etc/apache2/sites-available/MyDevWeb.local.conf
      1. We need to add the proxy information.  As per the Apache documentation referenced above, add the following two lines:
        ProxyPass  /SimpleWebService  http://localhost:8080/SimpleWebService/
        ProxyPassReverse  /SimpleWebService  http://localhost:8080/SimpleWebService/
        Your file should look like this:
        <VirtualHost *:80>
        ServerName MyDevWeb.local
        DocumentRoot /var/www/devweb/
        ProxyPass  /SimpleWebService  http://localhost:8080/SimpleWebService/
        ProxyPassReverse  /SimpleWebService  http://localhost:8080/SimpleWebService/
        </VirtualHost>
    3. We need to disable the original site and update with the current information:
      sudo a2dissite MyDevWeb.local.conf
      sudo a2ensite MyDevWeb.local.conf
      sudo service apache2 reload
  6. OK, I’m sure you are anxious to test, but it won’t work.  Try it:  from your VM browser, navigate to http://mydevweb.local/SimpleWebService and you will see our page; but when you key in a value, you get an error.  Press the F12 in the browser and you will see that you have a 404 error; not found.  What gives.  Well, we changed the URL and as you can see in the debugger, our path is not correct.  We need to change our javascript to fix the URL.  But this is OK for now, we’ll fix this in a minute but first, let’s confirm that the URL to our web service is correct.  Key in http://mydevweb.local/SimpleWebService/SimpleServlet?mrn=12345  and confirm that your web service is working using the new proxied URL.
  7. So let’s fix our web page.  In fact, we don’t want the web page in our web services layer at all.  Let’s just copy the file from /usr/local/apache-tomcat-8.0.27/webapps/SimpleWebService/index.html to the root of our web site at: /var/www/devWeb after we delete the existing index.html.  Here are the terminal commands we need to use
    sudo mv -v /usr/local/apache-tomcat-8.0.27/webapps/SimpleWebService/index.html /var/www/devweb/
    sudo chown -R www-data:www-data /var/www/devweb
    sudo chmod -R 755 /var/www/devweb
  8. Now, let’s fix our path problem.  Open the /var/www/devweb/index.html file and set the path in the Ajax call to the correct path.  You can use the full path, or we can just use the correct relative path.  The ajax line should look like: url: “SimpleWebService/SimpleServlet”,   or it could be complete at: http://mydevweb.local/SimpleWebService/SimpleServlet
Conclusion

We have configured our system to answer requests for both static content that is served by Apache web server and dynamic web service content that is served by our Tomcat Web Services layer on the same machine using a proxy.  Cool.  In the next lesson, we will code our test solution to show how well this all works.

Leave a Reply

Your email address will not be published. Required fields are marked *