EzyHTTP How to Use Tomcat
Updated at 1784045714000EzyHTTP 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
| Property | Default | Meaning |
|---|---|---|
server.port | 8080 | Main HTTP port. |
server.host | 0.0.0.0 | Host address bound by Tomcat. |
server.max_threads | 16 | Maximum Tomcat connector worker threads. |
server.min_threads | 4 | Minimum spare worker threads for the main server. |
server.idle_timeout | 150000 | Used for session timeout, connection timeout, and keep-alive timeout. |
server.context.path | JVM temp directory | Base directory used when creating the embedded Tomcat context. |
server.max_request_body_size | 2MB | Applied to Tomcat maxPostSize and maxSwallowSize. |
server.multipart.location | JVM temp directory | Temporary directory for multipart upload files. |
server.multipart.file_size_threshold | 1MB | Size threshold before multipart content is written to disk. |
server.multipart.max_file_size | 5MB | Maximum size for one uploaded file. |
server.multipart.max_request_size | 5MB | Maximum size for the whole multipart request. |
server.compression.enable | true | Enables Tomcat response compression. |
server.compression.min_size | 32B | Minimum response size before compression is applied. |
cors.enable | false | Adds Tomcat's CORS filter to all paths when enabled. |
cors.allowed_origins | * | Allowed CORS origins. |
cors.allowed_headers | * | Allowed CORS request headers. |
management.enable | true in the Tomcat bootstrap field | Starts a second embedded Tomcat server for management traffic when enabled. |
management.host | 0.0.0.0 | Host address for the management server. |
management.port | 18080 | Port 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
| Problem | What to check |
|---|---|
| Application starts with the wrong embedded server | Remove the default boot dependency or register only one application bootstrap. |
| No application bootstrap found | Make sure TomcatApplicationBootstrap is registered through @ComponentClasses or passed as a component class when building the application context. |
| Controller returns 404 | Confirm the controller package is included in the application scan. |
| Multipart upload fails | Check server.max_request_body_size, server.multipart.max_file_size, and server.multipart.max_request_size. |
| CORS does not work | Set cors.enable=true and configure allowed origins and headers. |
| Management port is open unexpectedly | Set 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.