How does FlexyPool support both Connection proxies and decorators

Proxies

FlexyPool monitors connection pool usage and so it needs to intercept the connection close method call.
For simplicity sake, the first version was relying on dynamic proxies for this purpose:

private static class ConnectionInvocationHandler 
    implements InvocationHandler {

    public static final String CLOSE_METHOD_NAME = "close";

    private final Connection target;
    private final ConnectionCallback callback;

    public ConnectionInvocationHandler(
        Connection target, 
        ConnectionCallback callback) {
        this.target = target;
        this.callback = callback;
    }

    @Override
    public Object invoke(
        Object proxy, 
        Method method, 
        Object[] args) throws Throwable {
        if (CLOSE_METHOD_NAME.equals(method.getName())) {
            callback.close();
        }
        return method.invoke(target, args);
    }
}

As straightforward as it may be, a proxy invocation is slower than a decorator, which calls the target method using a direct invocation.
Because all connection pools use proxies anyway, adding another proxy layer only adds more call-time overhead and so now FlexyPool supports connection decorators as well.

Decorators

A ConnectionDecorator wraps an underlying database connection, delegating all calls to the actual object instance. Just like its proxy counterpart, oOnly the close method is doing any extra logic:

public class ConnectionDecorator 
    implements Connection {

    private final Connection target;

    private final ConnectionCallback callback;

    public ConnectionDecorator(
        Connection target, 
        ConnectionCallback callback) {
        this.target = target;
        this.callback = callback;
    }

    public Connection getTarget() {
        return target;
    }

    public ConnectionCallback getCallback() {
        return callback;
    }

    @Override
    public Statement createStatement() 
        throws SQLException {
        return target.createStatement();
    }
    
    @Override
    public void close() 
        throws SQLException {
        callback.close();
        target.close();
    }
    
    /**
     *  More methods omitted for brevity sake
     */

    public void setSchema(String schema) 
        throws SQLException {
        ReflectionUtils.invoke(
            target,
            ReflectionUtils.getMethod(
                target, 
                "setSchema", 
                String.class
            ),
            schema
        );
    }

    public String getSchema() 
        throws SQLException {
        return ReflectionUtils.invoke(
            target,
            ReflectionUtils.getMethod(
                target, 
                "getSchema"
            )
        );
    }

    public void abort(Executor executor) 
        throws SQLException {
        ReflectionUtils.invoke(
            target,
            ReflectionUtils.getMethod(
                target, 
                "abort", 
                Executor.class
            ),
            executor
        );
    }

    public void setNetworkTimeout(
        Executor executor, 
        int milliseconds) 
        throws SQLException {
        ReflectionUtils.invoke(
            target,
            ReflectionUtils.getMethod(
                target, 
                "setNetworkTimeout", 
                Executor.class, 
                int.class
            ),
            executor, 
            milliseconds
        );
    }

    public int getNetworkTimeout() 
        throws SQLException {
        return (Integer) 
            ReflectionUtils.invoke(
                target,
                ReflectionUtils.getMethod(
                    target, 
                    "getNetworkTimeout"
                )
            );
    }
}

As you might have noticed already, some methods use Java Reflection instead of a direct method call:

These methods have been added to Java 1.7 and a direct call will fail when compiling the project with Java 1.6.
Because Java 1.6 is the minimum requirement for most FlexyPool modules, these methods forward the incoming method call through a Java reflection invocation.
Omitting these methods is not optional either because on a 1.7 JVM, the Connection decorator will not have these methods and a class loading error will be thrown.

On projects using at least Java 1.7, FlexyPool also offers the Java7ConnectionDecorator:

public class Java7ConnectionDecorator 
    extends ConnectionDecorator {

    public Java7ConnectionDecorator(
        Connection target, 
        ConnectionCallback callback) {
        super(target, callback);
    }

    @Override
    public void setSchema(String schema) 
        throws SQLException {
        getTarget().setSchema(schema);
    }

    @Override
    public String getSchema() 
        throws SQLException {
        return getTarget().getSchema();
    }

    @Override
    public void abort(Executor executor) 
        throws SQLException {
        getTarget().abort(executor);
    }

    @Override
    public void setNetworkTimeout(
        Executor executor, 
        int milliseconds) 
        throws SQLException {
        getTarget().setNetworkTimeout(executor, milliseconds);
    }

    @Override
    public int getNetworkTimeout() 
        throws SQLException {
        return getTarget().getNetworkTimeout();
    }
}

This class is not part of the core library, being included in a separated Java 1.7 compliant module.
To make use of it, you need to add the following Maven dependency:

<dependency>
    <groupId>com.vladmihalcea.flexy-pool</groupId>
    <artifactId>flexy-pool-core-java7</artifactId>
    <version>${flexy-pool.version}</version>
</dependency>

The service discovery mechanism

From the very beginning, FlexyPool has offered support for configuring the ConnectionProxyFactory instance, so switching to decorators didn’t require any intensive code refactoring.

Prior to release 1.2.4 the default connection provider was the JdkConnectionProxyFactory, which uses dynamic proxies.
Since 1.2.4, FlexyPool uses connection decorators as the default connection intercepting mechanism.

The actual decorator version is resolved at runtime and the loading mechanism is built out of the following components:

FlexyPoolConnectionProxyDecorator

The actual connection decorator factory is resolved by the following method:

public ConnectionDecoratorFactory resolve() {
    int loadingIndex = Integer.MIN_VALUE;
    ConnectionDecoratorFactory connectionDecoratorFactory = null;
    Iterator<ConnectionDecoratorFactoryService> 
        connectionDecoratorFactoryServiceIterator = serviceLoader.iterator();
    while (connectionDecoratorFactoryServiceIterator.hasNext()) {
        try {
            ConnectionDecoratorFactoryService connectionDecoratorFactoryService = 
                connectionDecoratorFactoryServiceIterator.next();
            int currentLoadingIndex = connectionDecoratorFactoryService.loadingIndex();
            if (currentLoadingIndex > loadingIndex) {
                ConnectionDecoratorFactory currentConnectionDecoratorFactory = 
                    connectionDecoratorFactoryService.load();
                if (currentConnectionDecoratorFactory != null) {
                    connectionDecoratorFactory = currentConnectionDecoratorFactory;
                    loadingIndex = currentLoadingIndex;
                }
            }
        } catch (LinkageError e) {
            LOGGER.info("Couldn't load ConnectionDecoratorFactoryService on the current JVM", e);
        }
    }
    if (connectionDecoratorFactory != null) {
        return connectionDecoratorFactory;
    }
    throw new IllegalStateException("No ConnectionDecoratorFactory could be loaded!");
}

Just like the MetricsFactory, each connection decorator factory has an associated Service Provider. Multiple such Service Providers can be loaded at runtime (the default Java 1.6 connection decorator service or the Java 1.7 one). The selection is done based on the index (latest Java version take precedence) and the current JVM JDBC version support (the Java 1.7 connection decorator won’t be resolved on a Java 1.6 runtime environment).

Conclusion

Decorators incur more configuration overhead than a proxy but if you want to squeeze the last performance drop it’s worth considering the direct method call advantage.

Why you should always use connection pooling with Oracle XE

Introduction

Oracle Express Edition is the free version of Oracle Enterprise Edition and its smaller size makes it very convenient for testing various Oracle functionalities.

According to Oracle documentation, the Express Edition can use at most one CPU and 1 GB of RAM, but in reality there are other limitations that are not always obvious.

Database connection handling anomaly

The following tests tries to simulate a low latency transaction environment, so the connection is leased for a very short ammount of time:

private void simulateLowLatencyTransactions(
        DataSource dataSource, int waitMillis) 
        throws SQLException {
    for (int i = 0; i < callCount; i++) {
        try {
            try (Connection connection = 
                 dataSource.getConnection()) {
                //Let's assume we are running a
                //short-lived transaction
                sleep(waitMillis);
            }
        } catch (SQLException e) {
            LOGGER.error("Exception on iteration " + i, e);
        }
    }
}

This test works fine until lowering the waiting time beyond a certain threshold value, in which case the database sporadically starts throwing the following exception:

ERROR  [main]: c.v.b.h.j.c.OracleConnectionCallTest - Exception on iteration 111
java.sql.SQLException: Listener refused the connection with the following error:
ORA-12516, TNS:listener could not find available handler with matching protocol stack
 
    at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:489) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:553) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:254) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:528) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at oracle.jdbc.pool.OracleDataSource.getPhysicalConnection(OracleDataSource.java:280) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.java:207) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.java:157) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at com.vladmihalcea.book.high_performance_java_persistence.jdbc.connection.OracleConnectionCallTest.simulateLowLatencyTransactions(OracleConnectionCallTest.java:50) [test-classes/:na]
    at com.vladmihalcea.book.high_performance_java_persistence.jdbc.connection.OracleConnectionCallTest.testConnections(OracleConnectionCallTest.java:40) [test-classes/:na]

Although the code is single-threaded, Oracle starts complaining that the connection request listener cannot find a process handler for serving the incoming request.

This assumption can be proven by raising the processes and sessions parameters to a higher value:

alter system set processes=1000 scope=spfile;
alter system set sessions=1000 scope=spfile;

With these new settings, the code runs fine and no exception is issued. Although increasing the processes and sessions limits makes the issue go away, this solution is only a work-around and it only raises the connection threshold instead of addressing the root cause.

One possible explanation is given by this IBM troubleshooting note, suggesting that the connection listener might not be instantly notified by the connection closing events. This might causes the connection listener to wrongly assert the actual connection count and to assume that the maximum number of processes has already been reached.

On Oracle 11g Enterprise Edition this issue is not replicable.

The fix

Astute readers will notice the problem when looking on the exception stack-trace. The OracleDataSource doesn’t offer any connection pooling mechanism and that’s causing a lot of connection establishing overhead on both the driver as on the server side.

Using a connection pool fixes this issue because connections are reused instead of being established on demand. The connection pool dramatically reduces the connection acquire time, which also leads to lower transaction latencies and better throughput.

This article is part of the research I’m undergoing for my High-Performance Java Persistence book. If you enjoyed it reading it, you might also subscribe to follow my progress.

How to translate WordPress blog posts to Leanpub Markdown

Unix tools to the rescue

I am a big fan of Unix utilities as they help my out on a daily basis. When the Leanbub WordPress export tool failed me, I knew I had to write my own import script. Without an automatic script I’d had to spend more than half an hour to fix broken source codes or tables and migrate image references to the book repository folder structure.

But the The High-Performance Java Persistence book is using info that’s scattered across over 60 blog posts, which would have taken me months to manually import.

With this little script, I managed to cut the import time to a couple of second per article.

#!/bin/bash

url=$1

#Generate the file name from URL
file=`echo $url | sed -r 's/.*\..*?\/(.*?)[\/$]/\1.md/' | sed 's/\//-/'g`

#Generate a temporary file
tmpfile=`uuidgen`

#Create missing files
touch $tmpfile
touch $file

#Download the WordPress post to the temporary file
wget $url --no-cache --cache=off -O $tmpfile

#Extract the relevant post content  
perl -0777 -n -e 'print "<h1>$1<\/h1>\n$2" while (m/<h1\s*class="entry-title">(.*?)<\/h1>.*?<div\s*class="entry-content">(.*?)<\/div>/sgmp)' $tmpfile > $file

#Remove the temporary file
rm $tmpfile

echo 'Importing resource from ' $url 'to' $file

#Convert the HTML document to MarkDown
pandoc -s -r html $file -t markdown-backtick_code_blocks-simple_tables+pipe_tables --atx-headers -o $file

#Adjust code blocks according to Leanpub style
perl -0777 -i -pe 's/(\~+)\s+.*?\.(\w+);.*?\}/{lang="$2",line-numbers=off}\n$1/ig' $file

#Remove unnecessary footer notes
perl -0777 -i -pe 's/Code\s*available\s*(on|for).*$//igs' $file
perl -0777 -i -pe 's/\*\*If\syou\shave\senjoyed.*$//igs' $file

#Migrate image locations from WP to relative image folder
sed -i -r 's_\[\!\[(.*?)\]\(.*?\)\]\(http.*\/([a-zA-Z0-9\-]+\.(gif|png|jpg))\)_![\1]\(images\/\1\.\3\)_g' $file

#First line header is set to ##
sed -i '1s/^#/##/g' $file

#Next lines headers upper limit is ###
sed -i '2,$s/^#/###/g' $file

#Remove backup file generated by perl
rm $file.bak

So this little script takes a blog post URL and the does the following steps:

  1. It first generates a file name from the blog post URL
  2. It creates a temporary file
  3. It downloads the blog HTML content to the temporary file
  4. Using Perl, it extract the article content from the enveloping HTML markup
  5. Using Pandoc, it transform the extracted HTML content to Markdown
  6. With Perl, it then formats all code blocks to Leanpub supported format
  7. It also remove unnecessary blocks (e.g. follow me notes or GitHub references)
  8. All images are changed to reference a relative book repository folder
  9. Headers are migrated to Leanpub chapters format

All in all, I managed to get all articles in a timely manner so I can concentrate on writing instead.

Speedment ORM – deliberate enterprise caching

A small company with big dreams

I first heard of Speedment while watching a Hazelcast webinar about a RDBMS Change Data Capture approach for updating the in-memory data grid. Their products are very much in-line with Greg Luck’s Deliberate caching and I can see many enterprise products gaining from this new paradigm shift.

We have the pleasure of talking to Per-Åke Minborg, who is the CTO and one of the founders of Speedment AB.

Hi Per. Can you please describe Speedment goals?

Speedment brings a more modern way of handling data located in various data stores, such as SQL databases. We are using standard Java 8 streams for querying the data sources, so the developers do not need to learn new complex APIs or configure ORMs. Thus, we speed up the development process. Speedment will also speed up the application as such. One problem with some of the existing products are that they are actually making data access SLOWER than JDBC and not faster. We think it should be the other way around and have developed a way to make applications run quicker with Speedment.

How does it differ from any existing data access technologies (JPA, jOOQ)?

JPA is a separate framework that is added to Java and it is not always easy to understand how to use it in the best way. It does not take advantage of all the new features that became available with Java 8. Also, in JPA, you start to construct your Java domain model and then you translate it to a database domain. Speedment and jOOQ does it the other way around. You start with your data model and then extract your Java domain model from that. Even though you can cache data with JPA, neither JPA nor jOOQ can provide data acceleration as Speedment can. Furthermore, with Speedment, you do not have to learn a new query API, because it relies on standard Java 8 streams.

Does Speedment shifts to a deliberately cache architecture?

The enterprise version of Speedment contains “caching” functionality. The new thing with our “caching” is that you will be able to locate objects in the cache in many ways (i.e. using several keys or search criteria) and not only as a key/value store. The “cache” can also be shared concurrently with the application so that cache operations can be completed in O(1) time. For example, if you are retrieving all users named “Bob” you use a “view” of the user cache (i.e. the “name” view) and you will be able to obtain all the Bobs rapidly and in constant time regardless if there where just one Bob or if there were thousands of Bobs. Speedment is using an advanced in-JVM-memory solution that can extend the JVM to hundreds of terabytes without garbage collect problems and enables a JVM that is bigger than the actual RAM size. This allows all your data to fit into the same JVM as the application. The Speedment cache is “hot”, so if the underlying database changes, then the cache is updated accordingly using a reactive model.

How does it integrate with Hazelcast in-memory data grid

Hazelcast provides an add-on solution to hold all the caching elements using a distributed memory data grid. That way, you will be able to scale out applications indefinitely into any number of terabytes. Speedment provides a hot-cache solution for Hazelcast that can be compared to Oracles Golden Gate Hotcache.

Which parts of the whole platform are going to be included in the open-source version

Speedment Open Source is a native Java 8 API with powerful developer features. In addition to this there are add-ons available as enterprise features. The team will continuously evaluate the community contributions and add features to the main branch continuously. We want our users to be able to test, develop and deploy applications with Speedment Open Source, but we would also like to be able to offer them something more. If they want enterprise grade functions like really big data sets, high availability or clustered environments this can all be added from the enterprise portfolio. You can go to our open source project on GitHub and follow the development there and perhaps also join the community! The first official version speedment-2.0.0 will be launched in the end of the summer and will contain many new interesting Java 8 features.

Thanks Per for taking your time to give this interview. Let’s hope we hear more from you guys.

How does FlexyPool support the Dropwizard Metrics package renaming

Introduction

FlexyPool relies heavily on Dropwizard (previously Codahale) Metrics for monitoring the connection pool usage. Being integrated into Dropwizard, the package name was bound to be renamed.

So instead of com.codahale.metrics the 4.0.0 release will use the io.dropwizard.metrics package name.

The challenge

Apart from the obvious backward incompatibility, the most challenging aspect of this change is that the Maven dependency will only see a version incrementation. This means that you won’t be able to include both versions in the same Maven module, because the groupId and the artifactId will not change between the 3.x.x and the 4.x.x version change.

<dependency>
     <groupId>io.dropwizard.metrics</groupId>
     <artifactId>metrics-core</artifactId>
     <version>${codahale.metrics.version}</version>
</dependency>

<dependency>
     <groupId>io.dropwizard.metrics</groupId>
     <artifactId>metrics-core</artifactId>
     <version>${dropwizard.metrics.version}</version>
</dependency>

This change is manageable in an end-user application as you only have to migrate from one version to the other. An open source framework built on top of Dropwizard Metrics is much more difficult to refactor as you need to support two incompatible versions of the same library. After all, you don’t want to force your clients to migrate to a certain Metrics dependency.

Luckily, FlexyPool has had its own Metrics abstraction layer from the very beginning. Insulating a framework from external dependencies is a safe measure, allowing you to swap dependencies without much effort.

To support both Codahale and Dropwizard package names, FlexyPool metrics are build like this:

FlexyPoolMetricsCodahaleDropwizard

Because those classes cannot reside in one jar, there are three modules hosting this hierarchy:

  • flexy-pool-core: defines the FlexyPool Metrics abstraction
  • flexy-codahale-metrics: implements the FlexyPool metrics abstraction on top of Codahale Matrics
  • flexy-dropwizard-metrics: implements the FlexyPool metrics abstraction on top of Dropwizard Matrics

Each MetricsFactory is registered as a Service Provider:

public class CodahaleMetricsFactoryService 
    implements MetricsFactoryService {

    public static final String METRICS_CLASS_NAME = 
        "com.codahale.metrics.Metric";

    @Override
    public MetricsFactory load() {
        return ClassLoaderUtils
            .findClass(METRICS_CLASS_NAME) ? 
                CodahaleMetrics.FACTORY : null;
    }
}

public class DropwizardMetricsFactoryService 
    implements MetricsFactoryService {

    public static final String METRICS_CLASS_NAME = 
        "io.dropwizard.metrics.Metric";

    @Override
    public MetricsFactory load() {
        return ClassLoaderUtils
            .findClass(METRICS_CLASS_NAME) ? 
                DropwizardMetrics.FACTORY : null;
    }
}

and the services are resolved at runtime:

private ServiceLoader<MetricsFactoryService> 
    serviceLoader = ServiceLoader.load(
        MetricsFactoryService.class);

public MetricsFactory resolve() {
    for(MetricsFactoryService service : serviceLoader) {
        MetricsFactory metricsFactory = service.load();
        if(metricsFactory != null) {
            return metricsFactory;
        }
    }
    throw new IllegalStateException(
        "No MetricsFactory could be loaded!"
    );
}

Conclusion

This way FlexyPool can use both Metrics implementations and the decision is taken dynamically based on the currently available library. The Dropwizard metrics 4.0.0 is not yet released, but FlexyPool is ready for the upcoming changes.

The High-Performance Java Persistence book

A book in the making

It’s been a year since I started the quest for a highly-effective Data Knowledge Stack and the Hibernate Master Class contains over fifty articles already.

Now that I covered many aspects of database transactions, JDBC and Java Persistence, it’s time to assemble all the pieces together into the High-Performance Java Persistence book.

An Agile publishing experience

Writing a book is a very time-consuming and stressful process and the last thing I needed was a very tight schedule. After reading Antonio Goncalves’s story, I chose the self-publishing way.

In the end, I settled for Leanpub because it allows me to publish the book incrementally. This leads to a better engagement with readers, allowing me adapt the book content on the way.

The content

At its core, the book is about getting the most out of your persistence layer and that can only happen when your application resonates with the database system. Because concurrency is inherent to database processing, transactions play a very important role in this regard.

The first part will be about some basic performance-related database concepts such as: locking, batching, connection pooling.

In the second part, I will explain how an ORM can actually improve DML performance. This part will include the Hibernate Master Class findings.

The third part is about advance querying techniques with jOOQ.

Get involved

The Agile methodologies are not just for software development. Writing a book in a Lean style can shorten the feed-back period and readers can get involved on the way.

If you have any specific request or you are interested in this project, you can join my newsletter and follow my progress.

How to monitor a Java EE DataSource

Introduction

FlexyPool is an open-source framework that can monitor a DataSource connection usage. This tool come out of necessity, since we previously lacked support for provisioning connection pools.

FlexyPool was initially designed for stand-alone environments and the DataSource proxy configuration was done programmatically. Using Spring bean aliases, we could even substitute an already configured DataSource with the FlexyPool Metrics-aware proxy alternative.

Java EE support

Recently, I’ve been asked about supporting Java EE environments and in the true open-source spirit, I accepted the challenge. Supporting a managed environment is tricky because the DataSource is totally decoupled from the application-logic and made available through a JNDI lookup.

One drawback is that we can’t use automatic pool sizing strategies, since most Application Servers return a custom DataSource implementation (which is closely integrated with their in-house JTA transaction manager solution), that doesn’t offer access to reading/writing the connection pool size.

While the DataSource might not be adjustable, we can at least monitor the connection usage and that’s enough reason to support Java EE environments too.

Adding declarative configuration

Because we operate in a managed environment, we can no longer configure the DataSource programmatically, so we need to use the declarative configuration support.

By default, FlexyPool looks for the flexy-pool.properties file in the current Class-path. The location can be customized using the flexy.pool.properties.path System property , which can be a:

  • URL (e.g. file:/D:/wrk/vladmihalcea/flexy-pool/flexy-pool-core/target/test-classes/flexy-pool.properties)
  • File system path (e.g. D:\wrk\vladmihalcea\flexy-pool\flexy-pool-core\target\test-classes\flexy-pool.properties)
  • Class-path nested path (e.g. nested/fp.properties)

The properties file may contain the following configuration options:

Parameter name Description

flexy.pool.data.source.unique.name

Each FlexyPool instance requires a unique name so that JMX domains won’t clash

flexy.pool.data.source.jndi.name

The JNDI DataSource location

flexy.pool.data.source.jndi.lazy.lookup

Whether to lookup the DataSource lazily (useful when the target DataSource is not available when the FlexyPoolDataSource is instantiated)

flexy.pool.data.source.class.name

The DataSource can be instantiated at Runtime using this Class name

flexy.pool.data.source.property.*

If the DataSource is instantiated at Runtime, each flexy.pool.data.source.property.${java-bean-property} will set the java-bean-property of the newly instantiated DataSource (e.g. flexy.pool.data.source.property.user=sa)

flexy.pool.adapter.factory

Specifies the PoolAdaptorFactory, in case the DataSource supports dynamic sizing. By default it uses the generic DataSourcePoolAdapter which doesn’t support auto-scaling

flexy.pool.metrics.factory

Specifies the MetricsFactory used for creating Metrics

flexy.pool.metrics.reporter.log.millis

Specifies the metrics log reported interval

flexy.pool.metrics.reporter.jmx.enable

Specifies if the jmx reporting should be enabled

flexy.pool.metrics.reporter.jmx.auto.start

Specifies if the jmx service should be auto-started (set this to true in Java EE environments)

flexy.pool.strategies.factory.resolver

Specifies a ConnectionAcquiringStrategyFactoryResolver class to be used for obtaining a list of ConnectionAcquiringStrategyFactory objects. This should be set only if the PoolAdaptor supports accessing the DataSource pool size.

Hibernate ConnectionProvider

Most Java EE applications already use JPA and for those who happen to be using Hibernate, we can make use of the hibernate.connection.provider_class configuration property for injecting our proxy DataSource.

Hibernate provides many built-in extension points and the connection management is totally configurable. By providing a custom ConnectionProvider we can substitute the original DataSource with the FlexyPool proxy.

All we have to do is adding the following property to our persistence.xml file:

<property name="hibernate.connection.provider_class"
          value="com.vladmihalcea.flexypool.adaptor.FlexyPoolHibernateConnectionProvider"/>

Behind the scenes, this provider will configure a FlexyPoolDataSource and use it whenever a new connection is requested:

private FlexyPoolDataSource<DataSource> flexyPoolDataSource;

@Override
public void configure(Map props) {
    super.configure(props);
    LOGGER.debug(
        "Hibernate switched to using FlexyPoolDataSource
    ");
    flexyPoolDataSource = new FlexyPoolDataSource<DataSource>(
        getDataSource()
    );
}

@Override
public Connection getConnection() throws SQLException {
    return flexyPoolDataSource.getConnection();
}

Instantiating the actual DataSource at runtime

If you’re not using Hibernate, you need to have the FlexyPoolDataSource ready before the EntityManagerFactory finishes bootstrapping:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

    <persistence-unit name="persistenceUnit" transaction-type="JTA">

        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

        <jta-data-source>java:global/jdbc/flexypool</jta-data-source>

        <properties>
            <property 
                name="hibernate.hbm2ddl.auto" 
                value="update"/>

            <property 
                name="hibernate.show_sql" 
                value="true"/>

            <property 
                name="hibernate.dialect" 
                value="org.hibernate.dialect.HSQLDialect"/>

            <property 
                name="hibernate.transaction.jta.platform" 
                value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform"/>
        </properties>
    </persistence-unit>
</persistence>

While in a production Java EE environment we use an Application server specific DataSource configuration, for simplicity sake, I’m going to configure the FlexyPooldataSource using the DataSourceDefinition annotation:

@DataSourceDefinition(
    name = "java:global/jdbc/flexypool",
    className = "com.vladmihalcea.flexypool.FlexyPoolDataSource")
@Stateless
public class FlexyPoolDataSourceConfiguration {}

We now need to pass the actual DataSource properties to FlexyPool and this is done through the flexy-pool.properties configuration file:

flexy.pool.data.source.unique.name=unique-name
flexy.pool.data.source.class.name=org.hsqldb.jdbc.JDBCDataSource
flexy.pool.data.source.property.user=sa
flexy.pool.data.source.property.password=
flexy.pool.data.source.property.url=jdbc:hsqldb:mem:test
flexy.pool.metrics.reporter.jmx.auto.start=true

The actual DataSource is going to be created by the FlexyPoolDataSource on start-up.

Locating the actual DataSource from JNDI

If the actual DataSource is already configured by the Application Server, we can instruct FlexyPool to fetch it from JNDI. Let’s say we have the following DataSource configuration:

@DataSourceDefinition(
	name = "java:global/jdbc/default",
	className = "org.hsqldb.jdbc.JDBCDataSource",
	url = "jdbc:hsqldb:mem:test",
	initialPoolSize = 3,
	maxPoolSize = 5
)
@Stateless
public class DefaultDataSourceConfiguration {}

To proxy the JNDI DataSource, we need to configure FlexyPool like this:

flexy.pool.data.source.unique.name=unique-name
flexy.pool.data.source.jndi.name=java:global/jdbc/default
flexy.pool.metrics.reporter.jmx.auto.start=true

The FlexyPoolDataSource is defined alongside the actual DataSource:

@DataSourceDefinition(
	name = "java:global/jdbc/flexypool",
	className = "com.vladmihalcea.flexypool.FlexyPoolDataSource")
@Stateless
public class FlexyPoolDataSourceConfiguration {}

The JPA will have to fetch the FlexyPoolDataSource instead of the actual one:

<jta-data-source>java:global/jdbc/flexypool</jta-data-source>

In TomEE, because the DataSourceDefinitions are not lazily instantiated, the actual DataSource might not be available in the JNDI registry when the FlexyPoolDataSource definition is processed.

For this, we need to instruct FlexyPool to dely the JNDI lookup until the DataSource is actually requested:

flexy.pool.data.source.jndi.lazy.lookup=true

Conclusion

The last time I used Java EE was in 2008, on a project that was using Java EE 1.4 with EJB 2.1. After 7 years of using Spring exclusively, I’m pleasantly surprised by the Java EE experience. Arquillian is definitely my favourite add-on, since integration testing is of paramount importance in enterprise applications. CDI is both easy and powerful and I’m glad the dependency injection got standardised.

But the best asset of the Java EE platform is the community itself. Java EE has very strong community, willing to give you a hand when in need. I’d like to thank Steve Millidge (Founder of Payara and C2B2) for giving me some great tips on designing the FlexyPool Java EE integration, Alex Soto, Antonio Goncalves, Markus Eisele and all the other Java EE members whom I had some very interesting conversations on Twitter.

If you have enjoyed reading my article and you’re looking forward to getting instant email notifications of my latest posts, consider following my blog.