Monday, October 31, 2005

Configuring Apache 2 and Tomcat 5.5 with mod_jk

Update May 15th 2007

If you're interested in setting up Apache virtual hosts with Tomcat 5.5 and mod_jk, check out my recent blog post on that subject.

I recently went through the painful exercise of configuring Tomcat 5.5 behind Apache 2 using the mod_jk connector. I had done it before with mod_jk2, but it seems that mod_jk2 is deprecated, so I wanted to redo it with the officially supported mod_jk connector. Although I found plenty of tutorials and howtos on Google, they all missed some important details or were not exactly tailored to my situation. So here's my own howto:

Step 1: Install Apache 2

I won't go into many details, as this a very well documented process. I installed httpd-2.0.55 and I used the following configuration options:

./configure --enable-so --enable-mods-shared=most

In the following discussion, I will assume that Apache 2 is installed in /usr/local/apache2.

Step 2: Install JDK 1.5

In my case, I put the JDK files in /usr/local/java and I added this line to root's .bash_profile file:

export JAVA_HOME=/usr/java/jdk1.5.0_05

Step 3: Install Tomcat 5.5

Download apache-tomcat-5.5.12.tar.gz and put it in /usr/local. Unpack the package, create tomcat user and group, change ownership:

# cd /usr/local; tar xvfz apache-tomcat-5.5.12
# ln -s /usr/local/apache-tomcat-5.5.12 /usr/local/tomcat
# groupadd tomcat; useradd tomcat -g tomcat -d /usr/local/tomcat tomcat
# chown -R tomcat.tomcat /usr/local/apache-tomcat-5.5.12 /usr/local/tomcat

Modify .bash_profile for user tomcat and source it

Become user tomcat and modify .bash_profile file by adding following lines:

export PATH=$PATH:/usr/local/bin:/usr/local/tomcat/bin
export JAVA_HOME=/usr/java/jdk1.5.0_05
export CATALINA_HOME=/usr/local/tomcat

$ . ~/.bash_profile

Test starting/stopping the Tomcat server

Try to start up tomcat by running startup.sh (it's in bin subdir, should be in PATH)

If you do ps -def | grep tomcat you should see something like:

tomcat 18591 1 88 06:40 pts/0 00:00:02 /usr/java/jdk1.5.0_05/bin/java -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.endorsed.dirs=/usr/local/tomcat/common/endorsed -classpath :/usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/commons-logging-api.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start

Try to shut down tomcat by running shutdown.sh (it's in bin subdir, should be in PATH)

If you do ps -def | grep tomcat you shouldn't see the above process running.

Step 4: Install the mod_jk connector

Download jakarta-tomcat-connectors-1.2.14.1-src.tar.gz and unpack it, then configure and build it:

# cd jakarta-tomcat-connectors-1.2.14.1-src/jk/native
# ./buildconf.sh
# ./configure --with-apxs=/usr/local/apache2/bin/apxs
# make; make install

Verify that mod_jk.so is in /usr/local/apache2/modules and is chmod 755.

Step 5: Connect Tomcat to Apache

Create workers.properties file in /usr/local/apache2/conf with following contents:

#
# This file provides minimal jk configuration properties needed to
# connect to Tomcat.
#
# We define a worked named 'default'
#

workers.tomcat_home=/usr/local/tomcat
workers.java_home=/usr/java/jdk1.5.0_05
ps=/
worker.list=default

worker.default.port=8009
worker.default.host=localhost
worker.default.type=ajp13
worker.default.lbfactor=1

Edit httpd.conf and add the following mod_jk-specific directives (I added them just before the start of Section 3 / Virtual Hosts).

Important note: the name of the worker defined in the workers.properties file ('default' in this example) needs to be the same as the worker that appears in httpd.conf in the JkMount lines. Also note that the JkMount lines below only map the two sample JSP/servlet applications that ship with Tomcat. You need to add similar lines for your custom application.


#
# Mod_jk settings
#
# Load mod_jk module
LoadModule jk_module modules/mod_jk.so
# Where to find workers.properties
JkWorkersFile conf/workers.properties
# Where to put jk logs
JkLogFile logs/mod_jk.log
# Set the jk log level [debug/error/info]
JkLogLevel debug
# Select the log format
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
# JkOptions indicate to send SSL KEY SIZE,
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
# JkRequestLogFormat set the request format
JkRequestLogFormat "%w %V %T"
# Send JSPs for context /jsp-examples to worker named default
JkMount /jsp-examples/*.jsp default
# Send servlets-examples to worker named default
JkMount /servlets-examples/* default

Keep editing httpd.conf and add following Alias directives (for example under the entry for the icon Alias). These directives tell Apache to map /jsp-examples and servlets-examples to the sample directories that ship with Tomcat.

# Static files in the jsp-examples webapp are served by apache
Alias /jsp-examples "/usr/local/tomcat/webapps/jsp-examples/"

Options FollowSymLinks
AllowOverride None
Allow from all


# The following line prohibits users from directly access WEB-INF

AllowOverride None
deny from all


# Static files in the servlets-examples webapp are served by apache
Alias /servlets-examples "/usr/local/tomcat/webapps/servlets-examples/"

Options FollowSymLinks
AllowOverride None
Allow from all


# The following line prohibits users from directly access WEB-INF

AllowOverride None
deny from all


Restart Apache via /etc/rc.d/init.d/httpd restart

Test standalone Tomcat server by going to http://Web_server_name_or_IP:8080

Test Apache/Tomcat integration by going to http://Web_server_name_or_IP/jsp-examples and http://Web_server_name_or_IP/servlets-examples

That should be it. At least it did the trick for me. In future posts I'll cover Tomcat clustering/session replication and some tips for tuning Apache/Tomcat.

Helpful articles/howtos/tutorials:

A. Ramnishath's Knowledge Base: Configuring AJP1.3 Connector for Tomcat
Jakarta Tomcat Connector -- Apache Howto
JSP Quick-Start for Linux

55 comments:

Anonymous said...

Thanks for posting this!! I've never used Tomcat before, and these instructions were great. Everything worked on the first try.

(BTW, you might want to remind people to run "restart.sh" at the same time they Restart Apache in Step 5.)

Thanks again!!

--Mike

Anonymous said...

looks like a nice article... does anyone know of one to connect apache 2 and tomcat 5.5 on a windows machine? feel free to email me kewlken6@hotmail.com

Anonymous said...

Thank you for your post! I was trying to follow apache's instructions for apache2,tomcat 5.0, and mod_jk for windows and failing miserably.

After following yours and adapting it for windows, I was able to get the server up and kicking within minutes.

Anonymous said...

Same as the others. Tried lots of other how-to's on the web, but none of them got me going until I came across yours.

THANK YOU, THANK YOU, THANK YOU!!

Anonymous said...

Mate, very helpful. You made me laugh with the "painful" comment. Its true...i was going in circles using Apaches own docs until I found your page. Only a few more configurations and I can maybe actually start coding :). This works on Windows too for others.

Cheers again.

Grig Gheorghiu said...

No idea about how to configure PUT methods....maybe some other people reading this page will have ideas.

Grig

Anonymous said...

Any idea how to get this configuration to work with the PUT request method? Apache does not support it out of the box and I was wondering if it could be forwarded through mod_jk.

Anonymous said...

I got it working, but shouldn't there be directory tags surrounding the
Options FollowSymLink
AllowOverride None
Allow from all
under Alias /servlets-examples "/usr/local/tomcat/webapps/servlets-examples/?

Grig Gheorghiu said...

You're right, there should be directory tags in the apache directives. It's just that the Blogger editor doesn't like HTML tags and it silently eliminates them when it shows the post....

Anonymous said...

Thank You very much, but...

I am very sorry for asking stupid questions, but I can`t ask another any more...

How must I change those configuration settings to be able to do such thing:
place file like C:/sites/my_virtual_host_N/www/my_file.jsp and view them in http://my_virtual_host_N/my_file.jsp.

Actually, I want them to behavior like PHP files, with possibility to use JSP.

Anonymous said...

Grig Rocks

Anonymous said...

Fantastic instructions! Thank you.
Would you please include instructions how to have the tomacat service startup on boot (add to chkconfig for startup and service restart)
Thanks again!

Anonymous said...

You idiot! After 2 hours I realized that your configuration files misses the <directory> tags.

Grig Gheorghiu said...

I used to have directory tags in there, but the angle brackets have been stripped by the Blogger editor. So thanks for pointing it out. It didn't seem to stop other people from getting it to work though :-)

Anonymous said...

Tip: instead of editing httpd.conf manually, you can use the Tomcat autoconfigure feature. It generates the appropriate section to be Included in httpd.conf, including all context root mappings.

I saw a pretty good discussion of this at http://www.howtoforge.com/apache2_tomcat5_mod_jk

-- Zwets

Anonymous said...

i tried this a million times and it does not work for me. i think apache is not sending 8080 stuff to tomcat. how can i debug this on apache side. debuggin on tomcat side is useless as 8009 recieves nothing. telnetting to 8009 works fine.

email addres jkoorts at gmail.

Anonymous said...

Thank you so very much.

Anonymous said...

Excellent article!!! After struggling for countless hours got it working with the help of this article!!

Cheers!
-Parvinder Bhasin

Anonymous said...

The article helped me to get things running. Good example. Directory tags are indeed needed. Too bad you didn't mention it, but hey, you won't hear me complaining :)

Anonymous said...

Great tutorial, but whne I restart Apache 2, I get this error ...

Syntax error on line 448 of /usr/local/apache2/conf/httpd.conf:
AllowOverride not allowed here

Complaining about the commented line

Alias /jsp-examples "/usr/local/tomcat/webapps/jsp-examples/"

Options FollowSymLinks
# Complains about "AllowOverride"
AllowOverride None
Allow from all

Anonymous said...

1 question. I've been trying to do this for several days with no effect..

Is there a way to browse files using apache2 thoug server and when selecting *.jsp file (wherewer it is) make Tomcat compile it and show..? I managed to compile files that were in webapps dir or ROOT and tried some things so i wouldn't have to write http://localhost:8080 and so on but it fails..i'd be really happy if someone there could help me with it. mail testament777(at)gmail.com

Anonymous said...

http://ramnishath.blogspot.com/2006/05/configuring-ajp13-connector-for-tomcat.html

Anonymous said...

Great Dog funiture Hi, found a great site, has all breeds and made in the USA.

Anonymous said...

Thanks a lot for the tutorial. It worked great for me. I set it up on a Mac. It only took about a half hour. You can check out my blog at
http://www.surfssl.com
. I have a tutorial on using SSH as a socks proxy.

Anonymous said...

Wonderful HowTo, Thanks a lot

Anonymous said...

Very good HowTo,
thank you very much

Unknown said...

In your step 4, there isn't a /bin folder under my /var/apache2. If I use /var/apache2/support/apxs, the ./configure command will come back with error saying can't find the file /var/apache2/support/apxs. So I eventually use:
./configure --with-apxs=/usr/sbin/apxs
It works. but when I come to "make; make install", I got the following error:

Copying files to Apache libexec Directory...
/bin/sh ../libtool --mode=install /bin/cp mod_jk.la /etc/httpd/libexec/mod_jk.so
/bin/cp .libs/mod_jk.so.0.0.0 /etc/httpd/libexec/mod_jk.so.0.0.0
/bin/cp: cannot create regular file `/etc/httpd/libexec/mod_jk.so.0.0.0': No such file or directory

It seems that it does not finding the right folder for my apache2. Any one can help?

Grig Gheorghiu said...

What happens if you run

./configure --with-apxs=/var/apache2/support/apxs

You may also want to google for how to build mod_jk on your particular Unix flavor.

Grig

Unknown said...

Grig:

It is so nice to hear from you!!! :)

In the step 4, when I run
./buildconf.sh
I got something like:
configure.in:177: warning: AC_TRY_RUN called without default to allow cross compiling
configure.in:178: warning: AC_TRY_RUN called without default to allow cross compiling
automake -a --foreign --copy
configure.in: 8: `automake requires `AM_CONFIG_HEADER', not `AC_CONFIG_HEADER'
autoconf
configure.in:177: warning: AC_TRY_RUN called without default to allow cross compiling
configure.in:178: warning: AC_TRY_RUN called without default to allow cross compiling

And when I run:
./configure --with-apxs=/var/apache2/support/apxs

I got the error:
checking for perl... (cached) /usr/bin/perl
could not find /var/apache2/support/apxs
configure: error: You must specify a valid --with-apxs path
[root@nexant-pl native]# ls -l /var/apache2/support/apxs
-rwxr-xr-x 1 root root 22597 Jun 3 09:45 /var/apache2/support/apxs

As you can see, even apxs indeed exists, but the configure process still complains about it.

One of the readers in your article suggests another article, which recommend to download and install apxs2 from www.debian.org. But I don't know how to install the package after I download the file with extension .deb. Do you have any clue? Or can you point me to a link that I can download the same installation file of Apache as you do which contains the /bin/apxs. I would appreciate it.

Unknown said...

Actually I know my problem. It is because my server misses "apxs" for Apache 2. I don't know why the apache 2.2.4 or 2.0.59 version does not come with /bin/apxs. Can anyone tell me where to download an Aapache 2 version which comes with apxs?

I did a lot of search today and find a way to download the package apache2-thereaded-dev and install the APT-GET software on my REDHEAD linux. But when I install the package, I got the following error:

[root@nexant-pl ebby]# ls *.deb
apache2-threaded-dev_2.0.54-5sarge1_i386.deb
apache2-threaded-dev_2.2.3-4+b1_i386.deb
apache2-threaded-dev_2.2.3-4_i386.deb
apache2-threaded-dev.deb
[root@nexant-pl ebby]#
[root@nexant-pl ebby]# apt-get install apache2-threaded-dev
Reading Package Lists... Done
Building Dependency Tree... Done
E: Couldn't find package apache2-threaded-dev
[root@nexant-pl ebby]#

Can anyone tell what did I do wrong?

Grig Gheorghiu said...

Jenny -- here's a post that explains how to install .deb files:

http://www.newlinuxuser.com/howto-use-dpkg-to-install-deb-files/

Unknown said...

Grig:

I still did not get through my problem because Redhat does not has dpkg. I search the web but can't find a file to allow me install dpkg to Redhat.

Would you please tell me the URL where you download your APACHE 2.0.55? It seems that your apache2 does come with apxs in its /bin folder. As I mentioned, I download both apache 2.2.24 or 2.0.59, either them come with apxs2.

Thank you very much.

Grig Gheorghiu said...

Jenny -- you can search for apache rpms at rpmfind.net:

http://rpmfind.net/linux/rpm2html/search.php?query=apache&submit=Search+...

Once you download an RPM that's suitable for your RH distro, install it with

rpm -hi rpmname.rpm

Grig

Unknown said...

Grig:

I finally find a RPM package with apxs in it. And I install the package successfully in my server. [root@nexant-pl man8]# rpm -ql apache2-devel | grep apxs2
/usr/sbin/apxs2
/usr/share/man/man8/apxs2.8.gz

However, I don't know if I need to do "Make" or "make install" in order to make apxs2 take effort. I check by typing >man apxs2, it does not come up. And I do the following in the JK connector folder:
./configure --with-apxs=/usr/sbin/apxs2

and get the same error :
could not find /usr/sbin/apxs2
configure: error: You must specify a valid --with-apxs path

Do you know if I miss anything to make the apxs2 takes effort in my server?

Grig Gheorghiu said...

Not sure what's going on with your configuration. You may want to try installing mod_jk from an RPM:

http://rpmfind.net/linux/rpm2html/search.php?query=mod_jk&submit=Search+...

Rajeesh V said...

I did it everything . I also got the connection, but I can only load pages which are static. I can't load jsp pages

Anonymous said...

Hi,
First of all thanks so much for helping us get through the pain of configuring Apaceh2 and Tomcat 5.5 with mod_jk. However I am running into certain issues.

1. I am having a apache loadbalancer in place and I am using ssl. My ssl.conf file has the necessary ssl parameters. Now the issue I am actually facing is:
Say the name of my application is ABC which is placed under /opt/tomcat/webapps/ABC.

The ssl.conf file has following entries in Virtual Hosts section:

DocumentRoot "/opt/static" #Static content is served from here.

JKMount /ABC loadbalancer
JKMount /ABC/* loadbalancer

Now when I type https://ip-address/ in the browser, then the welcome page defined in web.xml of ABC application gets displayed (this is a login page). When I enter the username and press submit ideally /ABC/login.do should be called. However when i checked the apache logs, it showed that /login.do was called instead of /ABC/login.do. Basically this request was not forwarded to tomcat.

However this works well when I enter https://ip-address/ABC in the broswer. Following this all calls are made in the proper way. i.e /ABC/login.do was called.

2. I am no getting any entries in mod_jk.log, Like the worker was looked up and stuff.

3. I have another application PQR in webapps. I have configuerd this application on another ip-address on the same machine.
There is another virtual host entry for this :

However when i try to access the application on this ip-address, the other applictaion ABC gets displayed. However if I type

https://ip-address2/PQR then this applictaion works fine.

Request you guys to help me sort this out.

Thanks in advance.

Anonymous said...

Thanks for posting this wonderful article.
I found tomcat jsp examples if I only added "Alias" part(of course with directory tag) into the httpd.conf.
I don't know what is wrong? why I don't even need mod_jk.so.

Thanks,

ray

Vivek Bhandarkar said...

hello there .........
really a nice tutorial that u have written... .above........


as the steps u have written.........
i have done all the configuration..........

as u have written in the documentation ........that static content is served by the apache it is gettting served .......
and jsp content is getting server by the tomcat using connector.......

but in case of jsp files the tomcat is showing the 404 error.......
i know what this error exctly means...........

but the the jsp files that i am looking for are already present at that location...........

Anonymous said...

has anyone try to have apache and tomcat in two different machine?

Grig Gheorghiu said...

dbspace -- to point apache to a tomcat instance on a different machine, you need to specify that machine in your workers.properties file.

Example:

worker.app2.port=8010
worker.app2.host=remote-host
worker.app2.type=ajp13
worker.app2.lbfactor=1

In this case, worker app2 is directed to remote-host.

HTH,

Grig

Anonymous said...

Thanks a lot. It worked for tomcat6 too.

Suraj Chattar said...

Nice article but if you still have problem running your java applications on apache2 with mod_jk connector just make a slight change..viz, use ajp13 worker rather than default, ajp12. good luck.

Anonymous said...

Thank you so much. Was going thru so much pain trying to get tomcat to work on apache server until I ran into your how-to. Thanks.
Tilak

MishaDar said...

Straight, Forwarded and Focused.

Short comment thought:

In case U're using Virtual Host tags then the following will not work for U:
Test Apache/Tomcat integration by going to http://Web_server_name_or_IP/jsp-examples and http://Web_server_name_or_IP/servlets-examples

Assuming that
Web_server_name_or_IP = Your_Virtual_Host_Name

To make it happen U need to place JkMount lines within Virtual_Host derectives tags.

Asad Sheikh said...

The above examples will serve the static content, not dynamic content

eg. Alias /jsp-examples "/usr/local/tomcat/webapps/jsp-examples/"

To get the static content, you don't even need to configure mod_jk

Anonymous said...

Great Post!!! I used the same approach and posted it at:

http://vladi-blog.blogspot.com/

There you can find other issues on Apache, Tomcat, and other technical issues.

Avrono said...

Hi Grig,
Great post, after a little effort I managed to get it working with Tomcat on port 8080. I have another server running Tomcat on port 80 and can't figure out how to get the right port for the worker. After a netstat -anp, I am non-the-wiser, any ideas ?

Prakash said...

great post...thanks a lot..Keep posting...

Anonymous said...

you are the DON ... after hours with no luck your article hit the spot ... first time i have ever left a post ... well done

Manoj said...

Thanks for such a nice Blog. I install Apache httpd 2.2, tomcat 6.0. I installed apache as root user and tomcat as tomcat user. I downloaded tomcat-connectors-1.2.28-src. Now i m trying to configure it as a tomcat user, but unable to configure it. getting error " cp: cannot create regular file `/usr/local/apache2/modules/mod_jk.so': Permission denied
"
Is there any way to configure it as tomcat user or do i have to configure it as root.

Please advice.

Thanks
Manoj

Jackie said...

for me, its three part configurations,
1. apache, to load mod_jk.so, forward request to workers
2. tomcat, the worker connect to tomcat ajp1.3 connector port, so that tomcat would be notified of the forwarded request.
3. especially import, the worker port should be same as tomcat ajp1.3 connector port.

Unknown said...

Thank you..this worked like a dream..

but applications seem to be accessible from tomcats port as well.. how can i block that.

i just want the applications to be accessed from apache(port).

btw both tomcat and apache are on same unix server.

Anonymous said...

using apache2.2.17,mod_jk_1.2.30,tomcat5.5.27..
mo norma LB working fine.... i want 2500 concuurent request to handle..What all i have to configure at apache and tomcat ?

Anonymous said...

Great tutorial,

Its very use full tutorial for me thanks very much..

Modifying EC2 security groups via AWS Lambda functions

One task that comes up again and again is adding, removing or updating source CIDR blocks in various security groups in an EC2 infrastructur...