Not able to connect to XA datasource using JNDI - java

I am trying to connect my java spring batch application to datasource using JNDI. My application requires XA datasource. I tried to configure normal datasource using below code and it seems to connect to it perfectly. But when i try to change the driver class to XA(oracle.jdbc.xa.client.OracleXADataSource) it doesn't seem to connect.i tried changing the type to javax.sql.XADataSource. Can someone tell me if i need to set additional properties for XA connectivity ?
<Resource name="jdbc/DS-ref"
auth="Container"
type="javax.sql.DataSource"
username="user"
password="password"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#xxx"
initialSize="20"
maxWaitMillis="15000"
maxTotal="75"
maxIdle="20"
testOnBorrow="true"
validationQuery="select 1 from dual" />
If i change the code in context.xml, I get error saying " Name [jdbc/DS-ref] is not bound in this Context. Unable to find [jdbc]."
Context.xml
<Resource name="jdbc/DS-ref"
auth="Container"
type="javax.sql.XADataSource"
username="user"
password="password"
driverClassName="oracle.jdbc.xa.client.OracleXADataSource"
url="jdbc:oracle:thin:#xxx"
initialSize="20"
maxWaitMillis="15000"
maxTotal="75"
maxIdle="20"
testOnBorrow="true"
validationQuery="select 1 from dual" />
web.xml
<resource-ref id="ResourceRef_CrcDataSource">
<description></description>
<res-ref-name>jdbc/DS-ref</res-ref-name>
<res-type>javax.sql.XADataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
datasource.java
// Use JNDI via Spring
Object tmpDs;
setResourceRef(true); // Make "java:comp/env/" prefix optional
try {
log.debug("pJndiName" +pJndiName);
tmpDs = lookup(pJndiName, DataSource.class);
log.debug("tmpDs"+tmpDs);
}
catch (Exception e) {
throw new RuntimeException("Error looking up DataSource via JNDI. jndiName: " + pJndiName, e);
}
if (null == tmpDs) {
throw new RuntimeException("DataSource JNDI lookup returned null. jndiName: " + pJndiName);
}
if (!DataSource.class.isInstance(tmpDs)) {
throw new RuntimeException("Illegal class returned by DataSource JNDI lookup. " + "jndiName: "
+ pJndiName + ", returned class: " + tmpDs.getClass().getName());
}
return (DataSource) tmpDs;

Related

How to resolve RecoverableDataAccessException in spring boot application

I am using JNDI configuration with JDBCtemplate as autowired in spring boot application.
Connection is creating successfully. But when we execute save or search operation it gets failed with below error:
org.springframwwork.dao.RecoverableDataAccessException: CallableStatementCallback; SQL [] Closed Connection ; nested exception is java.sql.SQLRecoverableException: Closed Connection
I have tried below stackoverflow solution as well but it doesn't worked.
What is the cause of "RecoverableDataAccessException" received when checking health of database?
Please find the below context.xml configuration used for the connection:
<Resource name="jdbc/xyz"
auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
url=""
username=""
password=""
minActive="30"
maxActive="100"
minIdle="10"
maxIdle="10"
initialSize="10"
jmxEnabled="true"
timeBetweenEvictionRunsMillis="30000"
minEvictableIdleTimeMillis="30000"
maxWait="10000"
logAbandoned="true"
testOnBorrow="true"
testOnConnect="false"
suspectTimeout="120"
validationQuery="select 1 from dual"
validationInterval="30000"
initSQL="select 1 from dual"
removeAbandoned="true"
removeAbandonedTimeout="60"
maxAge="180000"
accessToUnderlyingConnectionAllowed="true">
</Resource>
Tried changing the maxWait to -1 in context.xml as well.
JdbcTemplate is getting autowired successfully. Mostly search operations are working fine but when we do save operation its getting failed with SQLRecoverableException as mentioned above.
I am creating SimpleJdbcCall object using jdbcTemplate object and then executing it as to save the details in oracle database.
SimpleJdbcCall save = new SimpleJdbcCall(jdbcTemplate).withProcedureName("xxpqr_abc")
.withCatalogName("xxpqr__xx_abc").withoutProcedureColumnMetaDataAccess()
.declareParameters(new SqlParameter("abc", OracleTypes.ARRAY, "abc1"),
new SqlParameter("xyz", OracleTypes.ARRAY, "xyz1"),
new SqlOutParameter("error_msg", Types.VARCHAR));
Map<String, Object> saveResult = save.execute(
new MapSqlParameterSource().addValue("pqr", new SqlArrayValue(empDetailsArray))
.addValue("pqr", saveObj.getSubmitFlag()));
During execute got the java.lang.NullPointerException.
Same operation is working fine if connection created using spring #configuration annotation using separate class. But that doesn't provide connection pooling.

Data Source Injection issue in Tomcat

I have configured a datasource in tomcat 8.5.29 for oracle database in following ways:
Step 1:
edited server.xml in tomcat as follows:
<GlobalNamingResources>
<Resource name="jdbc/personapp" global="jdbc/personapp" auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.xa.client.OracleXADataSource"
url="jdbc:oracle:thin:<host_name>:1521:<db_name>"
username="my_user_name" password="my_pwd"
maxActive="100"
maxIdle="20"
minIdle="5"
maxWait="10000"/>
</GlobalNamingResources>
Step 2:
edited the context.xml as follows:
<ResourceLink name="jdbc/personappLocalDB"
global="jdbc/personapp"
auth="Container"
type="javax.sql.DataSource" />
I have DBUtility.java class as follows:
public class DBUtility {
#Resource(lookup="java:/comp/env/jdbc/personappLocalDB")
private static DataSource dataSource;
public static Connection getConnection() {
try {
connection = dataSource.getConnection();
System.out.println("connection="+connection);
} catch(Exception e){
e.printStackTrace();
}
return connection;
}
}
I am getting following exception:
java.lang.NullPointerException
at com.adv.dao.DBUtility.getConnection(DBUtility.java:27)
DataSource is not getting injected to Java class.
Can anyone figure out the problem??
Your utility class isn't #Named or an #EJB. The #Resource annotation will not be processed if it's in a regular POJO.

JNDI DataSource configuration in Tomcat 7

I am new to JNDI and I am trying to get my db connection working. So far no luck.
I either get a message stating: "Name [java:comp/env] is not bound in this Context. Unable to find [java:comp]"
or I received a time out.
Here's information about my current configuration.
Tomcat: Apache Tomcat/7.0.29
JMV: 1.7.0_06-b24
OS: Win 10 Pro
Tomcat\conf\web.xml
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/myDatabaseName</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Tomcat\conf\context.xml
<ResourceLink type="javax.sql.DataSource"
name="jdbc/localRemarket"
global="jdbc/remarket"
/>
I also tried to put the resource in context.xml to make sure it's findable:
<Resource
type="javax.sql.DataSource"
name="jdbc/myDatabaseName"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/myDatabaseName"
username="myUsername"
password="myPassword"
maxActive="1500"
maxIdle="200"
maxwait="-1"
testOnBorrow="true"
testOnReturn="true"
testWhileIdle="true"
validationQuery="SELECT 1"
timeBetweenEvictionRunsMillis="2000"
minEvictableIdleTimeMillis="15000"
removeAbandoned="true"
removeAbandonedTimeout="5"
/>
Tomcat\conf\server.xml
<Resource
type="javax.sql.DataSource"
name="jdbc/myDatabaseName"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/myDatabaseName"
username="myUsername"
password="myPassword"
maxActive="1500"
maxIdle="200"
maxwait="-1"
testOnBorrow="true"
testOnReturn="true"
testWhileIdle="true"
validationQuery="SELECT 1"
timeBetweenEvictionRunsMillis="2000"
minEvictableIdleTimeMillis="15000"
removeAbandoned="true"
removeAbandonedTimeout="5"
/>
java code:
Connection conn;
public void openMyConnection() {
try {
Properties props = new Properties();
props.put("java.naming.factory.initial", "org.apache.naming.java.javaURLContextFactory");
InitialContext ctx = new InitialContext(props);
Context envCtx = (Context) ctx.lookup("java:comp/env"); // <<<<< PRB HERE
// error message : Name [java:comp/env] is not bound in this Context. Unable to find [java:comp]
org.apache.tomcat.jdbc.pool.DataSource ds = (org.apache.tomcat.jdbc.pool.DataSource) envCtx.lookup("jdbc/localDB");
conn = ds.getConnection();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
if I change
props.put("java.naming.factory.initial", "org.apache.naming.java.javaURLContextFactory");
for
props.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
I get :
Receive timed out
I have reviewed many posts related to JNDI including the following two that were the most helpful:
http://tomcat.apache.org/tomcat-7.0-doc/jndi-datasource-examples-howto.html
and
https://examples.javacodegeeks.com/enterprise-java/tomcat/tomcat-datasource-jndi-example/
Please note that I read the How to configure jndi DataSource in Tomcat 7 but it doesn't provide a solution for my problem.
Can anyone please help resolve this issue?
It worked for me, when I configured the datasource directly in the webapp (file META-INF/context.xml):
<Context >
<Resource name="jdbc/EmployeeDB"
auth="Container"
type="javax.sql.DataSource"
username="scott"
password="tiger"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#127.0.0.1:1521:mysid"
maxActive="8"
maxIdle="4"/>
</Context>

Naming error while using multiple connection pools in a Tomcat 8 application

I have an application that uses the built-in Tomcat connection pool, and for the most part it works. A problem arises when I'm trying to use another pool to get a different set of connection from the same database, but from a different username/password (It's an oracle database that uses 2 usernames to access different namespaces of tables and function).
The first pool is accepted, but for the second one, I'm getting this error
15:09:47.157 [http-nio-8081-exec-5] ERROR com.applicationname.providers.ConnectionManager - NamingException in MyDataSource
javax.naming.NameNotFoundException: Name [appdb_two] is not bound in this Context. Unable to find [appdb_two].
at org.apache.naming.NamingContext.lookup(NamingContext.java:818) ~[catalina.jar:8.0.15]
Here is my configuration:
server.xml
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users-->
<Resource name="UserDatabase"
auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
<Resource name="jdbc/appdb_two"
auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.driver.OracleDriver"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"/>
<Resource name="jdbc/appdb_one"
auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.driver.OracleDriver"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"/>
</GlobalNamingResources>
context.xml
<ResourceLink name="jdbc/appdb_two"
auth="Container"
username="DBONE"
password="xxxx"
type="javax.sql.DataSource"
url="jdbc:oracle:thin:#xx.xxx.xxx.xxx:1521:XE"
initialSize="20"
maxActive="50"
maxIdle="20"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"/>
<ResourceLink name="jdbc/appdb_one"
auth="Container"
username="DBTWO"
password="xxxx"
type="javax.sql.DataSource"
url="jdbc:oracle:thin:#xx.xxx.xxx.xxx:1521:XE"
initialSize="20"
maxActive="50"
maxIdle="20"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"/>
...
I think you're looking up the second datasource via name "appdb_two", but should be using "jdbc/appdb_two" - it's hard to see from the stacktrace alone, code for lookup would be helpful.
Also check that your web.xml has references to both data sources (<resource-ref> elements).

NoInitialContextException

I have a problem.
I want to connect to database using JDBC, I have Tomcat server. For this I use connection pool.
According to Internet tutorials I've written:
context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/Server" docBase="dbcp" debug="5"
reloadable="true" crossContext="true">
<Resource name="jdbc/TestDB" auth="Container"
type="javax.sql.DataSource" removeAbandoned="true"
removeAbandonedTimeout="30" maxActive="100"
maxIdle="30" maxWait="10000" username="root"
password="newpass"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/delta_server"/>
</Context>
web.xml :
<resource-ref>
<description>DB Connection Pooling</description>
<res-ref-name>jdbc/TestDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
and I try to connect...
Connection conn=null;
DataSource ds;
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:comp/env");
ds = (DataSource) envContext.lookup("jdbc/TestDB");
conn = ds.getConnection();
But I get a mistake:
javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
What to do???

Categories