Skip to content

Java EE Configuration

Vlad Mihalcea edited this page Jan 22, 2018 · 13 revisions

Java EE Application servers

Maven dependency

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

In a Java EE environment, the DataSource is managed/provided by the Application Server through a JNDI lookup. Each Application server has a specific way of setting up a DataSource and the actual implementation doesn’t allow adjusting the pool size dynamically. In most Java EE applications, FlexyPool can only monitor the connection pool usage, without providing a dynamic pool sizing strategy.

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

Declarative Flexypool configuration

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 an:

  • 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 Optional Default value Description

flexy.pool.data.source.unique.name

false

N/A

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

flexy.pool.data.source.jndi.name

true

N/A

The JNDI DataSource location

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

true

false

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

true

N/A

The DataSource can be instantiated at Runtime using this Class name

flexy.pool.data.source.property.*

true

N/A

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

true

DataSourcePoolAdapter.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

true

DropwizardMetrics.FACTORY

Specifies the MetricsFactory used for creating Metrics

flexy.pool.metrics.reporter.log.millis

true

TimeUnit.MINUTES.toMillis(5)

Specifies the metrics log reported interval

flexy.pool.metrics.reporter.jmx.enable

true

true

Specifies if the jmx reporting should be enabled

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

true

false

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

flexy.pool.strategies.factory.resolver

true

N/A

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 Connection Provider

If you are using Hibernate, you can substitute the JPA configured DataSource (e.g. defined in persistence.xml) with FlexyPoolDataSource by adding the following hibernate.connection.provider_class property to your existing JPA configuration:

<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:/comp/env/jdbc/hsqldb</jta-data-source>

        <properties>
            <property name="hibernate.archive.autodetection"
                      value="class, hbm"/>

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

            <property name="hibernate.transaction.jta.platform"
                      value="org.hibernate.service.jta.platform.internal.BitronixJtaPlatform"/>

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

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

        </properties>
    </persistence-unit>
</persistence>

When Hibernate bootstraps, the FlexyPoolHibernateConnectionProvider will take the existing DataSource and decorate it with the FlexyPoolDataSource proxy.

You can now even pass FlexyPool configuration properies via JPA or Hibernate, as in the following example:

<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:/comp/env/jdbc/hsqldb</jta-data-source>

        <properties>
            <property name="hibernate.archive.autodetection"
                      value="class, hbm"/>

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

            <property name="hibernate.transaction.jta.platform"
                      value="org.hibernate.service.jta.platform.internal.BitronixJtaPlatform"/>

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

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

            <property name="flexy.pool.data.source.unique.name"
                      value="ds-jdbc-hsqldb"/>

        </properties>
    </persistence-unit>
</persistence>

In the example above, the flexy.pool.data.source.unique.name configuration property from the persistence.xml configuration file will override the one found in the flexy-pool.properties file.

Instantiating the actual DataSource at runtime

We can instantiate the actual DataSource when FlexyPool is initialized. For example, if we use the following properties:

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

and let’s say we are using the following DataSourceDefinition:

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

The persistence.xml uses the FlexyPoolDataSource JNDI location:

<?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>

The FlexyPoolDataSource is instantiated using the currently available configuration file and it’s made available through JNDI.

Locating the actual DataSource from JNDI

The actual DataSource might be already available in JNDI (e.g. java:global/jdbc/default).

The persistence.xml is configured like this:

<?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>

We now need to register the FlexyPoolDataSource under the java:global/jdbc/flexypool JNDI name:

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

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

And we need to instruct FlexyPool to locate the actual DataSource from JNDI:

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