EzyHTTP How to Use Tomcat

Updated at 1784045714000
EzyHTTP can run with an embedded Tomcat server. This is useful when you want EzyHTTP's controller model, request binding, response conversion, interceptors, and application context, but prefer Tomcat as the HTTP runtime instead of the default boot setup.
This guide shows the minimal setup for starting an EzyHTTP application on Tomcat, adding a controller, and tuning the most common Tomcat-related properties.

When to Use Tomcat

Use the Tomcat server module when your application needs an embedded servlet container backed by Apache Tomcat. EzyHTTP still handles routing and controller invocation. Tomcat handles the network connector, servlet lifecycle, multipart upload configuration, CORS filter registration, compression, and connection-level settings.
At runtime, the flow looks like this:
flowchart LR
    A[HTTP client] --> B[Embedded Tomcat connector]
    B --> C[EzyHTTP servlet]
    C --> D[Request arguments and body binding]
    D --> E[Controller method]
    E --> F[Response conversion]
    F --> G[HTTP response]

Add the Dependency

Add the Tomcat server module to your project:
<dependency>
    <groupId>com.tvd12</groupId>
    <artifactId>ezyhttp-server-tomcat</artifactId>
    <version></version>
</dependency>
The Tomcat module depends on the EzyHTTP server core module, so you can start the application through the core EzyHttpApplication API.

Use Tomcat with ezyhttp-server-boot

If your project uses ezyhttp-server-boot, exclude the default Jetty server module and include the Tomcat server module explicitly:
<dependency>
    <groupId>com.tvd12</groupId>
    <artifactId>ezyhttp-server-boot</artifactId>
    <version></version>
    <exclusions>
        <exclusion>
            <groupId>com.tvd12</groupId>
            <artifactId>ezyhttp-server-jetty</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>com.tvd12</groupId>
    <artifactId>ezyhttp-server-tomcat</artifactId>
    <version></version>
</dependency>
You can still start the application through the boot helper:
package com.example.app;

import com.tvd12.ezyhttp.server.boot.EzyHttpApplicationBootstrap;
import com.tvd12.ezyhttp.server.core.annotation.ComponentClasses;
import com.tvd12.ezyhttp.server.core.annotation.ComponentsScan;
import com.tvd12.ezyhttp.server.tomcat.TomcatApplicationBootstrap;

@ComponentsScan("com.example.app")
@ComponentClasses(TomcatApplicationBootstrap.class)
public class App {

    public static void main(String[] args) throws Exception {
        EzyHttpApplicationBootstrap.start(App.class);
    }
}
The key point is that ezyhttp-server-boot provides the convenient startup API, while TomcatApplicationBootstrap is the server runtime that EzyHTTP finds and starts from the application context. Excluding Jetty avoids having two embedded server bootstraps on the classpath.

Create the Application Entry

If you do not use ezyhttp-server-boot, register TomcatApplicationBootstrap and start through the core API. A simple application entry can look like this:
package com.example.app;

import com.tvd12.ezyhttp.server.core.EzyHttpApplication;
import com.tvd12.ezyhttp.server.core.annotation.ComponentClasses;
import com.tvd12.ezyhttp.server.tomcat.TomcatApplicationBootstrap;

@ComponentClasses(TomcatApplicationBootstrap.class)
public class App {

    public static void main(String[] args) throws Exception {
        EzyHttpApplication.start(App.class);
    }
}
EzyHttpApplication.start(App.class) scans the package of App, builds the application context, finds the registered application bootstrap, and starts the embedded Tomcat server.
If your controllers and services are in different packages, add a component scan:
package com.example.app;

import com.tvd12.ezyhttp.server.core.EzyHttpApplication;
import com.tvd12.ezyhttp.server.core.annotation.ComponentClasses;
import com.tvd12.ezyhttp.server.core.annotation.ComponentsScan;
import com.tvd12.ezyhttp.server.tomcat.TomcatApplicationBootstrap;

@ComponentsScan({
    "com.example.app",
    "com.example.feature"
})
@ComponentClasses(TomcatApplicationBootstrap.class)
public class App {

    public static void main(String[] args) throws Exception {
        EzyHttpApplication.start(App.class);
    }
}

Add a Controller

Controllers work the same way as they do with the other EzyHTTP server runtimes:
package com.example.app.controller;

import com.tvd12.ezyhttp.server.core.annotation.Controller;
import com.tvd12.ezyhttp.server.core.annotation.DoGet;
import com.tvd12.ezyhttp.server.core.annotation.RequestParam;

@Controller("/hello")
public class HelloController {

    @DoGet
    public String hello(@RequestParam String name) {
        return "Hello " + name;
    }
}
After starting the application, call:
GET http://localhost:8080/hello?name=Tomcat
The response body will be:
Hello Tomcat

Configure Tomcat

EzyHTTP reads configuration from application properties loaded by the application context. For a basic Tomcat setup, create application.properties in your resources:
server.port=8080
server.host=0.0.0.0
server.max_threads=32
server.min_threads=4
server.idle_timeout=150000

server.max_request_body_size=2MB
server.multipart.location=tmp
server.multipart.file_size_threshold=1MB
server.multipart.max_file_size=5MB
server.multipart.max_request_size=5MB

server.compression.enable=true
server.compression.min_size=32B

cors.enable=false
cors.allowed_origins=*
cors.allowed_headers=*

management.enable=false
management.host=127.0.0.1
management.port=18080

Important Properties

PropertyDefaultMeaning
server.port8080Main HTTP port.
server.host0.0.0.0Host address bound by Tomcat.
server.max_threads16Maximum Tomcat connector worker threads.
server.min_threads4Minimum spare worker threads for the main server.
server.idle_timeout150000Used for session timeout, connection timeout, and keep-alive timeout.
server.context.pathJVM temp directoryBase directory used when creating the embedded Tomcat context.
server.max_request_body_size2MBApplied to Tomcat maxPostSize and maxSwallowSize.
server.multipart.locationJVM temp directoryTemporary directory for multipart upload files.
server.multipart.file_size_threshold1MBSize threshold before multipart content is written to disk.
server.multipart.max_file_size5MBMaximum size for one uploaded file.
server.multipart.max_request_size5MBMaximum size for the whole multipart request.
server.compression.enabletrueEnables Tomcat response compression.
server.compression.min_size32BMinimum response size before compression is applied.
cors.enablefalseAdds Tomcat's CORS filter to all paths when enabled.
cors.allowed_origins*Allowed CORS origins.
cors.allowed_headers*Allowed CORS request headers.
management.enabletrue in the Tomcat bootstrap fieldStarts a second embedded Tomcat server for management traffic when enabled.
management.host0.0.0.0Host address for the management server.
management.port18080Port for the management server.

Multipart Uploads

Tomcat receives multipart settings through the servlet multipart configuration. If server.multipart.location is relative, EzyHTTP resolves it under the Tomcat context base directory. If the directory does not exist, EzyHTTP creates it before the servlet starts handling uploads.
For example:
server.context.path=/var/app/ezyhttp
server.multipart.location=uploads/tmp
server.multipart.max_file_size=20MB
server.multipart.max_request_size=25MB
This stores temporary multipart data under:
/var/app/ezyhttp/uploads/tmp
Use an absolute path when you want temporary upload files outside the context directory:
server.multipart.location=/mnt/data/upload-tmp

CORS

When cors.enable=true, EzyHTTP registers Tomcat's CORS filter for all paths:
cors.enable=true
cors.allowed_origins=https://example.com
cors.allowed_headers=Content-Type,Authorization
For local development, * is convenient. For production, prefer explicit origins and headers so browser access is limited to the clients you expect.

Compression

Tomcat compression is enabled by default in the bootstrap. You can disable it:
server.compression.enable=false
Or keep it enabled and raise the minimum response size:
server.compression.enable=true
server.compression.min_size=1KB
Size values such as 32B, 1KB, 2MB, and 20MB are parsed by EzyHTTP before they are passed to Tomcat.

Management Server

The Tomcat bootstrap can start a separate embedded Tomcat instance for management traffic:
management.enable=true
management.host=127.0.0.1
management.port=18080
This only gives you a separate management HTTP runtime. To expose actual management endpoints, include and configure the EzyHTTP management module in your application. In production, binding management to 127.0.0.1 or a private interface is usually safer than exposing it on 0.0.0.0.

Reverse Proxy Headers

The Tomcat bootstrap installs a remote IP valve that reads the X-Forwarded-Proto header. This helps the application understand whether the original request was HTTP or HTTPS when Tomcat is running behind a reverse proxy or load balancer.
Make sure your proxy sets the header correctly:
X-Forwarded-Proto: https

Shutdown

EzyHttpApplication.start(...) returns the running application instance. If you start EzyHTTP from tests or an embedded host process, keep the returned object and call stop() when you are done:
EzyHttpApplication application = EzyHttpApplication.start(App.class);

// later
application.stop();
Stopping the application destroys the application context, which also stops the Tomcat bootstrap.

Troubleshooting

ProblemWhat to check
Application starts with the wrong embedded serverRemove the default boot dependency or register only one application bootstrap.
No application bootstrap foundMake sure TomcatApplicationBootstrap is registered through @ComponentClasses or passed as a component class when building the application context.
Controller returns 404Confirm the controller package is included in the application scan.
Multipart upload failsCheck server.max_request_body_size, server.multipart.max_file_size, and server.multipart.max_request_size.
CORS does not workSet cors.enable=true and configure allowed origins and headers.
Management port is open unexpectedlySet management.enable=false when you do not need the management server.

Conclusion

Using Tomcat with EzyHTTP is mostly a matter of choosing the Tomcat server module and registering the Tomcat bootstrap. Your controllers, services, request parameters, request bodies, response entities, exception handlers, and interceptors continue to follow the normal EzyHTTP programming model, while Tomcat provides the embedded servlet runtime underneath.

Table Of Contents