Friday Apr 15, 2016

Using Coherence with Universal Connection Pool (UCP)

ucpcoherence

Coherence is an in-memory data grid solution that addresses the issues of working with distributed objects in memory (cache). Amongst its many features, Pluggable Cache Stores allows caching (i.e., load/store) contents from any persistence layer.

This way, the cache abstracts content persistence and loading through the CacheStore interface to be implemented by the user. The synchronization of updates, also decoupled from the persistence layer, is governed by the following strategies:

  • Refresh-Ahead / Read-Through: whether you want data to be loaded in the cache before being actually requested vs staleness of the data in the cache
  • Write-Behind / Write-Through: whether you expect better response time by doing the actualization of the data asynchronous vs immediate persistence of the change

Relational databases is the most common option for persistence, but its selection forces you to define an object-relational mapping from Java classes to the underlying relational model (using for example: hibernate, TopLink or any ad-hoc JPA implementation). But that is only half of the job to be done. It is also paramount to define how you will manage the connections to execute this persistence.

The following diagram depicts how Coherence persists in an RDBMS through the CacheStore interface:

The CacheStore is responsible for handling the connection to the database. Not only in terms of connection creation/pooling but also in terms of how to detect changes in the instances of the database it is connected to.
Connection management is critical when you are looking for extreme performance and high availability; hence it’s critical for the CacheStore to handle connection acquirement properly.

Oracle Universal Connection Pool (UCP) provides you not only all the intrinsic advantages of connection pooling (connection re-use, management, availability, purge, etc.) but it also leverages the possibility to use all the features you have when connected to a RAC environment:

  • Runtime Connection Load Balancing (RCLB)
  • Fast Connection Failover (FCF)
  • Transaction Affinity
  • Built-in support for Database Resident Connection Pooling (DRCP) and Application Continuity (AC)

By taking this approach, you are not only setting the relationship between your cache and your persistence layer. You are also optimizing the configuration and management with your underlying RAC, by exploiting all its features in terms of connection handling.

For more information about UCP, please refer to: Introduction to UCP.
In a previous article we already discussed these features and how to exploit them from a JBoss Web application:
Using Universal Connection Pooling (UCP) with JBoss AS
In this article we are going to show you how to use UCP from Coherence using Pluggable Cache Stores, hence also making it available for any type of Coherence client.

1. Download and install coherence standalone, UCP and Oracle JDBC Driver.

You can skip this step if you already have coherence.jar, ucp.jar and ojdbc7.jar.
Download “Coherence Stand-Alone Install” from this location.
Unzip the downloaded file.
Run the universal installation jar:

java -jar fmw_12.2.1.0.0_coherence.jar

During install, select an Oracle Home location. In this location you will find the coherence jar that we will be using during this demo: 
ORACLE_HOME/coherence/lib/coherence.jar.

Download UCP and Oracle JDBC Driver (ucp.jar and ojdbc.jar) UCP JDBC

For this sample, I copied these jars are in the home directory (~) and coherence.jar to ~/ucpcoherence dir:

~/ucpcoherence/coherence.jar
~/ucp.jar
~/ojdbc8.jar

2. Configure Cache and CacheStore.

You need to indicate coherence the scheme for your cache. The scheme will define its behavior (such as if it’s local, replicated or distributed, etc.). For our configuration, these are the most important things to understand:

  • cache-mapping: this will indicate coherence what cache-names (ids) will match to this specific type (scheme). In our sample we’ll create cache “test1” to match it with “test*”, which in turns will associate with scheme-name “example-distributed” and under this scheme-name we’ll define our cache-scheme.
  • class-name (in cachestore-scheme): here we will inject into our distributed cache the name of the class that will handle the persistence (load / loadAll / store / storeAll / erase / eraseAll) operations in our cache. In our case it will be ucp_samples.EmployeeCacheStore, which we will define later in this article.
  • init-params (in class-scheme): here you can specify values that will be used in the constructor of our class.
~/ucpcoherence/example-ucp.xml:

<?xml version="1.0"?>

<!DOCTYPE cache-config SYSTEM "cache-config.dtd">

<cache-config>

<caching-scheme-mapping>
<cache-mapping>

<cache-name>test*</cache-name>
<scheme-name>example-distributed</scheme-name>
</cache-mapping>

</caching-scheme-mapping>
<caching-schemes>
<distributed-scheme>

<scheme-name>example-distributed</scheme-name>

<service-name>DistributedCache</service-name>
<backing-map-scheme>
<read-write-backing-map-scheme>
<internal-cache-scheme>
<local-scheme />
 </internal-cache-scheme>
<cachestore-scheme>
<class-scheme>

<class-name>ucp_samples.EmployeeCacheStore</class-name>
<init-params>
<init-param>
<param-type>java.lang.String</param-type>
<param-value>jdbc:oracle:thin:@//localhost:1521/cdb1</param-value>
</init-param>
<
init-param>
<param-type>java.lang.String</param-type>
<
param-value>scott</param-value>
</init-param>
<init-param>
<param-type>java.lang.String</param-type>
<param-value>tiger</param-value>
</init-param>
</
init-params>

</class-scheme>
</cachestore-scheme>
</read-write-backing-map-scheme>
</backing-map-scheme>
<autostart>true</autostart>

</distributed-scheme>
</caching-schemes>

</cache-config>

3. Provide CacheStore Implementation.

As configured in previous file, you need to provide an implementation for CacheStore that will execute its methods when objects in the cache are added or requested (it will store or load if the object is not on the cache). We provide an implementation for the load method and the constructor of the class (which shows how to use UCP). You can define the behavior for the rest of the methods as part of your test.
Notice that the values for UCP can be changed/monitored through JMX as it was explained in this article.

To check more in how to use UCP with Hibernate you can check in this article.

public class EmployeeCacheStore implements CacheStore {

private PoolDataSource pds = null;
private int INITIAL_POOL_SIZE = 5;

private Connection getConnection() throws SQLException {

return pds.getConnection();
}

/**
* Constructor for the CacheStore, parses initial values and sets the
* connection pool.
*
*
@param url
*
@param user
*
@param password
*/

public EmployeeCacheStore(String url, String user, String password) {

try {

// Create pool-enabled data source instance
 pds = PoolDataSourceFactory.getPoolDataSource();

// set the connection properties on the data source
pds.setConnectionFactoryClassName(
    "oracle.jdbc.pool.OracleDataSource");
pds.setURL(url);
pds.setUser(user);
pds
.setPassword(password);

// Override pool properties
pds.setInitialPoolSize(INITIAL_POOL_SIZE);
pds.setConnectionPoolName(this.getClass().getName());

} catch (SQLException e) {

e.printStackTrace();
}
}

/**
* When an object is not in the cache, it will go through cache store to
* retrieve it, using the connection pool. In this sample we execute a
* manual object relational mapping, in a real
-life scenario hibernate, or
* any other ad
-hoc JPA implementation should be used.
*/

@Override
public Employee load(Object employeeId) {

Employee employee = null;
try {

PreparedStatement ps = getConnection().prepareStatement("select * from employees where employee_id = ?");
ps.setObject(1, employeeId);
ResultSet rs = ps.executeQuery();

if (rs.next()) {
employee = new Employee();
employee.setEmployeeId(rs.getInt("employee_id"));
employee.setFirstName(rs.getString("first_name"));
employee.setLastName(rs.getString("last_name"));
employee.setPhoneNumber(rs.getString("phone_number"));
}
ps.close();
rs.close();

} catch (SQLException e) {
e.printStackTrace();

}

return employee;

}

}

4. Provide the Java Bean.

This is the class that will live in our cache. It’s a simple Java Bean which needs to implement Serializable in order to be able to be shared across the nodes of the cache. In a real-life scenario you will want to implement coherence’s PortableObject instead of only Serializable, so you will be using coherence ultra-optimized mechanisms to share/store objects: Portable Object Format Serialization (POF).
Note: getters/setters/constructors are removed to be easier to read this example. Also note that your implementation of toString() is what you are going to see in coherence’s console.

public class Employee implements Serializable {

int employeeId;
String firstName;
String lastName;
String email;
String phoneNumber;
Date hireDate;
String jobId;

@Override
public String toString() {
return getLastName() + ", "
+ getFirstName() + ": "
+ getPhoneNumber();
}
}

5. Configure Operational File.

In order to provide some specific operational values for your cache, you will need to provide the following operational configuration file.
Take particular attention for the name of the cluser “cluster_ucp”, the address/port you will be synchronizing with other nodes of the cluster “localhost:6699” and the name of the configuration file you will use (you set this through the system property parameter “tangosol.coherence.cacheconfig=example-ucp.xml”, defined in 2nd step.
Note: since version 12.2.1 you no longer need to use prefix “tangosol”.

~/ucpcoherence/tangosol-coherence-override.xml

<?xml version='1.0'?>
<!DOCTYPE coherence SYSTEM "coherence.dtd">
<coherence>

<cluster-config>
<member-identity>
<cluster-name>cluster_ucp</cluster-name>

</member-identity>
<unicast-listener>

<address>localhost</address>
<port>6699</port>
<time-to-live>0</time-to-live>
<well-known-addresses>
<socket-address id="1">
<address>localhost</address>
<port>6699</port>
</socket-address>
</well-known-addresses>

</unicast-listener>
</cluster-config>
<services>

<service id="3">
<service-type>DistributedCache</service-type>
<service-component>PartitionedService.PartitionedCache</service-component>

</service>
</services>
<configurable-cache-factory-config>

<class-name system-property="tangosol.coherence.cachefactory">com.tangosol.net.ExtensibleConfigurableCacheFactory</class-name>
<init-params><init-param><param-type>java.lang.String</param-type>
<param-value system-property="tangosol.coherence.cacheconfig">example-ucp.xml</param-value>
</init-param></init-params>

</configurable-cache-factory-config>

</coherence>


6. Start Cache nodes and client.

From command line you can start the nodes of your cache through DefaultCacheServer class and the following parameters:
(from ~/ucpcocherence, being ./ucp_samples/bin the output folder for your eclipse project or the place where you have your compiled custom classes)

../jdk1.8.0_60/jre/bin/java -Dtangosol.coherence.override=tangosol-coherence-override.xml -Dtangosol.coherence.cluster=cluster_ucp -cp coherence.jar:../ucp.jar:../ojdbc8.jar:./ucp_samples/bin com.tangosol.net.DefaultCacheServer

Note: as stated before, since 12.2.1 you no longer need to use tangosol prefix, it will also work with coherence.cluster.

You can check by the output the name of the cluster (cluster_ucp), the addresses it’s listening (localhost:6699) and the name of the member you just started (Id=1).

If you issue the same command on a separate process to start 2nd node:

You can check member id = 2 joining the cluster (it shows in both processes). This way now you have 2 nodes working for this cluster.

Lastly, you start the client for the cluster (which indeed is a new member itself) using CacheFactory class and running this command:

../jdk1.8.0_60/jre/bin/java -Dtangosol.coherence.override=tangosol-coherence-override.xml -Dtangosol.coherence.cluster=cluster_ucp -cp coherence.jar:../ucp.jar:../ojdbc8.jar:./ucp_samples/bin com.tangosol.net.CacheFactory

Note that if you wouldn’t want your client to be a storage member you can provide the option -Dtangosol.coherence.distributed.localstorage=false to achieve this behavior. This can also be done via configuration.

You see member id = 3 with command line option to interact with the cache.

The first thing you need to do is to start a cache with the same scheme as the one we defined. In order to do that you use the same name pattern we defined in cache-mapping using a name matching “test*”. So you issue:

cache test1

And you will notice now that the prompt is with this cache

Map (test1):

Now you try to load the first object by issuing:

get 100

You’ll notice for each new object loaded in the cache the additional time it takes to read its value from the database and you’ll see the output of the object retrieved in the console (executing Employee.toString() method).

Run again get 100 and you’ll notice the difference in the response time of using an object that’s already in the cache.

7. Interact with the cache from Java code

To interact with the cache from a java class it’s even easier. The only thing you should do is add the VM parameter -Dtangosol.coherence.override=tangosol-coherence-override.xml (pointing to the same one that started the nodes) to the following code:

public class EmployeeQueryCache {

public static void main(String[] args) {

// define cache
NamedCache cache = CacheFactory.getCache("test1");

// retrieve object
Employee employee = (Employee) cache.get(101);

// update it
employee.setPhoneNumber("(650)-500-5000");

// print in console
System.out.println(employee);

// store it
cache.put(101, employee);

}

}

Since coherence 12.2.1 the interface NamedCache supports generics, so you might be able to update previous code with:

NamedCache<Integer, Employee> cache = CacheFactory.getTypedCache("test1", TypeAssertion.withoutTypeChecking());

Monday Feb 15, 2016

Get Oracle JDBC drivers from the Oracle Maven Repository - NetBeans, Eclipse & Intellij

Oracle JDBC drivers and Universal Connection Pool (ucp.jar) are now available in the Oracle Maven Repository. The drivers and ucp.jar from 11.2.0.4, 12.1.0.1 and 12.1.0.2 releases are available in the Oracle Maven Repository. Complementary jars such as simplefan.jar and ons.jar can also be downloaded from the same location. This blog outlines the steps for successfully downloading the required version of these jar files while using NetBeans, Eclipse and Intellij IDEs. These steps are similar while using other IDEs. Please refer to Get Oracle JDBC drivers and UCP from the Oracle Maven Repository (without IDEs) for a sample pom.xml, settings.xml and settings-security.xml

Steps to create a Maven project and download the Oracle JDBC drivers and UCP.
  • Create a New Project: Create a Maven Java application as per the screenshots
  • Update pom.xml: Include GAV(Group ID, Artifact Id, Version ID) for ojdbc7.jar and/or ucp.jar in pom.xml as shown below. Refer to a sample pom.xml in the blog
    <dependency> <groupId>com.oracle.jdbc</groupId> <artifactId>ojdbc7</artifactId> <version>12.1.0.2</version> </dependency>

  • Create the settings-security.xml and settings.xml files: The Oracle Maven repository requires a user registration including a valid username and an encrypted password to be passed in settings.xml and settings-security.xml.
  • Update Bundled Maven path: Oracle Maven Repository requires Maven version 3.2.5 or higher, therefore, you need to update the bundled maven version in the IDE.
  • Maven Build/Package/Compile: Use "mvn compile", "mvn package" or "mvn install" to build the Java application.
  • Verify the successful completion of the download: Check the local maven repository and make sure that JDBC drivers are downloaded at "USER_HOME/.m2/repository/com/oracle/jdbc/". Check out the successful download message in the blog.
  • Download Instructions for NetBeans

    Download Instructions for Eclipse

    Download Instructions for Intellij

    Download Instructions for NetBeans

    NetBeans Version: NetBeans IDE 8.1
    Maven Version Used: Apache-Maven-3.3.9

    Step#1: Click on File --> New Project and create a Maven project

    NetBeans_NewProject

    Step#2: Provide Name and Location

    NetBeans_ProjectName and Location

    Step#3: Update pom.xml to include JDBC drivers and UCP as dependencies and Run --> Build project

    NetBeans Build the project

    Step#4: Successful Download of JDBC drivers

    NetBeans- successful download

    Download Instructions for Eclipse

    Eclipse Version: Mars.1 Release (4.5.1)
    Maven Version Used: Apache-Maven-3.3.9

    Step#1:Click on File --> New --> Maven Project

    Eclipse_NewProject

    Step#2: Specify the project location

    Eclipse_Location

    Step#3: Choose the Archetype

    Eclipse_ProjectArchetype

    Step#4: Choose project name

    Eclipse Build the project

    Step#5: Run --> Run Configurations. Change the bundled maven version to a higher version than 3.2.5

    Eclipse- successful download

    Step#6: Update pom.xml to include JDBC and UCP dependencies. Click on the project --> Run as --> Maven Build

    Eclipse- Build project

    Download Instructions for Intellij

    NetBeans Version: IntelliJ IDEA 15
    Maven Version Used: Apache-Maven-3.3.9

    Step#1: File --> New --> Project. Select "Create from archetype"

    Intellij_NewProject

    Step#2: Provide GAV for the project

    Intellij_select GAV

    Step#3: Change the bundled maven version to something higher than 3.2.5 --> Build project

    Intellij- Change the maven version

    Step#4: Enter the project name to complete the process.

    Intellij- Enter project name and location

    Step#5: Update pom.xml to include JDBC and UCP dependencies. Click on the maven project--> compile/install to successfully download the JDBC drivers and UCP.

    Intellij- Compile or build

    Get Oracle JDBC drivers and UCP from Oracle Maven Repository (without IDEs)

    The Oracle JDBC drivers and Universal Connection Pool (UCP) are now available on the Oracle Maven Repository https://maven.oracle.com . The versions made available on this repository are 11.2.0.4, 12.1.0.1 and 12.1.0.2. Complementary jars such as simplefan.jar and ons.jar can also be downloaded from Oracle Maven Repository. Follow the steps mentioned in this blog to successfully download the required version of Oracle JDBC drivers and UCP. Please refer to "Get Oracle JDBC drivers and UCP from the Oracle Maven Repository - NetBeans, Eclipse, Intellij" for steps while using NetBeans, Eclipse and Intellij.

    (1) Setting up Maven:

    Step#1: Download Maven

    If you do not have Maven installed already, download and install it from the website: http://maven.apache.org

    Step#2: Update M2_HOME and JAVA_HOME environment variables

    Make sure to update M2_HOME to point to the path where Maven is installed and JAVA_HOME to point to the location where the JDK is installed. If you require a specific Java version then set it using these system arguments. -Dmaven.compiler.source=1.8 -Dmaven.compiler.target=1.8

    (2) Customizing Maven Settings

    Step#1: Create a settings.xml file

    The settings.xml file is required for downloading Oracle JDBC drivers and UCP. You must create a new one if it does not exist already. The Maven settings.xml file is kept in the local maven repository ( {USER_HOME}/.m2/ ) that is usually under the user home directory.
    For example: If the username is test then the path will be
  • Unix : /home/test/.m2/settings.xml
  • Windows : C:\Users\test\.m2\settings.xml
  • Step#2: Registering with the Oracle Maven site

    The Oracle Maven repository requires a valid user registration and the user should also accept the terms and conditions (T&Cs) by logging into http://maven.oracle.com . This username will be used in settings.xml .

    Step#3: Create a settings-security.xml

    Create a settings-security.xml file that holds the master password information under the local maven repository. Refer to Step#1 for local maven repository (../.m2/.) path
    Use the following commands to generate a master password in Maven and add the output of this command to settings-security.xml as shown in the sample
    "mvn -encrypt-master-password <any_master_password>" or "mvn -emp <any_master_password>"
    Sample settings-security.xml :
    <settingsSecurity> <master>{By8wW7YcTxAHof0MF4Z3wPKboywhGJvxHD9m0NvHA2U=}</master> </settingsSecurity>

    Step#4: Encrypt the user password before using it in settings.xml

    Encrypt the user password (the one used to accept T&Cs on http://maven.oracle.com) before using it in settings.xml.
    Use the following commands to encrypt the user password and update settings.xml as shown in the sample
    "mvn -encrypt-password <user_password>" or "mvn -ep <user_password>"
    Sample settings.xml
    <settings> <proxies> <proxy> <active>true</active> <protocol>http</protocol> <host>proxy.mycompany.com</host> <nonProxyHosts>mycompany.com</nonProxyHosts> </proxy> </proxies> <servers> <server> <id>maven.oracle.com </id> <username>firstname.lastname@test.com</username> <password>{pnwmhVnzdM8H3UAneUKLmaHGZCoaprbMQ/Ac5UktvsM=}</password> <configuration> <basicAuthScope> <host>ANY </host> <port>ANY </port> <realm>OAM 11g </realm> </basicAuthScope> <httpConfiguration> <all> <params> <property> <name>http.protocol.allow-circular-redirects </name> <value>%b,true </value> </property> </params> </all> </httpConfiguration> </configuration> </server> </servers> </settings>

    (3) Create a project to test Maven download

    Step#1: Create a pom.xml and specify GAV for JDBC drivers and UCP

    Add the following GAV details for downloading JDBC driver or UCP from the required version.
    <dependencies> <dependency> <groupId>com.oracle.jdbc</groupId> <artifactId>ojdbc7</artifactId> <version>12.1.0.2</version> </dependency> <dependency> <groupId>com.oracle.jdbc</groupId> <artifactId>ucp</artifactId> <version>12.1.0.2</version> </dependency> </dependencies> <repositories> <repository> <id>maven.oracle.com</id> <name>oracle-maven-repo</name> <url>https://maven.oracle.com</url> <layout>default</layout> <releases> <enabled>true</enabled> <updatePolicy>always</updatePolicy> </releases> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>maven.oracle.com</id> <name>oracle-maven-repo</name> <url>https://maven.oracle.com</url> <layout>default</layout> <releases> <enabled>true</enabled> <updatePolicy>always</updatePolicy> </releases> </pluginRepository> </pluginRepositories>

    Step#2: Create 'src' and 'target' directories

    All Java source files must be placed under src directory. Example: /src/main/java/<foldername>/<filename> In addition, create a target directory where the compiled classes will be placed.

    (4) Testing the download of JDBC and UCP

    Step#1: Compile the Maven Project

    Use the following commands to compile or install or package to test the download.
    "mvn –s settings.xml package" or "mvn -s settings.xml compile" or "mvn -s settings.xml install"
    The output of a successful download will look as shown below:
    [INFO] Building jar: /home/test/maven/public-repo-test/target/jdbc-driver-test.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 2.437 s [INFO] Finished at: 2015-10-01T12:58:25-07:00 [INFO] Final Memory: 9M/282M [INFO] ------------------------------------------------------------------------

    Step#2: Check the downloaded JDBC drivers and UCP

    If the build was successful, then the JARs and POMs will be downloaded onto the local maven repository at ~/.m2/repository/com/oracle/jdbc/ojdbc7/12.1.0.2/ . Note that OJDBC7.jar will download all the dependent jar files such as osdt_core.jar, xdb6.jar, xmlparserv2.jar etc., . Each download has its own JAR and POM files.
    Sample output:
    [test@mymachine jdbc]$ pwd /home/test/.m2/repository/com/oracle/jdbc [test@mymachine jdbc]$ ls -lt total 11 drwxr-xr-x+ 3 test dba 3 Oct 1 11:13 osdt_core drwxr-xr-x+ 3 test dba 3 Oct 1 11:13 osdt_cert drwxr-xr-x+ 3 test dba 3 Oct 1 11:13 oraclepki drwxr-xr-x+ 3 test dba 3 Oct 1 11:13 xmlparserv2 drwxr-xr-x+ 3 test dba 3 Oct 1 11:13 orai18n drwxr-xr-x+ 3 test dba 3 Oct 1 11:13 xdb6 drwxr-xr-x+ 3 test dba 3 Oct 1 11:13 ojdbc7

    Wednesday Oct 21, 2015

    OOW SF 2015 - Session Recommendations

    JavaOne SF 2015  Session recommendations

    High Availability with Java EE Containers, JDBC, and Java Connection Pools [BOF7732]
    Monday, Oct 26, 8:00 p.m. | Parc 55—Mission


    Implement Cloud Data Services with Java 8 Nashorn [CON4405]
    Tuesday, Oct 27, 4:00 p.m. | Hilton—Continental Ballroom 1/2/3


    Java Connection Pool Performance and Scalability with Wait-Free Programming [CON2158]
    Wednesday, Oct 28, 4:30 p.m. | Hilton—Continental Ballroom 1/2/3


    OOW SF 2015 - Session recommendations

    Java Virtual Machine Cookbook [UGF2720]
    Sunday, Oct 25, 9:00 a.m. | Moscone West—3011


    Next-Generation Database:  Implement Cloud Data Services with Java 8 Nashorn  [CON8461]
    Monday, Oct 26, 5:15 p.m. | Moscone South—308


    Next-Generation Database: Java Connection Pool for Multitenant and Sharded Databases [CON8460]
    Monday, Oct 26, 2:45 p.m. | Moscone South—308


    Integrate Master Data with Big Data on Hadoop and Spark [CON8459]
    Wednesday, Oct 28, 3:00 p.m. | Moscone South—308


    Next-Gen Database Enhancements for Java Application Performance and Scalability [CON10310]
    Thursday, Oct 29, 2:30 p.m. | Moscone South—307


    Dialog with the Oracle Database Java Developers and Architects [MTE9501]
    Tuesday, Oct 27, 7:15 p.m. | Moscone South—305


    Thursday Sep 17, 2015

    Using Universal Connection Pooling (UCP) with JBoss AS

    Even though WebLogic with Active GridlLink is Oracle's suggested approach to deploy Java applications that use Oracle Real Applications Clusters (RAC), there might be scenarios in which you can't make that choice (e.g.: certification issues, licensing, library dependency, etc.). Application servers and their database connection pool mechanisms might end up being a bottleneck in the architecture of your applications and a critical component to provide performance, scalability and high-availability.

    UCP, besides providing connection pooling and all its intrinsic benefits, leverages features specific from RAC.
    These features are:

    • Runtime Connection Load Balancing (RCLB)
    • Fast Connection Failover (FCF)
    • Transaction Affinity
    • Built-in support for Database Resident Connection Pooling (DRCP) and Application Continuity (AC)

    You won't be able to exploit this features by using out of the box JBoss' connection pools.

    In this simple example we will show you how to configure UCP to be used in a JBoss deployed application, wrapping UCP around a Singleton Enterprise Java Bean (EJB) and using a Servlet as client to the wrapper. We will also show you how to monitor and administer UCP using JBoss JMX-Console without needing extra configuration, coding or deployment.

    In an ideal scenario the application server would provide us the possibility to set a custom implementation of a connection pooling (by implementing an interface, for example), but that is not the case with JBoss. In JBoss you can configure all the necessary information to create a connection (driver, url, user, password, etc) and some configuration for the pool (minimum size, maximum size, etc), but you can't configure the class that is going to provide the implementation for connection pooling. There's a workaround for that in this article: https://blogs.oracle.com/dev2dev/entry/how_to_use_oracle_universal1 , which explains how to set a UCP data-source using Spring). But for both scenarios you're declaring beans, or wrappers, to contain the UCP configuration.

    1. Download and start JBoss AS:

    You can download it from this site: http://jbossas.jboss.org/downloads/.
    For this sample we used “JBoss AS 6.1.0.Final”: http://download.jboss.org/jbossas/6.1/jboss-as-distribution-6.1.0.Final.zip.
    After unzipping the file you should set your JAVA_HOME env variable to an existing JDK directory (jdk7, it won't work with jdk8).
    To start the app server you go to the unzipped directory /bin and run standalone.sh or standalone.bat, depending on your OS (you can skip this step if you install JBoss Developer Studio.
    You can check successful start-up by opening a browser to http://localhost:8080/

    2. Download and install JBoss Developer Studio:

    This is also an optional step, you can download JBoss Developer Studio from http://www.jboss.org/products/devstudio/download/ after unzipping you start it by running jbdevstudio executable. This is an extension of Eclipse with JBoss specific plugins installed.

    JBoss Developer Studio

    3. Configure JBoss AS in JBoss Developer Studio:

    In “servers” view choose “new” / “server”, select “JBoss Community, JBoss AS 6.x”, select “Home Directory” to the previously downloaded JBoss AS and leave default values.
    After this step you can start/stop application server from JBoss Developer Studio and deploy / un-deploy applications by selecting “Add and Remove..” in Server's contextual menu.

    4. Add ucp.jar and ojdbc.jar both to Jboss's runtime:

    Add both jars in (JBOSS_HOME/common/lib) and in project's build path (project / properties / Java Build Path / libraries). You could also deploy this jars as specifics for the app, off course.

    5. Create the Singleton Wrapper for UCP as this:

    @Startup
    @Singleton(name = "UcpDemoSingletonWrapper")
    public class UcpDemoSingletonWrapper {

    @Resource(name = "connectionFactoryClassName")
    String connectionFactoryClassName;

    @Resource(name = "url")
    String url;

    @Resource(name = "user")
    String user;

    @Resource(name = "password")
    String password;

    @Resource(name = "initialPoolSize")
    Integer initialPoolSize;

    /**
    * Initialize method for the Singleton. This wrapper
    * could also implement JMX APIs to be able to be
    * managed through the JMX Console (or any other 
    * JMX-compliant Tool)
    */
    @PostConstruct
    void init() {

    try {

    // Retrieve values from bean's configuration
    pds.setConnectionFactoryClassName(connectionFactoryClassName);
    pds.setURL(url);
    pds.setUser(user);
    pds.setPassword(password);

    /**
    * Override example's desired pool
    * properties, will be
    * used through JMX Console
    * later in this example
    */
    pds.setInitialPoolSize(initialPoolSize);
    pds.setConnectionPoolName(this.getClass().getName());

    } catch (Exception e) {

    e.printStackTrace();
    }

    }

    // Wrapped pool
    private PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource();

    /**
    * Retrieves connections using wrapped pool
    *
    * @return a pooled connection
    * @throws SQLException
    */
    public Connection getConnection() throws SQLException {

    /**
    * Trivial implementation to retrieve connections.
    * Logic intrinsic to the pool could be set here.
    */
    return pds.getConnection();

    }

    }

    6. Create EJB configuration file (WEB-INF/ejb-jar.xml) with this values:

    <ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" version="3.1" metadata-complete="false">

    <enterprise-beans>

    <session>

    <ejb-name>UcpDemoSingletonWrapper</ejb-name>
    <env-entry>

    <env-entry-name>connectionFactoryClassName</env-entry-name>
    <env-entry-type>java.lang.String</env-entry-type>
    <env-entry-value>oracle.jdbc.pool.OracleDataSource</env-entry-value>

    </env-entry>

    <env-entry>

    <env-entry-name>url</env-entry-name>
    <env-entry-type>java.lang.String</env-entry-type>
    <env-entry-value>jdbc:oracle:thin:@//myhost:1521/cdb1</env-entry-value>

    </env-entry>

    <env-entry>

    <env-entry-name>user</env-entry-name>
    <env-entry-type>java.lang.String</env-entry-type>
    <env-entry-value>myuser</env-entry-value>

    </env-entry>

    <env-entry>

    <env-entry-name>password</env-entry-name>
    <env-entry-type>java.lang.String</env-entry-type>
    <env-entry-value>mypwd</env-entry-value>

    </env-entry>

    <env-entry>

    <env-entry-name>initialPoolSize</env-entry-name>
    <env-entry-type>java.lang.Integer</env-entry-type>
    <env-entry-value>5</env-entry-value>

    </env-entry>

    </session>

    </enterprise-beans>

    </ejb-jar>

    7. Create the client as this sample servlet:

    /**
    * Simple client to show how to use wrapped ucp's EJB
    *
    */
    @WebServlet("/UcpDemoServletClient")
    public class UcpDemoServletClient extends HttpServlet {

    @EJB
    UcpDemoSingletonWrapper ucpWrapper;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    doPost(request, response);

    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    try (

    // Get connection from pool, for this trivial example we avoid ORM
    Connection connection = ucpWrapper.getConnection();
    Statement statement = connection.createStatement();
    ResultSet resultSet = statement.executeQuery("select * from test_table")) {

    // Send output to response
    PrintWriter printWriter = response.getWriter();

    while (resultSet.next()) {

    printWriter.println(resultSet.getString(1));

    }

    } catch (SQLException sqlException) {

    throw new ServletException(sqlException);

    }

    }

    }

    8. From Servers's view execute “Publish” and “Start” (or just execute from project's context menu “run in server”).

    JBoss deploy

    9. Administer EJB from JMX-Console:

    Login to http://localhost:8080/jmx-console/
    Look for UCP's MBEANs:
    oracle.ucp.admin.UniversalConnectionPoolManagerMBean
    oracle.ucp.admin.UniversalConnectionPoolMBean

    JMX Console


    Invoke getConnectionPoolName (you will get what was setted on the EJB, “ucp_demo.UcpDemoSingletonWrapper").
    Go through oracle.ucp.admin.UniversalConnectionPoolMBean and look for availableConnectionsCount.

    10. Invoke servlet:

    Typing in a browser http://localhost:8080/ucp_jboss_demo_web_project/UcpDemoServletClient
    Check that after several executions the amount of available connections remains constant.
    Do the same but not closing the connections in the wrapper (remove from the try with resources block, avoiding connection.close())
    Or just execute Connection connection = ucpWrapper.getConnection(); without closing the connection.
    You will check that available connections decreases until exception is thrown.
    Use JMX-console to administer life-cycle of UCP (start / stop / purge connection pool, etc.).
    A full-fledged test would include modifications in the RAC (shutting down/up nodes, checking load balance between them, validating transaction affinity, etc.), in these scenarios UCP would show all its capacities and features (as described at the beginning of this article).

    Thursday May 21, 2015

    UCP with Spring Framework

    This article illustrates the steps to use Oracle Universal Connection Pool (UCP) with the Spring framework, using a sample application built using the JDBC template.

    • Assume there is a simple table EMP in the database with a single column “name” that is loaded with employee information (i.e., employee names).
    • Consider the following example DAO class in the package “test”:
    • The following is an example of the Row mapper implementation class for the EMP table:
    • The following class is the example of a java class that uses the JDBC Template for implementing the business logic:
    • The XML configuration file should specify UCP's oracle.ucp.jdbc.PoolDataSourceImpl as the data source class along with relevant connection pool properties, such as the initial-pool-size, max-pool-size, etc. For this sample, the XML configuration file is named "HelloAppConf.xml".
      <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- Initialization for data source --> <bean id="dataSource" class="oracle.ucp.jdbc.PoolDataSourceImpl"> <property name="connectionFactoryClassName" value="oracle.jdbc.pool.OracleDataSource"/> <property name="URL" value="jdbc:oracle:thin:@//host:port/service_name"/> <property name="user" value="scott"/> <property name="password" value="tiger"/> <property name="maxPoolSize" value="10"/> <property name="initialPoolSize" value="5"/> </bean> <!-- Definition for EmpJDBCTemplate bean --> <bean id="EmpJDBCTemplate" class="test.EmpJDBCTemplate"> <property name="dataSource" ref="dataSource"/> </bean> </beans>
    • The main application code looks like the following. The application using the JDBC template will internally use the Universal Connection Pool (UCP) for connection check-outs and check-ins.

    Use UCP with Hibernate

    Hibernate ORM is an object/relational mapping framework for Java. Out-of-box, Hibernate supports two open source connection pools C3P0 and Proxool.

    Universal Connection Pool (UCP) is Oracle’s feature-rich Java connection pool, replacing the Implicit Connection Cache (ICC), which has been de-supported in Oracle Database 12c. Besides standard connection pooling features, UCP has also been designed for scalability and high-availability during planned and unplanned database downtimes, with seamless support for Oracle Real Application Clusters (RAC), Active Data Guard (ADG) and Global Data Services (GDS).

    This article illustrates a couple of options for using Oracle Universal Connection Pool (UCP) with Hibernate. The code samples are for demonstration purpose only.

    Using UCP data source via JNDI lookup

    If the target application can use JNDI to lookup a data source (for example, when using Tomcat), then users can specify a UCP data source for Hibernate to use, by using the Hibernate property "hibernate.connection.datasource". This can be done either declaratively in a Hibernate configuration file (XML or properties file), or programmatically on org.hibernate.cfg.Configuration.

    For example, after binding a UCP PoolDataSource in JNDI, users can specify in hibernate.cfg.xml:

    <hibernate-configuration> <session-factory> <property name="hibernate.connection.datasource"> java:comp/env/UCP_PoolDataSource_JNDI_NAME </property>

    All the UCP connection pool and data source configurations should be done on the PoolDataSource, before binding it in JNDI.

    Using UCP data source with Spring framework

    If the target application can use Spring along with Hibernate, then UCP data sources can be configured in Spring configuration XML files.

    For example:

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- Initialization for data source --> <bean id="dataSource" class="oracle.ucp.jdbc.PoolDataSourceImpl"> <property name="connectionFactoryClassName" value="oracle.jdbc.pool.OracleDataSource"/> <property name="URL" value="jdbc:oracle:thin:@//host:port/service_name"/> <property name="user" value="scott"/> <property name="password" value="tiger"/> <property name="maxPoolSize" value="10"/> <property name="initialPoolSize" value="5"/> </bean> <!-- Definition for EmpJDBCTemplate bean --> <bean id="EmpJDBCTemplate" class="test.EmpJDBCTemplate"> <property name="dataSource" ref="dataSource"/> </bean> </beans>

    Implementing UCP as a Hibernate ConnectionProvider

    If the target application is standalone and cannot use the two options above, Hibernate provides the ConnectionProvider interface to integrate with a third-party JDBC connection provider. Users need to implement this interface and then specify the implementation class to Hibernate.

    The ConnectionProvider interface has changed with different Hibernate versions. As of Hibernate 4.x, the interface is org.hibernate.engine.jdbc.connections.spi.ConnectionProvider. We will use that version for illustration.

    The following is an example implementation of ConnectionProvider that plugs in a UCP data source. It has been tested using Hibernate 4.3.8. Note that the Hibernate 4.x version of the interface no longer provides the configure(Properties hibernateProperties) method, so this example simply overrides the DriverManagerConnectionProviderImpl which provides a similar method. An alternative is for the interface implementation to load the configuration properties from its own properties file or explicitly from the hibernate.properties file.

    /* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. */ package oracle.ucp.hibernate.sample; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; import java.sql.Connection; import java.sql.SQLException; import java.util.Map; import java.util.logging.Logger; import oracle.ucp.UniversalConnectionPoolException; import oracle.ucp.admin.UniversalConnectionPoolManager; import oracle.ucp.admin.UniversalConnectionPoolManagerImpl; import oracle.ucp.jdbc.PoolDataSource; import oracle.ucp.jdbc.PoolDataSourceFactory; import org.hibernate.HibernateException; import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; public class UCPConnectionProvider extends DriverManagerConnectionProviderImpl { private PoolDataSource pds; private static final Logger logger = Logger.getLogger(UCPConnectionProvider.class.getCanonicalName()); private static final String URL = "hibernate.ucp.url"; private static final String USER = "hibernate.ucp.user"; private static final String PASSWORD = "hibernate.ucp.password"; private static final String CONN_FACTORY = "hibernate.ucp.connectionFactoryClassName"; private static final String POOL_NAME = "hibernate.ucp.connectionPoolName"; private static final String MAX_POOL_SIZE = "hibernate.ucp.maxPoolSize"; private static final String MIN_POOL_SIZE = "hibernate.ucp.minPoolSize"; private static final String INITIAL_POOL_SIZE = "hibernate.ucp.initialPoolSize"; private static final String FAN_ENABLED = "hibernate.ucp.fastConnectionFailoverEnabled"; private static final String ONS_CONFIG = "hibernate.ucp.onsConfiguration"; private static final String CONN_VALIDATE = "hibernate.ucp.validateConnectionOnBorrow"; public UCPConnectionProvider() { try { pds = PoolDataSourceFactory.getPoolDataSource(); logger.finest("PoolDataSource initialized: " + pds); } catch (Exception exc) { logger.warning(getStackTraceString(exc)); } } public void configure(Map props) throws HibernateException { if(pds == null) throw new HibernateException("PoolDataSource was not initialized."); if (props == null) throw new HibernateException("Null configuration properties passed in."); try { logger.finest("Passed in properties: " + props); String tempval = (String) props.get(CONN_FACTORY); if (tempval != null) pds.setConnectionFactoryClassName(tempval); tempval = (String) props.get(URL); if (tempval != null) pds.setURL(tempval); tempval = (String) props.get(USER); if (tempval != null) pds.setUser(tempval); tempval = (String) props.get(PASSWORD); if (tempval != null) pds.setPassword(tempval); tempval = (String) props.get(POOL_NAME); if (tempval != null) pds.setConnectionPoolName(tempval); tempval = (String) props.get(MAX_POOL_SIZE); if (tempval != null) pds.setMaxPoolSize(Integer.parseInt(tempval)); tempval = (String) props.get(MIN_POOL_SIZE); if (tempval != null) pds.setMinPoolSize(Integer.parseInt(tempval)); tempval = (String) props.get(INITIAL_POOL_SIZE); if (tempval != null) pds.setInitialPoolSize(Integer.parseInt(tempval)); tempval = (String) props.get(FAN_ENABLED); if (tempval != null) pds.setFastConnectionFailoverEnabled(Boolean.parseBoolean(tempval)); tempval = (String) props.get(ONS_CONFIG); if (tempval != null) pds.setONSConfiguration(tempval); tempval = (String) props.get(CONN_VALIDATE); if (tempval != null) pds.setValidateConnectionOnBorrow(Boolean.parseBoolean(tempval)); } catch (SQLException sqlexc) { logger.warning(getStackTraceString(sqlexc)); } } public Connection getConnection() throws SQLException { final Connection conn = pds.getConnection(); logger.finest("Got connection " + conn + " from " + pds + ", number of available connections = " + pds.getAvailableConnectionsCount() + ", borrowed connections = " + pds.getBorrowedConnectionsCount()); return conn; } public void closeConnection(Connection conn) throws SQLException { conn.close(); logger.finest("Closed connection " + conn + " from " + pds + ", number of available connections = " + pds.getAvailableConnectionsCount() + ", borrowed connections = " + pds.getBorrowedConnectionsCount()); } public void close() { try { final UniversalConnectionPoolManager mgr = UniversalConnectionPoolManagerImpl.getUniversalConnectionPoolManager(); mgr.destroyConnectionPool(pds.getConnectionPoolName()); logger.finest("Closed PoolDataSource " + pds); } catch (UniversalConnectionPoolException exc) { logger.warning(getStackTraceString(exc)); } } public boolean supportsAggressiveRelease() { return true; } public boolean isUnwrappableAs(Class cls) { return false; } public <T> T unwrap(Class<T> cls) { return null; } private String getStackTraceString(Throwable exc) { final Writer stackTraceWriter = new StringWriter(1024); final PrintWriter pw = new PrintWriter(stackTraceWriter); exc.printStackTrace(pw); return stackTraceWriter.toString(); } }

    With UCP ConnectionProvider implementation ready, application can declaratively specify the implementation class name using the Hibernate property "hibernate.connection.provider_class".

    Below is an example hibernate.cfg.xml file including the UCP-specific configuration properties:

    <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <!-- Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. --> <hibernate-configuration> <session-factory> <property name="hibernate.connection.provider_class"> oracle.ucp.hibernate.sample.UCPConnectionProvider </property> <property name="hibernate.ucp.url"> jdbc:oracle:thin:@//host:1521/service_name </property> <property name="hibernate.ucp.connectionFactoryClassName"> oracle.jdbc.pool.OracleDataSource </property> <property name="hibernate.ucp.user">scott</property> <property name="hibernate.ucp.password">tiger</property> <property name="hibernate.ucp.maxPoolSize">2</property> </session-factory> </hibernate-configuration>

    Conclusion

    In this article, we illustrated three options for using UCP with Hibernate. In all three cases, UCP will function as the connection pool for Hibernate’s JDBC connections and intercept JDBC connection checkouts and checkins without additional application code changes. This allows applications to utilize UCP’s full pooling capabilities including all the scalability and high-availability features for Oracle RAC, ADG, and GDS.

    Wednesday Oct 09, 2013

    Write recovery code with Transaction Guard

    This article demonstrates how to use in Java a new 12C database feature called Transaction Guard.[Read More]
    About

    This blog is owned by the JDBC, UCP and OTA4H development team.

    Search

    Categories
    Archives
    « July 2016
    SunMonTueWedThuFriSat
         
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
          
    Today