By Rogerio Robetti – OJP Founder and Lead Developer

Every few releases a project crosses a threshold where the changes stop being incremental and start reshaping how the system can be used.
Open J Proxy 0.4.0-beta is one of those releases.
This version touches nearly every layer of OJP: integration with popular Java frameworks, observability, security, extensibility, and developer tooling. The result is a release that makes OJP easier to integrate, easier to operate, and far more flexible internally.
Let’s walk through the most important improvements.
Spring Boot Integration Without Boilerplate
For many Java teams, the easiest way to judge whether a tool will be adopted is simple: how easy is it to plug into Spring Boot?
Until now, integrating OJP into a Spring Boot application required a few manual steps—registering the driver, configuring the datasource, forwarding JVM properties, and ensuring initialization happened in the correct order.
That friction is now gone.
OJP 0.4.0-beta introduces a new module:
spring-boot-starter-ojp
Once the dependency is added, Spring Boot applications automatically detect OJP JDBC URLs and configure the datasource correctly.
<dependency>
<groupId>org.openjproxy</groupId>
<artifactId>spring-boot-starter-ojp</artifactId>
<version>0.4.0-beta</version>
</dependency>
From there, all you need is a JDBC URL starting with jdbc:ojp.
The starter automatically:
- registers the correct driver
- configures the datasource
- wires the integration into Spring Boot
Named datasource support is also included. If a datasource name is embedded in the JDBC URL, the Spring Boot starter forwards the correct configuration prefix so the OJP server can apply independent pool configurations for each datasource.
The starter targets Spring Boot 4.x, making it practical for teams already running production workloads.
A New SPI Architecture: Pluggable Connection Pools
One of the most important architectural additions in this release is the Connection Pool Provider SPI.
Instead of hard-coding a single pool implementation inside OJP, the server now exposes a pluggable provider interface. This means the connection pool implementation can be swapped without modifying OJP itself.
Several modules were introduced to support this architecture:
ojp-datasource-api— the provider interface and contractsojp-datasource-dbcp— an Apache Commons DBCP implementationojp-datasource-hikari— our default (previously only one) HikariCP implementation.ojp-xa-pool-commons— an Apache Commons Pool 2-based XA provider.
Providers are selected based on priority. If multiple providers are present, the one with the highest priority wins.
The implications of this change are significant.
It allows:
- custom pool implementations
- vendor-specific optimizations
- experimentation with different pooling strategies
- easier integration with future ecosystem tools
In other words, OJP’s internal pooling architecture is now extensible by design.
For an infrastructure component that sits between applications and databases, that level of flexibility is extremely valuable.
Observability: From Metrics to Full Telemetry
Operating a distributed system without good telemetry is extremely difficult. In this release, OJP significantly expands its observability capabilities.
Distributed Tracing
OJP now supports OpenTelemetry distributed tracing for all gRPC calls.
Two exporters are supported out of the box:
- Zipkin (default)
- OTLP, compatible with Jaeger, Grafana Tempo, the OpenTelemetry Collector, and most cloud APM systems
Tracing can be enabled with a simple configuration flag:
ojp.tracing.enabled=true
Sampling rates can also be configured so teams can control how much tracing data is generated.
Granular Telemetry Configuration
Previously telemetry in OJP was controlled by a single switch.
In 0.4.0-beta, telemetry is now configurable at a much finer level. You can enable or disable individual signals such as:
- gRPC call metrics
- connection pool metrics
- the overall telemetry infrastructure
This allows teams to collect the signals they care about without adding unnecessary overhead.
SQL Performance Visibility
One of the most practical improvements in this release is the ability to visualize actual SQL statements in execution metrics.
Instead of abstract identifiers, monitoring systems can now display the real SQL query associated with each metric. This makes it much easier to:
- identify slow queries
- filter dashboards by query type
- build alerts around specific SQL patterns
For teams operating production systems, this dramatically improves troubleshooting and performance analysis.
Early Warning Signals for Connection Pressure
Three additional metrics were introduced to help operators detect database pressure earlier:
- connection queue depth
- connection wait time
- SQL execution time per statement
Together these signals provide early warnings that connection contention is building before it becomes visible to users.
Security Improvements
Security also received attention in this release.
Mutual TLS (mTLS)
OJP now supports mutual TLS between the JDBC driver and the OJP server.
Both the client and server can be configured with certificates, allowing encrypted communication and mutual authentication.
This is particularly important for containerized and cloud environments where infrastructure boundaries are dynamic and network traffic should always be authenticated.
Dependency Security Updates
Several dependencies were upgraded to address known vulnerabilities, including updates affecting logging libraries, JSON processing, testing utilities, and networking components.
These upgrades eliminate multiple CVEs and keep OJP aligned with current security practices.
First-Class Integration Testing with TestContainers
Starting with 0.4.0-beta, OJP provides an official TestContainers integration module that is published as a separate JAR.
This module allows applications to easily spin up an OJP server inside a TestContainers-managed Docker container during integration tests.
Instead of manually orchestrating infrastructure during testing, applications can simply include the module and instantiate an OJP container directly in their test code.
This makes it much easier to test:
- session affinity behavior
- distributed transactions
- database interactions through OJP
in a reproducible environment.
For teams building systems around OJP, this removes a significant barrier to automated testing.
Modern Java Time Support
Released already in a hot-fix version 0.3.2-beta, the OJP JDBC driver now provides full support for modern java.time types when passed as JDBC parameters.
Developers can now call:
PreparedStatement.setObject(…)
with types such as: LocalDate, LocalTime, LocalDateTime, OffsetDateTime, OffsetTime, Instant, ZonedDateTime.
The driver and server cooperate to convert these values correctly using internal converters.
The implementation was tested across every database currently supported by OJP, including PostgreSQL, MySQL, MariaDB, Oracle, SQL Server, DB2, CockroachDB, and H2.
If a particular database driver does not support a specific type, OJP now returns a clear error rather than failing silently.
Slow Query Segregation Behavior Change
The slow query segregation feature itself has not changed in this release, but its default behavior has.
Previously the feature was enabled by default. That occasionally surprised users who had not explicitly opted into the behavior.
Beginning with 0.4.0-beta, slow query segregation is disabled by default and must be explicitly enabled via configuration.
This change makes the feature opt-in and avoids unexpected behavior for new users.
Under the Hood: Architectural Improvements
Several internal architectural improvements were also introduced.
Unified Connection Architecture
OJP previously had separate code paths for single-node and multi-node deployments.
That distinction has now been removed.
The server always uses the multinode connection manager, even when only one node is configured. This simplifies the codebase and eliminates a class of bugs that only appeared when systems moved from single-node setups to clustered deployments.
Virtual Threads (Java 21)
OJP now targets Java 21 and uses virtual threads for housekeeping tasks such as pool eviction and metrics listeners.
Some synchronization mechanisms were updated to avoid virtual-thread pinning issues, replacing synchronized blocks with ReentrantLock.
This allows OJP to benefit from modern JVM concurrency improvements while remaining compatible with older environments when necessary.
Action Pattern Across the Server
The server’s core request handling code has also been refactored to consistently use the Action pattern.
Operations such as:
- fetching rows
- starting transactions
- LOB handling
- XA operations
are now implemented as separate action classes.
While this does not change the external behavior of OJP, it significantly improves maintainability and reduces the complexity of the server core.
XA Transactions: Production-Ready
XA support existed before this release, but 0.4.0-beta is where it becomes truly production-ready.
The most important improvement is the introduction of a new XA connection pool built on Apache Commons Pool 2, chosen for its predictable behavior under distributed transaction workloads.
Finally, XA connections now support runtime transaction isolation configuration, with isolation levels reset automatically between sessions to ensure a clean state for every borrowed connection.
These improvements make distributed transaction support significantly more robust in real-world deployments.
A Release That Expands OJP’s Foundation
Taken together, the changes in OJP 0.4.0-beta represent a major milestone.
This release introduces:
New modules
- Spring Boot starter
- TestContainers integration
- datasource SPI modules
New capabilities
- distributed tracing
- mutual TLS
- SQL statement observability
- modern Java time support
Architectural improvements
- pluggable connection pool SPI
- unified connection model
- virtual thread support
- consistent action-based server architecture
Most importantly, these improvements strengthen the core idea behind OJP: providing a database-agnostic proxy designed specifically for modern Java systems.
As the project continues evolving, this release lays the groundwork for the next phase of development—an extensible ecosystem around OJP and even richer operational tooling.