Follow @vlad_mihalcea Imagine having a tool that can automatically detect if you are using JPA and Hibernate properly. Hypersistence Optimizer is that tool!

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.

Insert details about how the information is going to be processed DOWNLOAD NOW