blob: f9cf1a6dbd268e48b1b9d200af9acd485671bae3 [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* one or more patents listed at http://www.pivotal.io/patents.
*=========================================================================
*/
/*
* CacheJUnitTest.java
* JUnit based test
*
* Created on March 28, 2005, 10:59 AM
*/
package com.gemstone.gemfire.internal.jta.functional;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.sql.DataSource;
import javax.transaction.UserTransaction;
import org.apache.logging.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import com.gemstone.gemfire.cache.AttributesFactory;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheException;
import com.gemstone.gemfire.cache.CacheExistsException;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.CacheLoader;
import com.gemstone.gemfire.cache.CacheLoaderException;
import com.gemstone.gemfire.cache.LoaderHelper;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.internal.jta.CacheUtils;
import com.gemstone.gemfire.internal.jta.JTAUtils;
import com.gemstone.gemfire.internal.logging.LogService;
import com.gemstone.gemfire.test.junit.categories.IntegrationTest;
/**
* This JUnit version is created from class
* com.gemstone.gemfire.internal.jta.functional.CacheTest1. Tests functional
* behavior. Assumes that CacheUtils.java always creates table(s) and inserts
* data in the form: 1 => name1, 2 => name2, 3 => name3...as the values of ID
* and name fields respectively. Test # 15 & 16 has the dependency to run on
* CloudScape database only due to variations in DDL.
*
* @author prabir
*/
@Category(IntegrationTest.class)
public class CacheJUnitTest {
private static final Logger logger = LogService.getLogger();
private Region currRegion;
private Cache cache;
private int tblIDFld;
private String tblNameFld;
private String tblName;
@Before
public void setUp() throws Exception {
this.tblName = CacheUtils.init("CacheJUnitTest");
assertFalse(this.tblName == null || this.tblName.equals(""));
this.cache = CacheUtils.getCache();
assertNotNull(this.cache);
this.currRegion = this.cache.getRegion("root");
assertTrue(this.currRegion.getFullPath().equals("/root"));
}
@After
public void tearDown() throws java.lang.Exception {
try {
CacheUtils.closeCache();
CacheUtils.destroyTable(this.tblName);
} finally {
InternalDistributedSystem ids = InternalDistributedSystem.getAnyInstance();
if (ids != null) {
ids.disconnect();
}
}
}
/**
* Test of testScenario1 method, of class
* com.gemstone.gemfire.internal.jta.functional.CacheTest1. Tests a simple
* User Transaction with Cache lookup.
*/
@Test
public void testScenario1() throws Exception {
this.tblIDFld = 1;
this.tblNameFld = "test1";
JTAUtils jtaObj = new JTAUtils(cache, currRegion);
jtaObj.deleteRows(this.tblName);
Context ctx = cache.getJNDIContext();
UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
Connection conn = null;
try {
ta.begin();
DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
conn = da.getConnection();
Statement stmt = conn.createStatement();
String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'" + this.tblNameFld + "'" + ")";
stmt.executeUpdate(sqlSTR);
stmt.close();
ta.commit();
conn.close();
} catch (NamingException e) {
ta.rollback();
fail(" failed " + e.getMessage());
} catch (SQLException e) {
ta.rollback();
fail(" failed " + e.getMessage());
} catch (Exception e) {
ta.rollback();
fail(" failed " + e.getMessage());
} finally {
if (conn != null)
try {
conn.close();
} catch (SQLException ex) {
fail("SQL exception: " + ex.getMessage());
}
}
}
/**
* Test of testScenario2 method, of class
* com.gemstone.gemfire.internal.jta.functional.CacheTest1. Tests a simple
* User Transaction with Cache lookup but closing the Connection object before
* committing the Transaction.
*/
@Test
public void testScenario2() throws Exception {
this.tblIDFld = 2;
this.tblNameFld = "test2";
boolean rollback_chances = true;
JTAUtils jtaObj = new JTAUtils(cache, currRegion);
jtaObj.deleteRows(this.tblName);
Context ctx = cache.getJNDIContext();
System.out.print(" looking up UserTransaction... ");
UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
Connection conn = null;
try {
ta.begin();
DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
conn = da.getConnection();
Statement stmt = conn.createStatement();
String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'" + this.tblNameFld + "'" + ")";
stmt.executeUpdate(sqlSTR);
stmt.close();
conn.close();
ta.commit();
rollback_chances = false;
int ifAnyRows = jtaObj.getRows(this.tblName);
if (ifAnyRows == 0) {
// no rows are there !!! failure :)
fail(" no rows retrieved even after txn commit after conn close.");
}
} catch (NamingException e) {
if (rollback_chances)
ta.rollback();
fail(" failed " + e.getMessage());
} catch (SQLException e) {
if (rollback_chances)
ta.rollback();
fail(" failed " + e.getMessage());
} catch (Exception e) {
ta.rollback();
fail(" failed " + e.getMessage());
} finally {
if (conn != null)
try {
conn.close();
} catch (SQLException e) {
}
}
}
/**
* Test of testScenario3 method, of class
* com.gemstone.gemfire.internal.jta.functional.CacheTest1. Tests whether a
* user transaction with cache lookup and with XAPooledDataSOurce supports
* Cache put and get operations accordingly. Put and get are done within the
* transaction block and also db updates are done. After committing we check
* whether commit is proper in db and also in Cache.
*/
@Test
public void testScenario3() throws Exception {
this.tblIDFld = 3;
this.tblNameFld = "test3";
boolean rollback_chances = true;
final String DEFAULT_RGN = "root";
JTAUtils jtaObj = new JTAUtils(cache, currRegion);
jtaObj.deleteRows(this.tblName);
Context ctx = cache.getJNDIContext();
UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
Connection conn = null;
try {
/** begin the transaction **/
ta.begin();
String current_region = jtaObj.currRegion.getName();
assertEquals("the default region is not root", DEFAULT_RGN, current_region);
jtaObj.getRegionFromCache("region1");
String current_fullpath = jtaObj.currRegion.getFullPath();
assertEquals("failed retrieving current region fullpath", "/" + DEFAULT_RGN + "/region1", current_fullpath);
jtaObj.put("key1", "value1");
String str = jtaObj.get("key1");
String tok = jtaObj.parseGetValue(str);
assertEquals("get failed for corresponding put", "\"value1\"", tok);
current_fullpath = jtaObj.currRegion.getFullPath();
assertEquals("failed retrieving current region fullpath", "/" + DEFAULT_RGN + "/region1", current_fullpath);
DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
conn = da.getConnection();
Statement stmt = conn.createStatement();
String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'" + this.tblNameFld + "'" + ")";
stmt.executeUpdate(sqlSTR);
stmt.close();
ta.commit();
conn.close();
rollback_chances = false;
current_fullpath = jtaObj.currRegion.getFullPath();
assertEquals("failed retrieving current region fullpath after txn commit", "/" + DEFAULT_RGN + "/region1", current_fullpath);
int ifAnyRows = jtaObj.getRows(this.tblName);
assertEquals("rows retrieved is:" + ifAnyRows, 1, ifAnyRows);
/*
* if (ifAnyRows == 0) { fail
* (" DB FAILURE: no rows retrieved even after txn commit."); }
*/
// after jdbc commit cache value in region1 for key1 must retain...
str = jtaObj.get("key1");
tok = jtaObj.parseGetValue(str);
assertEquals("cache put didn't commit, value retrieved is: " + tok, "\"value1\"", tok);
} catch (CacheExistsException e) {
ta.rollback();
fail(" test 3 failed ");
} catch (NamingException e) {
if (rollback_chances)
ta.rollback();
fail(" test 3 failed " + e.getMessage());
} catch (SQLException e) {
if (rollback_chances)
ta.rollback();
fail(" test 3 failed " + e.getMessage());
} catch (Exception e) {
if (rollback_chances)
ta.rollback();
fail(" test 3 failed " + e.getMessage());
} finally {
if (conn != null)
try {
conn.close();
} catch (SQLException e) {
}
}
}
/**
* Test of testScenario4 method, of class
* com.gemstone.gemfire.internal.jta.functional.CacheTest1. Tests whether a
* user transaction with cache lookup and with XAPooledDataSOurce supports
* Cache put and get operations accordingly along with JTA behavior. Put and
* get are done within the transaction block and also db updates are done.
* After rollback the transaction explicitly we check whether it was proper in
* db and also in Cache, which should also rollback.
*/
@Test
public void testScenario4() throws Exception {
this.tblIDFld = 4;
this.tblNameFld = "test4";
boolean rollback_chances = true;
final String DEFAULT_RGN = "root";
JTAUtils jtaObj = new JTAUtils(cache, currRegion);
jtaObj.deleteRows(this.tblName);
Context ctx = cache.getJNDIContext();
UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
Connection conn = null;
try {
String current_region = jtaObj.currRegion.getName();
assertEquals("default region is not root", DEFAULT_RGN, current_region);
jtaObj.getRegionFromCache("region1");
String current_fullpath = jtaObj.currRegion.getFullPath();
assertEquals("failed retrieving current region fullpath after doing getRegionFromCache(region1)", "/" + DEFAULT_RGN + "/region1", current_fullpath);
jtaObj.put("key1", "test");
ta.begin();
jtaObj.put("key1", "value1");
String str = jtaObj.get("key1");
String tok = jtaObj.parseGetValue(str);
assertEquals("get value do not match with the put", "\"value1\"", tok);
current_fullpath = jtaObj.currRegion.getFullPath();
assertEquals("failed retrieving current region fullpath", "/" + DEFAULT_RGN + "/region1", current_fullpath);
DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
conn = da.getConnection();
Statement stmt = conn.createStatement();
String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'" + this.tblNameFld + "'" + ")";
stmt.executeUpdate(sqlSTR);
stmt.close();
ta.rollback();
conn.close();
rollback_chances = false;
current_fullpath = jtaObj.currRegion.getFullPath();
assertEquals("failed retirieving current region fullpath after txn rollback", "/" + DEFAULT_RGN + "/region1", current_fullpath);
int ifAnyRows = jtaObj.getRows(this.tblName);
assertEquals("rows retrieved is: " + ifAnyRows, 0, ifAnyRows);
/*
* if (ifAnyRows != 0) { fail (" DB FAILURE"); }
*/
str = jtaObj.get("key1");
tok = jtaObj.parseGetValue(str);
assertEquals("value existing in cache is: " + tok, "\"test\"", tok);
} catch (CacheExistsException e) {
ta.rollback();
fail(" failed " + e.getMessage());
} catch (NamingException e) {
if (rollback_chances)
ta.rollback();
fail(" failed " + e.getMessage());
} catch (SQLException e) {
if (rollback_chances)
ta.rollback();
fail(" failed " + e.getMessage());
} catch (Exception e) {
if (rollback_chances)
ta.rollback();
fail(" failed " + e.getMessage());
} finally {
if (conn != null)
try {
conn.close();
} catch (SQLException e) {
}
}
}
/**
* Test of testScenario5 method, of class
* com.gemstone.gemfire.internal.jta.functional.CacheTest1. Tests whether a
* user transaction with cache lookup and with XAPooledDataSOurce supports
* Cache put and get operations accordingly along with JTA behavior. Put and
* get are done within the transaction block and also db updates are done. We
* try to rollback the transaction by violating primary key constraint in db
* table, nad then we check whether rollback was proper in db and also in
* Cache, which should also rollback.
*/
@Test
public void testScenario5() throws Exception {
this.tblIDFld = 5;
this.tblNameFld = "test5";
boolean rollback_chances = false;
final String DEFAULT_RGN = "root";
JTAUtils jtaObj = new JTAUtils(cache, currRegion);
jtaObj.deleteRows(this.tblName);
Context ctx = cache.getJNDIContext();
UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
Connection conn = null;
try {
String current_region = jtaObj.currRegion.getName();
assertEquals("default region is not root", DEFAULT_RGN, current_region);
// trying to create a region 'region1' under /root, if it doesn't exist.
// And point to the new region...
jtaObj.getRegionFromCache("region1");
// now current region should point to region1, as done from within
// getRegionFromCache method...
String current_fullpath = jtaObj.currRegion.getFullPath();
assertEquals("failed retirieving current fullpath", "/" + DEFAULT_RGN + "/region1", current_fullpath);
jtaObj.put("key1", "test");
ta.begin();
jtaObj.put("key1", "value1");
String str = jtaObj.get("key1");
String tok = jtaObj.parseGetValue(str);
assertEquals("get value mismatch with put", "\"value1\"", tok);
current_fullpath = jtaObj.currRegion.getFullPath();
assertEquals("failed retrieving current fullpath, current fullpath: " + current_fullpath, "/" + DEFAULT_RGN + "/region1", current_fullpath);
DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
conn = da.getConnection();
Statement stmt = conn.createStatement();
String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'" + this.tblNameFld + "'" + ")";
stmt.executeUpdate(sqlSTR);
rollback_chances = true;
// capable of throwing SQLException during insert operation
sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'" + this.tblNameFld + "'" + ")";
stmt.executeUpdate(sqlSTR);
stmt.close();
ta.commit();
conn.close();
} catch (CacheExistsException e) {
ta.rollback();
fail("test failed " + e.getMessage());
} catch (NamingException e) {
ta.rollback();
fail("test failed " + e.getMessage());
} catch (SQLException e) {
// exception thrown during inserts are handeled as below by rollback
if (rollback_chances) {
try {
ta.rollback();
} catch (Exception ex) {
fail("failed: " + ex.getMessage());
}
// intended error is checked w.r.t database first
int ifAnyRows = 0;
try {
ifAnyRows = jtaObj.getRows(this.tblName);
} catch (Exception ex) {
fail(" failed: " + ex.getMessage());
}
assertEquals("rows found after rollback is: " + ifAnyRows, 0, ifAnyRows);
/*
* if (ifAnyRows != 0) { fail (" DB FAILURE"); }
*/
// intended error is checked w.r.t. cache second
String current_fullpath = jtaObj.currRegion.getFullPath();
assertEquals("failed retrieving current fullpath after rollback, fullpath is: " + current_fullpath, "/" + DEFAULT_RGN + "/region1", current_fullpath);
// after jdbc rollback, cache value in region1 for key1 must vanish...
String str1 = null;
try {
str1 = jtaObj.get("key1");
} catch (CacheException ex) {
fail("failed getting value for 'key1': " + ex.getMessage());
}
String tok1 = jtaObj.parseGetValue(str1);
assertEquals("value found in cache: " + tok1 + ", after rollback", "\"test\"", tok1);
} else {
fail(" failed: " + e.getMessage());
ta.rollback();
}
} catch (Exception e) {
ta.rollback();
fail(" failed: " + e.getMessage());
} finally {
if (conn != null)
try {
conn.close();
} catch (SQLException ex) {
fail("Exception: " + ex.getMessage());
}
}
}
/**
* Test of testScenario7 method, of class
* com.gemstone.gemfire.internal.jta.functional.CacheTest1. Tests a user
* transaction with cache lookup and with XAPooledDataSource lookup. It does
* get and put operations on the cache within the transaction block and checks
* whether these operations are committed once the transaction is committed.
*/
@Test
public void testScenario7() throws Exception {
this.tblIDFld = 7;
this.tblNameFld = "test7";
boolean rollback_chances = true;
final String DEFAULT_RGN = "root";
JTAUtils jtaObj = new JTAUtils(cache, currRegion);
jtaObj.deleteRows(this.tblName);
Context ctx = cache.getJNDIContext();
UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
Connection conn = null;
try {
ta.begin();
String current_region = jtaObj.currRegion.getName();
assertEquals("default region is not root", DEFAULT_RGN, current_region);
jtaObj.getRegionFromCache("region1");
// now current region should point to region1, as done from within
// getRegionFromCache method...
String current_fullpath = jtaObj.currRegion.getFullPath();
assertEquals("failed retrieving the current region fullpath", "/" + DEFAULT_RGN + "/region1", current_fullpath);
jtaObj.put("key1", "value1");
// try to get value1 from key1 in the same region
String str = jtaObj.get("key1");
String tok = jtaObj.parseGetValue(str);
assertEquals("get value mismatch with put", "\"value1\"", tok);
current_fullpath = jtaObj.currRegion.getFullPath();
assertEquals("failed retrieving current region fullpath", "/" + DEFAULT_RGN + "/region1", current_fullpath);
DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
conn = da.getConnection();
ta.commit();
conn.close();
rollback_chances = false;
current_fullpath = jtaObj.currRegion.getFullPath();
assertEquals("failed retrieving current region fullpath after txn commit, fullpath is: " + current_region, "/" + DEFAULT_RGN + "/region1", current_fullpath);
str = jtaObj.get("key1");
tok = jtaObj.parseGetValue(str);
assertEquals("cache value found is: " + tok, "\"value1\"", tok);
} catch (CacheExistsException e) {
if (rollback_chances)
ta.rollback();
fail(" failed due to: " + e.getMessage());
} catch (NamingException e) {
ta.rollback();
fail(" failed due to: " + e.getMessage());
} catch (SQLException e) {
ta.rollback();
fail(" failed due to: " + e.getMessage());
} catch (Exception e) {
if (rollback_chances)
ta.rollback();
fail(" failed due to: " + e.getMessage());
} finally {
if (conn != null)
try {
conn.close();
} catch (Exception e) {
}
}
}
/**
* Test of testScenario9 method, of class
* com.gemstone.gemfire.internal.jta.functional.CacheTest1. Tests a user
* transaction with cache lookup and with XAPooledDataSource lookup performing
* a db update within the transaction block and committing the transaction.
* Then agin we perform another db update with the same DataSource and finally
* close the Connection. The first update only should be committed in db and
* the second will not participate in transaction throwing an SQLException.
*/
@Test
public void testScenario9() throws Exception {
this.tblIDFld = 9;
this.tblNameFld = "test9";
boolean rollback_chances = true;
int first_field = this.tblIDFld;
JTAUtils jtaObj = new JTAUtils(cache, currRegion);
// delete the rows inserted from CacheUtils createTable, otherwise conflict
// in PK's
jtaObj.deleteRows(this.tblName);
Context ctx = cache.getJNDIContext();
UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
Connection conn = null;
try {
ta.begin();
DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
conn = da.getConnection();
Statement stmt = conn.createStatement();
String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'" + this.tblNameFld + "'" + ")";
stmt.executeUpdate(sqlSTR);
ta.commit();
rollback_chances = false;
// intended test for failure-- capable of throwing SQLException
this.tblIDFld += 1;
sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'" + this.tblNameFld + "'" + ")";
stmt.executeUpdate(sqlSTR);
stmt.close();
conn.close();
rollback_chances = true;
} catch (NamingException e) {
fail(" failed due to: " + e.getMessage());
ta.rollback();
} catch (SQLException e) {
if (!rollback_chances) {
int ifAnyRows = jtaObj.getRows(this.tblName);
assertEquals("rows found is: " + ifAnyRows, 1, ifAnyRows);
boolean matched = jtaObj.checkTableAgainstData(this.tblName, first_field + ""); // first
// field
// must
// be
// there.
assertEquals("first entry to db is not found", true, matched);
} else {
ta.rollback();
fail(" failed due to: " + e.getMessage());
}
} catch (Exception e) {
fail(" failed due to: " + e.getMessage());
if (rollback_chances) {
ta.rollback();
}
} finally {
if (conn != null)
try {
conn.close();
} catch (SQLException e) {
}
}
}
/**
* Test of testScenario10 method, of class
* com.gemstone.gemfire.internal.jta.functional.CacheTest1. Test a user
* transaction with cache lookup and with XAPooledDataSource for multiple JDBC
* Connections. This should not be allowed for Facets datasource. For other
* relational DB the behaviour will be DB specific. For Oracle DB, n
* connections in a tranxn can be used provided , n-1 connections are closed
* before opening nth connection.
*/
@Test
public void testScenario10() throws Exception {
this.tblIDFld = 10;
this.tblNameFld = "test10";
int rows_inserted = 0;
int ifAnyRows = 0;
int field1 = this.tblIDFld, field2 = 0;
JTAUtils jtaObj = new JTAUtils(cache, currRegion);
jtaObj.deleteRows(this.tblName);
Context ctx = cache.getJNDIContext();
UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
Connection conn1 = null;
Connection conn2 = null;
try {
ta.begin();
DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
conn1 = da.getConnection(); // the first Connection
Statement stmt = conn1.createStatement();
String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'" + this.tblNameFld + "'" + ")";
stmt.executeUpdate(sqlSTR);
rows_inserted += 1;
conn1.close();
conn2 = da.getConnection(); // the second Connection
stmt = conn2.createStatement();
this.tblIDFld += 1;
field2 = this.tblIDFld;
sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'" + this.tblNameFld + "'" + ")";
stmt.executeUpdate(sqlSTR);
rows_inserted += 1;
stmt.close();
conn2.close();
ta.commit();
// if we reach here check for proper entries in db
ifAnyRows = jtaObj.getRows(this.tblName);
if (ifAnyRows == rows_inserted) {
boolean matched1 = jtaObj.checkTableAgainstData(this.tblName, (field1 + ""));
boolean matched2 = jtaObj.checkTableAgainstData(this.tblName, (field2 + ""));
if (matched1)
System.out.print("(PK " + field1 + "found ");
else
System.out.print("(PK " + field1 + "not found ");
if (matched2)
System.out.print("PK " + field2 + "found)");
else
System.out.print("PK " + field2 + "not found)");
if (matched1 & matched2) {
System.out.println("ok");
} else {
fail(" inserted data not found in DB !... failed");
}
} else {
fail(" test interrupted, rows found=" + ifAnyRows + ", rows inserted=" + rows_inserted);
}
} catch (NamingException e) {
ta.rollback();
} catch (SQLException e) {
ta.rollback();
} catch (Exception e) {
ta.rollback();
} finally {
if (conn1 != null)
try {
conn1.close();
} catch (SQLException e) {
}
if (conn2 != null)
try {
conn2.close();
} catch (SQLException e) {
}
}
}
/**
* Test of testScenario11 method, of class
* com.gemstone.gemfire.internal.jta.functional.CacheTest1. Tests Simple
* DataSource lookup within a transaction. Things should not participate in
* the transaction.
*/
@Test
public void testScenario11() throws Exception {
this.tblIDFld = 11;
this.tblNameFld = "test11";
boolean rollback_chances = false;
JTAUtils jtaObj = new JTAUtils(cache, currRegion);
jtaObj.deleteRows(this.tblName);
Context ctx = cache.getJNDIContext();
UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
Connection conn = null;
try {
ta.begin();
DataSource da = (DataSource) ctx.lookup("java:/SimpleDataSource");
conn = da.getConnection();
Statement stmt = conn.createStatement();
String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'" + this.tblNameFld + "'" + ")";
stmt.executeUpdate(sqlSTR);
rollback_chances = true;
// try insert the same data once more and see if all info gets rolled
// back...
// capable of throwing SQLException
sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'" + this.tblNameFld + "'" + ")";
stmt.executeUpdate(sqlSTR);
stmt.close();
ta.commit();
conn.close();
} catch (NamingException e) {
ta.rollback();
} catch (SQLException e) {
if (rollback_chances) {
try {
ta.rollback();
} catch (Exception ex) {
fail("failed due to : " + ex.getMessage());
}
// try to check in the db whether any rows (the first one) are there
// now...
int ifAnyRows = jtaObj.getRows(this.tblName);
assertEquals("first row not found in case of Simple Datasource", 1, ifAnyRows); // one
// row--
// the
// first
// one
// shud
// be
// there.
boolean matched = jtaObj.checkTableAgainstData(this.tblName, this.tblIDFld + ""); // checking
// the
// existence
// of
// first
// row
assertEquals("first row PK didn't matched", true, matched);
} else {
ta.rollback();
}
} catch (Exception e) {
fail(" failed due to: " + e.getMessage());
ta.rollback();
} finally {
if (conn != null)
try {
conn.close();
} catch (SQLException e) {
}
}
}
/**
* Test of testScenario14 method, of class
* com.gemstone.gemfire.internal.jta.functional.CacheTest1. Tests a local
* Cache Loader with XADataSource lookup to get the connection. The Connection
* should not participate in the transaction and commit/rollback should take
* affect accordingly along with cache.
*/
@Test
public void testScenario14() throws Exception {
final String TABLEID = "2";
// final String TABLEFLD = "name2";
JTAUtils jtaObj = new JTAUtils(cache, currRegion);
Context ctx = cache.getJNDIContext();
UserTransaction utx = (UserTransaction) ctx.lookup("java:/UserTransaction");
utx.begin();
AttributesFactory fac = new AttributesFactory(currRegion.getAttributes());
fac.setCacheLoader(new XACacheLoaderTxn(this.tblName));
Region re = currRegion.createSubregion("employee", fac.create());
String retVal = (String) re.get(TABLEID); // TABLEID correspondes to
// "name1".
if (!retVal.equals("newname"))
fail("Uncommitted value 'newname' not read by cacheloader name = " + retVal);
utx.rollback();
DataSource ds = (DataSource) ctx.lookup("java:/XAPooledDataSource");
Connection conn = ds.getConnection();
Statement stm = conn.createStatement();
String str = "select name from " + tblName + " where id= (2)";
ResultSet rs = stm.executeQuery(str);
rs.next();
String str1 = rs.getString(1);
if (!str1.equals("name2"))
fail("Rollback not occured on XAConnection got in a cache loader");
}
/**
* Test of testScenario15 method, of class
* com.gemstone.gemfire.internal.jta.functional.CacheTest1. Tests performing
* DDL operations by looking up a XAPooledDataSource and without transaction.
*/
@Test
public void testScenario15() throws Exception {
this.tblIDFld = 15;
this.tblNameFld = "test15";
String tbl = "";
boolean row_num = true;
int ddl_return = 1;
JTAUtils jtaObj = new JTAUtils(cache, currRegion);
// delete the rows inserted from CacheUtils createTable, otherwise conflict
// in PK's. Basically not needed for this test
jtaObj.deleteRows(this.tblName);
Context ctx = cache.getJNDIContext();
// UserTransaction ta = null;
Connection conn = null;
Statement stmt = null;
/*
* try { ta = (UserTransaction)ctx.lookup("java:/UserTransaction");
*
* } catch (NamingException e) { fail ("user txn lookup failed: " +
* e.getMessage ()); }
*/
try {
DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
conn = da.getConnection();
stmt = conn.createStatement();
// Do some DDL stuff
String time = new Long(System.currentTimeMillis()).toString();
tbl = "my_table" + time;
// String sql = "create table " + tbl +
// " (my_id number primary key, my_name varchar2(50))";
String sql = "create table " + tbl + " (my_id integer NOT NULL, my_name varchar(50), CONSTRAINT my_keyx PRIMARY KEY(my_id))";
ddl_return = stmt.executeUpdate(sql);
// check whether the table was created properly
sql = "select * from " + tbl;
ResultSet rs = null;
rs = stmt.executeQuery(sql);
row_num = rs.next();
rs.close();
if (ddl_return == 0 && !row_num) {
sql = "drop table " + tbl;
try {
stmt = conn.createStatement();
stmt.executeUpdate(sql);
} catch (SQLException e) {
fail(" failed to drop, " + e.getMessage());
}
} else
fail("unable to create table");
/** Code meant for Oracle DB **/
/*
* tbl = tbl.toUpperCase(); sql =
* "select * from tab where tname like '%tbl%'"; ResultSet rs = null; rs =
* stmt.executeQuery(sql); rs.close(); sql = "drop table "+tbl; stmt =
* conn.createStatement(); stmt.execute(sql); System.out.println
* (this.space + "ok");
*/
stmt.close();
conn.close();
} catch (NamingException e) {
fail("failed, " + e.getMessage());
} catch (SQLException e) {
fail("failed, " + e.getMessage());
} catch (Exception e) {
fail("failed, " + e.getMessage());
} finally {
if (conn != null)
conn.close();
}
}
/**
* Test of testScenario16 method, of class
* com.gemstone.gemfire.internal.jta.functional.CacheTest1. Tests DDL
* operations on XAPooledDataSOurce lookup, without transaction but making
* auto commit false just before performing DDL queries and making it true
* before closing the Connection. The operations should be committed.
*/
@Test
public void testScenario16() throws Exception {
this.tblIDFld = 16;
this.tblNameFld = "test16";
String tbl = "";
int ddl_return = 1;
boolean row_num = true;
JTAUtils jtaObj = new JTAUtils(cache, currRegion);
jtaObj.deleteRows(this.tblName);
Context ctx = cache.getJNDIContext();
Connection conn = null;
Statement stmt = null;
try {
DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
conn = da.getConnection();
conn.setAutoCommit(false);
stmt = conn.createStatement();
String time = new Long(System.currentTimeMillis()).toString();
tbl = "my_table" + time;
// String sql = "create table " + tbl +
// " (my_id number primary key, my_name varchar2(50))";
String sql = "create table " + tbl + " (my_id integer NOT NULL, my_name varchar(50), CONSTRAINT my_key PRIMARY KEY(my_id))";
ddl_return = stmt.executeUpdate(sql);
sql = "select * from " + tbl;
ResultSet rs = null;
rs = stmt.executeQuery(sql);
row_num = rs.next();
rs.close();
if (ddl_return == 0 && !row_num) {
sql = "drop table " + tbl;
try {
stmt = conn.createStatement();
stmt.executeUpdate(sql);
} catch (SQLException e) {
fail(" failed to drop, " + e.getMessage());
}
} else
fail("table do not exists");
/*** Code meant for Oracle DB ***/
/*
* tbl = tbl.toUpperCase(); sql =
* "select * from tab where tname like '%tbl%'"; ResultSet rs = null; rs =
* stmt.executeQuery(sql); rs.close(); sql = "drop table "+tbl; stmt =
* conn.createStatement(); stmt.executeUpdate(sql); System.out.println
* (this.space + "ok");
*/
conn.setAutoCommit(true);
stmt.close();
conn.close();
} catch (NamingException e) {
fail("failed, " + e.getMessage());
} catch (SQLException e) {
fail("failed, " + e.getMessage());
} catch (Exception e) {
fail("failed, " + e.getMessage());
} finally {
if (conn != null)
try {
conn.close();
} catch (SQLException e) {
}
}
}
/**
* Test of testScenario18 method, of class
* com.gemstone.gemfire.internal.jta.functional.CacheTest1. Get a connection
* (conn1) outside a transaction with pooled datasource lookup and another
* connection (conn2) within the same transaction with XAPooled datasource
* lookup. After making updates we do a rollback on the transaction and close
* both connections in the order of opening them. The connection opened within
* transaction will only participate in the transaction.
*/
@Test
public void testScenario18() throws Exception {
this.tblIDFld = 18;
this.tblNameFld = "test18";
boolean rollback_chances = true;
int ifAnyRows = 0;
JTAUtils jtaObj = new JTAUtils(cache, currRegion);
jtaObj.deleteRows(this.tblName);
Context ctx = cache.getJNDIContext();
Connection conn2 = null; // connection within txn
DataSource da = (DataSource) ctx.lookup("java:/PooledDataSource");
Connection conn1 = da.getConnection(); // connection outside txn
UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
try {
ta.begin();
Statement stmt = conn1.createStatement();
String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'" + this.tblNameFld + "'" + ")";
stmt.executeUpdate(sqlSTR);
stmt.close();
ifAnyRows = jtaObj.getRows(this.tblName);
if (ifAnyRows == 0) {
fail("failed no rows are there...");
}
// tryin a XAPooled lookup for second connection
da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
conn2 = da.getConnection();
stmt = conn2.createStatement();
this.tblIDFld += 1;
sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'" + this.tblNameFld + "'" + ")";
stmt.executeUpdate(sqlSTR);
ta.rollback(); // intensional rollback
stmt.close();
conn2.close();
conn1.close();
rollback_chances = false;
// if we reach here check whether the rollback was success for conn1 and
// conn2
ifAnyRows = jtaObj.getRows(this.tblName);
assertEquals("at least one row not retained after rollback", 1, ifAnyRows);
boolean matched = jtaObj.checkTableAgainstData(this.tblName, this.tblIDFld + ""); // checking
// conn2's
// field
if (matched) { // data is still in db
fail(", PK " + this.tblIDFld + " found in db)" + " " + "rollback for conn #2 failed");
}
} finally {
if (conn1 != null)
try {
conn1.close();
} catch (SQLException ex) {
fail(" Exception: " + ex.getMessage());
}
if (conn2 != null)
try {
conn2.close();
} catch (SQLException ex) {
fail(" Exception: " + ex.getMessage());
}
}
}
/**
* required for test # 14
*/
static class XACacheLoaderTxn implements CacheLoader {
String tableName;
/** Creates a new instance of XACacheLoaderTxn */
public XACacheLoaderTxn(String str) {
this.tableName = str;
}
public final Object load(LoaderHelper helper) throws CacheLoaderException {
System.out.println("In Loader.load for" + helper.getKey());
return loadFromDatabase(helper.getKey());
}
private Object loadFromDatabase(Object ob) {
Object obj = null;
try {
Context ctx = CacheFactory.getAnyInstance().getJNDIContext();
DataSource ds = (DataSource) ctx.lookup("java:/XAPooledDataSource");
Connection conn = ds.getConnection();
Statement stm = conn.createStatement();
String str = "update " + tableName + " set name ='newname' where id = (" + (new Integer(ob.toString())).intValue() + ")";
stm.executeUpdate(str);
ResultSet rs = stm.executeQuery("select name from " + tableName + " where id = (" + (new Integer(ob.toString())).intValue() + ")");
rs.next();
obj = rs.getString(1);
stm.close();
conn.close();
return obj;
} catch (Exception e) {
throw new Error(e);
}
}
public void close() {
}
}
}