If you’re running a Spring Boot application, it’s generally a great idea to set it up with an Apache Web Server front-end.

Why? Because a front-end web server offers the following benefits:

  • Better load-balancing for high-throughput applications
  • Speedier delivery of static content
  • Easier configuration of security features
  • Access to additional functions provided by Apache modules

Fortunately, it’s fairly easy to set up your Spring Boot application behind an Apache Web Server. In this article, we’ll go over how to do just that.

For the purposes of this tutorial, we’ll use Apache 2.4 with Spring Boot 1.5.4. Your configuration requirements may vary slightly depending on which versions of both projects you’re using.

 

It’s Just Tomcat

Before you get started, it’s important to keep in mind that a Spring Boot app is just a web app that’s packaged with an embedded Apache Tomcat Application Server. That means the process of setting up Tomcat to run behind an Apache Web Server is very similar to what you’ll see here.

Bottom line: there’s no need to over-complicate this.

Speaking of not complicating things, for the purposes of this tutorial, we’ll refer to the Apache Web Server as “Apache” and the Tomcat Application Server as “Tomcat.” Yes, even though they’re both Apache products, that seems like the best way to refer to both of them.

 

A Tale of 2 Protocols

When it comes to communicating between Apache and Tomcat, you have a couple of popular options: HTTP or AJP.

You’re probably already familiar with the HyperText Transfer Protocol (HTTP). It’s the protocol that web browsers use to access websites.

You might not be familiar with the Apache JServ Protocol (AJP). That’s a binary protocol designed to proxies requests from a web server to an application server.

Since Apache can communicate with Tomcat using either HTTP or AJP, which one should you use?

The answer to that depends on who you ask. Some people prefer HTTP because of its simplicity. Others prefer AJP because it offers performance improvements.

If you’re a forward-looking developer, you’re probably leaning towards performance over simplicity. In that case, you’ll choose AJP.

This tutorial will show you how to set up the Apache-Tomcat link with AJP.

 

Setting the Properties

Get the ball rolling by adding a couple of properties to the application.properties file.

1
2
ajp.port=9090
ajp.enabled=true

The first property specifies the port that Tomcat will use to listen for AJP connections. Be sure to select a port that’s not being used by any other application on your server.

In this case, the app will listen for connections on port 9090.

Next, there’s a property that enables you to turn off AJP connections easily. Right now, ajp.enabled is set to true because you want to listen for AJP connections.

That brings us to the next section.

 

Listening for AJP Connections

Let’s say your Spring Boot app is all finished and now you’re ready to deploy so that it runs behind Apache. In that case, your Spring Boot really isn’t finished.

Why? Because you have to write a little more code so that your app “listens” for AJP connections.

For that, you’ll need a new class. Call it ServerSetup.

Here’s the initial code for that class:

1
2
3
4
5
6
7
8
9
10
@Configuration
public class ServerSetup {
 
    @Value("${ajp.port}")
    int ajpPort;
 
    @Value("${ajp.enabled}")
    boolean ajpEnabled;
  
    ...

The class is annotated with @Configuration. That tells Spring the code returns one or more beans that will be managed by the container.

Next, the class references the properties values that you just created. Those will be used later on in the code.

Here’s what that the only method in the ServerSetup class looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Bean
public EmbeddedServletContainerFactory servletContainer() {
    TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
     
    if (ajpEnabled) {
        Connector ajpConnector = new Connector("AJP/1.3");
        ajpConnector.setPort(ajpPort);
        ajpConnector.setSecure(false);
        ajpConnector.setScheme("http");
        ajpConnector.setAllowTrace(false);
        tomcat.addAdditionalTomcatConnectors(ajpConnector);
    }
 
    return tomcat;
}

Here’s what that’s doing in a nutshell: it’s creating a new connector that will listen for AJP requests.

As you can see the code starts off by instantiating a TomcatEmbeddedServletContainerFactory with an empty constructor. Don’t let the long name intimidate you — that object is really just a factory that produces a Tomcat container.

The default connector for that Tomcat container listens for HTTP requests on port 8080. That’s exactly why your Spring Boot app does that by default.

However, you can configure the container to listen for other protocols on other ports. That’s what the rest of the code does.

It starts off by instantiating a new Connector object. As you can see, the constructor specifies the protocol as a String. In this case, that connector will use version 1.3 of the AJP protocol.

After that, the method sets several fields in the connector object. Pay particular attention to the port field. That’s set from the properties file.

Note that the code is also specifying an unsecured communications channel. That’s why it sets the scheme to “http” instead of “https” and sets the secure boolean to false.

One final point here: as you might have guessed the connector object corresponds to the <Connector> element in a standard Tomcat setup.

 

Redeploy

Once you’re done coding the new configuration, build and run your Spring Boot app. You should see that it’s listening for AJP requests on port 9090 in addition to your default port (which in this case is 8090):

org.apache.coyote.ajp.AjpNioProtocol : Initializing ProtocolHandler ["ajp-nio-9090"]
org.apache.coyote.ajp.AjpNioProtocol : Starting ProtocolHandler [ajp-nio-9090]
s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8090 (http) 9090 (http)

 

Configuring Apache

Now that your Spring Boot app is finally complete, it’s time to do some work on the Apache side.

Let’s say that you’ve registered a domain that you want to point to your Spring Boot app. In other words, when people type the name of your domain in their browser URL bar, you want them to visit your app.

You can make that happen with an Apache front-end.

It’s beyond the scope of this article to tell you how to set up Apache from scratch. For the purposes of this tutorial, it’s assumed that you have a working Apache server that listens for requests on port 80 (the standard HTTP port).

If you want Apache to communicate with Tomcat via AJP, you have a couple of options. You can use the mod_jk module or the mod_proxy_ajp module.

For the purposes of this tutorial, we’ll go with mod_proxy_ajp. That’s because it’s a relatively recent addition to the Apache family that makes it easy to use AJP.

To use the mod_proxy_ajp module, you’ll need to edit your httpd.conf file.

The good news is that you probably have a recent version of Apache that already has the line you need in the httpd.conf file, except it’s commented out. All you need to do is uncomment it.

Specifically, these are the lines you need in your httpd.conf file:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

 

Once you’ve added those lines, save your configuration file and restart Apache just to make sure there aren’t any problems.

 

Specifying the VirtualHost

You’re not quite done with the httpd.conf file yet. Edit it again and scroll down to where you’ve specified one or more <VirtualHost> elements. If you don’t have any yet, just scroll down to a point following all the LoadModule declarations.

Now, add the following lines:

1
2
3
4
5
<VirtualHost *:80>
    ServerName yourdomain.com
    ProxyPass         /  ajp://localhost:9090/
    ProxyPassReverse  /  ajp://localhost:9090/
</VirtualHost>

For starters, you should obviously substitute “yourdomain.com” for whatever your domain is.

That XML stanza is telling Apache to listen for connections to your domain on port 80. When it receives those connections, it acts as a proxy and forwards them, via the AJP protocol, to your Spring Boot web app which is running on port 9090.

Save the file and restart Apache. Then, use your web browser to visit the domain you specified in <VirtualHost>. You should go straight to your Spring Boot app.

 

Wrapping It Up

The Demos web application is a Spring Boot app that runs behind Apache. Visit the link to this setup in action.

Of course, that link also uses SSL. We’ll cover that in a future article.

Have fun!