Upgrading to Dropwizard 4.0.x: A Complete Migration Guide
When we began the journey to upgrade our backend application to Dropwizard 4.0.x, we anticipated changes—but the depth and breadth of the migration process exceeded our expectations. From embracing Jakarta EE, refactoring for Guice compatibility, solving subtle Jetty and Jackson issues, to adapting to Metrics 5 and OpenAPI, this post is a comprehensive walkthrough of what we learned and how we overcame the challenges.
Whether you’re preparing for your own upgrade or just curious about the process, this blog will help you navigate the migration confidently.
✨ Why We Decided to Upgrade
- Outdated Dropwizard version: All our backend services were using Dropwizard version 2.x.x, while the stable release had progressed to 4.0.12. Continuing with older versions restricted our ability to leverage newer Java features.
- Modern Java compatibility: Our services were locked to Java 8 due to Dropwizard 2.x.x, preventing us from leveraging enhancements introduced in Java 17 and 21, including virtual threads and improved JVM performance.
- Dependency conflicts: We encountered growing dependency conflicts due to the outdated
javax.*
APIs in our stack, which were incompatible with newer versions of libraries. - Shift towards Jakarta EE: The community and long-term support were shifting to Jakarta EE, making it essential to upgrade to stay aligned with modern industry standards and maintain active community support.
- Opportunity to utilize Java 21 features: Since we had already migrated to Java 21 for our backend services, it was the ideal time to upgrade to Dropwizard 4.0.x and fully leverage advanced features like virtual threads.
🔍 Key Highlights of Dropwizard 4.0.x
1. Transition to Jakarta EE 9
Dropwizard 4.0.12 transitions from the javax.*
namespace to the jakarta.*
namespace, aligning with Jakarta EE 9 standards. This change requires updating import statements in existing applications.
2. Updated Servlet API
The framework now includes Jakarta Servlet API 5.0.0, aligning with the latest standards and ensuring compatibility with modern servlet containers. This update provides access to new features and improvements in the servlet specification.
3. Improved Database Support
Dropwizard 4.0.12 enhances database support, offering better integration with various database systems. This improvement simplifies database configuration and management within Dropwizard applications.
4. Upgrade to Hibernate 6.1
The upgrade to Hibernate 6.1 brings several enhancements and changes, including:
- Removal of the Criteria API
- Elimination of restrictions on Serializable keys
- Removal of
AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS
These changes necessitate adjustments in how entities and queries are defined and managed.
5. Updated Dependencies
Dropwizard 4.0.12 updates several key dependencies to their latest versions, ensuring better performance, security, and compatibility:
- Jetty 11.0.24 or higher
- Jakarta Servlet API 5.0.0
- Jackson 2.18.1
- Logback 1.4.11
- Hibernate Validator 7.0.5.Final
- Swagger Annotations 1.6.3
- Byte Buddy 1.17.5
- Netty 4.2.0.Final
🛠️ Migration Challenges and Fixes
1.Jakarta Namespace compatibility
Error: java.lang.NoClassDefFoundError: javax/ws/rs/core/Response
Root Cause:
This error typically occurs when your application or a transitive dependency still references the old javax.ws.rs
namespace. Since Dropwizard 4.x is based on Jakarta EE 9, all such packages have been relocated to jakarta.ws.rs
. This mismatch breaks runtime resolution when older libraries are still in use.
Fix: Add the Jakarta-compatible dependencies explicitly in your pom.xml
to ensure proper resolution:

2.Jakarta Persistence Compatibility Issue
Error:java.lang.NoSuchFieldError: Class jakarta.persistence.GenerationType does not have member field 'jakarta.persistence.GenerationType UUID'
Root Cause:
This error is typically caused when a mismatched version of jakarta.persistence
is on the classpath—one that does not yet support the GenerationType.UUID
constant. This field was introduced in Jakarta Persistence 3.1, and using an older version results in the above runtime failure.
Fix: Ensure you're explicitly using the correct version of jakarta.persistence
by adding the following dependency in your pom.xml
:

3.Swagger Annotations Missing
Error: package io.swagger.annotations does not exist
Root Cause:
After migrating to Jakarta EE or updating to newer Dropwizard versions, older Swagger 2.x annotations like @Api
, @ApiOperation
, etc., might be missing due to:
- Removal of Swagger dependencies in the upgrade.
- Migration to OpenAPI 3 without compatible annotation support.
- Refactoring away from
javax.*
, which earlier Swagger versions depended on.
Fix: If you're continuing to use Swagger 2.x (not OpenAPI 3), add the following dependency:

4.Jetty Compatibility Issues
Error: java.lang.NoClassDefFoundError: org/eclipse/jetty/http/UriCompliance
Root Cause:
This error is commonly observed when Jetty classes expected by Dropwizard are not available at runtime. Specifically, UriCompliance
was introduced in Jetty 11 and is not present in earlier versions. If an older or mismatched Jetty version is on the classpath—especially due to transitive dependencies—it can break Dropwizard’s internal web server startup.
Fix: Ensure that Jetty 11.0.24 or higher is explicitly declared in your dependencies to avoid version

5.Logback Configuration Issues During Migration
Error: java.lang.NoClassDefFoundError: org/eclipse/jetty/http/UriCompliance
Root Cause:
During the migration, we ran into Logback initialization failures—particularly during application startup and reloads. At first glance, it appeared to be a Jetty-related issue, especially since Jetty 11 introduced internal changes. However, deeper investigation revealed that the underlying cause was Dropwizard’s updated classloading behavior and lifecycle sequencing.
Dropwizard 4 alters the order and timing of internal component initialization, which in turn impacted how and when logging configurations were loaded.
Fix:
- Ensure you're using Jetty 11.0.24 or higher, as earlier versions might be missing classes like
UriCompliance
used during URI parsing. - If you override
logback.xml
or rely on reloadable logging configurations, validate that your setup doesn’t depend on legacy Dropwizard assumptions about logging lifecycle timing. - Check for proper shading or classpath isolation if using custom Dropwizard bundles or third-party logging extensions.

6.DTO Serialization Issues
Error: Request body sent from our service was not reaching the downstream service correctly due to missing Lombok annotations.
Fix: Add the @Setter
annotation from Lombok to your DTO classes to ensure proper deserialization.
7.Stricter Dirty Checking on JSON Fields in Hibernate 6
Error : One of the more unexpected issues we faced during the migration to Dropwizard 4.0.11 (with Hibernate 6) was related to how Hibernate handles dirty checking on entities with JSON fields. Specifically, entities annotated with @Column(columnDefinition = "json")
were causing unnecessary UPDATE
statements, even when there were no actual data changes.
The root cause was Hibernate's enhanced dirty checking mechanism, which flagged differences in the serialized form of the JSON—like property order or formatting—as changes. This resulted in redundant updates that impacted performance and cluttered our audit logs.
Fix : We resolved this by explicitly marking such queries as read-only, using the following Hibernate hint:

This instructs Hibernate not to track changes to the returned entities, effectively avoiding false-positive updates for unchanged JSON fields. It was a simple but powerful adjustment that helped stabilize our data access layer post-upgrade.
🧰 Helpful Tools for Migration
Before beginning the migration process, consider installing the following tool to streamline dependency analysis and version management:
🔍 Maven Helper Plugin
A popular IntelliJ IDEA plugin available from the IntelliJ Marketplace, Maven Helper allows you to visualize, analyze, and troubleshoot Maven dependencies with ease.
Why it's useful:
While not strictly required, this tool is extremely helpful during Jakarta migration efforts—especially when:
- Identifying transitive dependencies still referencing
javax.*
- Resolving version conflicts
- Understanding dependency trees at a glance
Using this plugin can significantly reduce troubleshooting time and help ensure a smoother upgrade process.
🧪 Testing and Validation Plan
Pre-Deployment:
- Enable NewRelic and take a snapshot of performance insights of the service.
Deployment to Stage:
- We deploy dropwizard migration changes to the staging environment.
- We verify that all resources are being registered and API endpoints are reachable.
- Check for 5xx and 4xx errors post-deployment in NewRelic.
- Compare performance metrics before and after deployment to validate improvements and ensure there are no regressions. For example, we observed a 10–12% reduction in idle CPU usage across some services.
Deployment to Production:
- We deploy the service to production during business hours to monitor service performance under higher load.
- We monitor the service for at least 3-4 hours and check JVM parameters and performance.

📊 Impact of Migration
Our migration efforts brought tangible, measurable improvements:
- ✅ 30% faster application startup time
Thanks to improved classpath scanning, Guice optimizations, and reduced bean initialization overhead. - 🧼 Cleaner audit logs & DB traffic
Cleaner audit logs were a result of more accurate Hibernate tracking behavior after resolving JSON dirty check issues. This reduced noise in change logs and unnecessary database updates. - 🔒 Better security posture
Updated core dependencies (Jetty, Jackson, Hibernate, Logback) eliminated several known CVEs and reduced our attack surface. - 📉 Reduced CPU consumption under idle and low load
Jetty 11 and Java 21 offered better thread management and GC behavior, resulting in 10–12% lower idle CPU usage in some services.- Pre-deployment cpu utilization (blue) remained close to 30–35%.
- Post-deployment (green) saw a notable reduction to around 15–20% in cpu utilization.

- 🔋 15–20% reduction in memory usage
Achieved by running on Java 21, removing legacy libraries, and leveraging memory-efficient data structures introduced in newer libraries.- Pre-deployment memory usage (blue) remained close to 90–95%.
- Post-deployment (green) saw a notable reduction to around 65–75%, demonstrating more efficient memory handling.

🧵 Embracing Virtual Thread Compatibility with Dropwizard 4.0.x
Java 21 introduces Virtual Threads, a groundbreaking feature for handling massive concurrency with minimal thread overhead. Thanks to the Dropwizard 4 upgrade, our application is now ready to experiment with and adopt virtual threads for future scalability improvements.
While Dropwizard itself runs seamlessly on virtual threads, we encountered a key caveat: many JDBC drivers, including the MySQL driver, still rely on traditional blocking I/O. This limits the effectiveness of virtual threads in I/O-heavy workloads.
🔍 Our tests showed no major performance gain when using virtual threads with MySQL, as blocking calls still dominate execution.
This limitation isn’t due to Dropwizard or Java—it’s an ecosystem-level gap. As non-blocking drivers (e.g., R2DBC) and libraries mature, we expect virtual threads to become a game-changer for high-throughput services.
Takeaways:
- Dropwizard 4 unlocks virtual-thread support with Java 21.
- Existing JDBC drivers may block true benefits—test before adopting.
- We're watching the ecosystem for non-blocking database access patterns.
Conclusion
Upgrading to Dropwizard 4.x was a significant engineering effort, but it enabled us to modernize our tech stack and improve operational performance. The migration brought:
- Full compatibility with Java 21
- Cleaner, future-proof dependency injection
- Metrics, serialization, and validation aligned with latest standards
While challenging, the upgrade paid off in performance, reliability, and long-term maintainability. If you're considering a similar move, it’s worth the investment—and much smoother with a clear plan.
If you’re currently on an older version of Dropwizard, it's prudent to plan the upgrade proactively—delaying may increase technical debt and migration complexity. Taking action now sets your codebase up for better performance, maintainability, and long-term scalability.
Join Us
Scalability, reliability and maintainability are the three pillars that govern what we build at Halodoc Tech. We are actively looking for engineers at all levels, and if solving complex problems with challenging requirements is your forte, please reach out to us with your resumé at careers.india@halodoc.com.
About Halodoc
Halodoc is the number one all-around healthcare application in Indonesia. Our mission is to simplify and deliver quality healthcare across Indonesia, from Sabang to Merauke. Since 2016, Halodoc has been improving health literacy in Indonesia by providing user-friendly healthcare communication, education, and information (KIE). In parallel, our ecosystem has expanded to offer a range of services that facilitate convenient access to healthcare, starting with Homecare by Halodoc as a preventive care feature that allows users to conduct health tests privately and securely from the comfort of their homes; My Insurance, which allows users to access the benefits of cashless outpatient services in a more seamless way; Chat with Doctor, which allows users to consult with over 20,000 licensed physicians via chat, video or voice call; and Health Store features that allow users to purchase medicines, supplements and various health products from our network of over 4,900 trusted partner pharmacies. To deliver holistic health solutions in a fully digital way, Halodoc offers Digital Clinic services including Haloskin, a trusted dermatology care platform guided by experienced dermatologists.We are proud to be trusted by global and regional investors, including the Bill & Melinda Gates Foundation, Singtel, UOB Ventures, Allianz, GoJek, Astra, Temasek, and many more. With over USD 100 million raised to date, including our recent Series D, our team is committed to building the best personalized healthcare solutions — and we remain steadfast in our journey to simplify healthcare for all Indonesians.