Oracle Database developers talking to the developers

Dev2Dev
Oracle Database developers talking to the developers
https://blogs.oracle.com/dev2dev/

Friday Apr 15, 2016

Using Coherence with Universal Connection Pool (UCP)

Coherenceis an in-memory data gridsolution that addresses the issues of working with distributed objectsinmemory (cache). Amongst its many features, Pluggable Cache Storesallows caching (i.e., load/store) contents from any persistence layer.

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

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

Relational databases is the most common option for persistence, but itsselectionforces you to define an object-relational mapping from Java classes tothe underlying relational model(using for example: hibernate, TopLink or any ad-hoc JPAimplementation). But thatis onlyhalf of the job to be done. It is also paramount to define how you willmanagethe connections to execute this persistence.

Thefollowing diagram depicts how Coherence persists in an RDBMS throughthe CacheStore interface:

TheCacheStore is responsible forhandling the connection to the database. Not only in terms ofconnectioncreation/pooling but also in terms of how to detect changes in theinstances ofthe database it is connected to.
Connectionmanagement is critical whenyou are looking for extreme performance and high availability; henceit’scritical for the CacheStore to handle connection acquirement properly.

OracleUniversal Connection Pool (UCP)provides you notonly all the intrinsic advantages of connection pooling (connectionre-use,management, availability, purge, etc.) but it also leverages thepossibility touse all the features you have when connected to a RAC environment:

  • RuntimeConnection Load Balancing (RCLB)
  • FastConnection Failover (FCF)
  • TransactionAffinity
  • Built-insupport for Database Resident Connection Pooling (DRCP) and ApplicationContinuity (AC)

Bytaking this approach, you are not onlysetting the relationship between your cache and your persistence layer.You are also optimizing the configuration and management with yourunderlying RAC, by exploiting all its features in terms of connectionhandling.

Formore information about UCP, please refer to: Introductionto UCP.
Ina previous article we already discussed these features and how toexploit them from a JBoss Web application:
UsingUniversal Connection Pooling (UCP) with JBoss AS
Inthis article we are going to show you how to use UCP from Coherenceusing Pluggable Cache Stores, hence also making it available for anytype ofCoherence client.

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

Youcan skip this step if you alreadyhave coherence.jar, ucp.jar and ojdbc7.jar.
Download“Coherence Stand-Alone Install” from  this location.
Unzipthe downloaded file.
Runthe universal installation jar:

java -jarfmw_12.2.1.0.0_coherence.jar

Duringinstall, select an Oracle Home location. In this location youwill find the coherence jar that we will be using during thisdemo: 
ORACLE_HOME/coherence/lib/coherence.jar.

DownloadUCP and Oracle JDBC Driver (ucp.jar and ojdbc.jar) UCPJDBC

Forthis sample, I copied these jars are in the home directory (~) andcoherence.jar to ~/ucpcoherence dir:

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

2.Configure Cache and CacheStore.

Youneed to indicate coherence the schemefor your cache. The scheme will define its behavior (such as if it’slocal,replicated or distributed, etc.). For our configuration, these are themostimportant things to understand:

  • cache-mapping:this will indicate coherence what cache-names (ids) will match to thisspecific type (scheme). In our sample we’ll create cache “test1” tomatch it with “test*”, which in turns will associate with scheme-name“example-distributed” and under this scheme-name we’ll define ourcache-scheme.
  • class-name(in cachestore-scheme): here we will inject into our distributed cachethe name of the class that will handle the persistence (load / loadAll/ store / storeAll / erase / eraseAll) operations in our cache. In ourcase it will be ucp_samples.EmployeeCacheStore, which we will definelater in this article.
  • init-params(in class-scheme): here you can specify values that will be used in theconstructor 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.

Asconfigured in previous file, you needto provide an implementation for CacheStore that will execute itsmethods whenobjects in the cache are added or requested (it will store or load iftheobject is not on the cache). We provide an implementation for the loadmethodand the constructor of the class (which shows how to use UCP). You candefinethe behavior for the rest of the methods as part of your test.
Noticethat the values for UCP can be changed/monitored through JMX asit was explained in thisarticle.

Tocheck more in how to use UCP with Hibernate you can check in thisarticle.

publicclassEmployeeCacheStore implementsCacheStore {

privatePoolDataSource pds= null;
private int INITIAL_POOL_SIZE= 5;

privateConnection getConnection() throwsSQLException {

return pds .getConnection();
}

/**
* Constructor fortheCacheStore, parsesinitial values and sets the
* connection pool.
*
*
@paramurl
*
@paramuser
*
@parampassword
*/

publicEmployeeCacheStore(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 isnot inthe cache, it willgo through cache store to
* retrieve it,using theconnection pool. Inthis sample we execute a
* manual objectrelationalmapping, in a real
-lifescenario hibernate, or
* any other ad
-hocJPA implementation should be used.
*/

@Override
publicEmployee 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.

Thisis the class that will live in ourcache. It’s a simple Java Bean which needs to implement Serializable inorderto be able to be shared across the nodes of the cache. In a real-lifescenarioyou will want to implement coherence’s PortableObject instead of onlySerializable, so you will be using coherence ultra-optimized mechanismstoshare/store objects: Portable Object Format Serialization (POF).
Note:getters/setters/constructors areremoved to be easier to read this example. Also note that yourimplementationof toString() is what you are going to see in coherence’s console.

publicclassEmployee implementsSerializable {

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

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

5.Configure Operational File.

Inorder to provide some specificoperational values for your cache, you will need to provide thefollowingoperational configuration file.
Takeparticular attention for the name ofthe cluser “cluster_ucp”, the address/port you will be synchronizingwith othernodes of the cluster “localhost:6699” and the name of the configurationfileyou will use (you set this through the system property parameter“tangosol.coherence.cacheconfig=example-ucp.xml”, defined in 2ndstep.
Note: sinceversion 12.2.1 you no longer needto use prefix “tangosol”.

~/ucpcoherence/tangosol-coherence-override.xml

<?xmlversion='1.0'?>
<!DOCTYPEcoherence 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.

Fromcommand line you can start the nodesof your cache through DefaultCacheServer class and the followingparameters:
(from~/ucpcocherence, being./ucp_samples/bin the output folder for your eclipse project or theplace whereyou 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/bincom.tangosol.net.DefaultCacheServer

Note:asstated before, since 12.2.1 you nolonger need to use tangosol prefix, it will also work withcoherence.cluster.

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

Ifyou issue the same command on aseparate process to start 2nd node:

Youcan check member id = 2 joining thecluster (it shows in both processes). This way now you have 2 nodesworking forthis cluster.

Lastly,you start the client for thecluster (which indeed is a new member itself) using CacheFactory classandrunning this command:

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

Notethat if you wouldn’t want yourclient to be a storage member you can provide the option-Dtangosol.coherence.distributed.localstorage=false to achieve thisbehavior.This can also be done via configuration.

Yousee member id = 3 with command lineoption to interact with the cache.

Thefirst thing you need to do is tostart a cache with the same scheme as the one we defined. In order todo thatyou use the same name pattern we defined in cache-mapping using a namematching“test*”. So you issue:

cachetest1

Andyou will notice now that the promptis with this cache

Map(test1):

Nowyou try to load the first object byissuing:

get100

You’llnotice for each new object loadedin the cache the additional time it takes to read its value from thedatabaseand you’ll see the output of the object retrieved in the console(executingEmployee.toString() method).

Runagain get 100 and you’ll notice thedifference in the response time of using an object that’s already inthe cache.

7.Interact with the cache from Java code

Tointeract with the cache from a javaclass it’s even easier. The only thing you should do is add the VMparameter-Dtangosol.coherence.override=tangosol-coherence-override.xml (pointingto thesame one that started the nodes) to the following code:

publicclassEmployeeQueryCache {

public static voidmain(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);

}

}

Sincecoherence 12.2.1 the interfaceNamedCache supports generics, so you might be able to update previouscodewith:

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 classUcpDemoSingletonWrapper {

@Resource(name= "connectionFactoryClassName")
StringconnectionFactoryClassName;

@Resource(name= "url")
Stringurl;

@Resource(name= "user")
Stringuser;

@Resource(name= "password")
Stringpassword;

@Resource(name= "initialPoolSize")
IntegerinitialPoolSize;

/**
* Initialize method for the Singleton. This wrapper
* could alsoimplement JMX APIs to be able to be
* managed through the JMX Console (or anyother 
* JMX-compliantTool)
*/
@PostConstruct
voidinit() {

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
privatePoolDataSource pds= PoolDataSourceFactory.getPoolDataSource();

/**
* Retrieves connections using wrapped pool
*
* @returna pooled connection
* @throwsSQLException
*/
publicConnection getConnection() throwsSQLException {

/**
* 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 classUcpDemoServletClient extendsHttpServlet {

@EJB
UcpDemoSingletonWrapperucpWrapper;

protected voiddoGet(HttpServletRequest request, HttpServletResponseresponse)throwsServletException, IOException {

doPost(request,response);

}

protected voiddoPost(HttpServletRequest request, HttpServletResponseresponse)throwsServletException, IOException {

try(

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

//Send output to response
PrintWriterprintWriter= response.getWriter();

while(resultSet.next()){

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

}

}catch(SQLException sqlException){

throw newServletException(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]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值