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.
Related
I have a web application which runs fine using embedded Tomcat server. What I need to do is to have a Tomcat server (not embedded) that has all the information about DB connection so that my app could connect this DB by means of JNDI. I followed this tutorial (except for Hibernate part cause I don't use it rn): https://www.baeldung.com/spring-persistence-jpa-jndi-datasource
but I fail to run my app cause of NoInitialContextException (Need to specify class name in environment or system property, or in an application resource file: java.naming.factory.initial).
My code:
#Configuration
#EnableTransactionManagement
#PropertySource("classpath:persistence-jndi.properties")
public class PersistenceJNDIConfig {
#Autowired
private Environment env;
#Bean
public DataSource dataSource() throws NamingException {
return (DataSource) new JndiTemplate().lookup(env.getProperty("jdbc.url"));
}
}
.properties file:
jdbc.url=java:comp/env/jdbc/postgres
server.xml in tomcat dir:
<Resource name="jdbc/postgres"
auth="Container"
type="javax.sql.DataSource"
driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://localhost:5432/university"
username="admin"
password="admin"
maxTotal="20"
maxIdle="10"
maxWaitMillis="-1"/>
context.xml
<ResourceLink
name="jdbc/postgres"
global="jdbc/postgres"
type="javax.sql.DataSource"/>
Any suggestions on how to solve this problem are much appreciated.
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;
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>
I write in the contex.xml:
<Resource name="1_db" auth="Container" type="javax.sql.DataSource" maxActive="50" maxIdle="30" maxWait="10000" username="root" password="tunespray2008" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/1_db">
<Resource name="2_db" auth="Container" type="javax.sql.DataSource" maxActive="50" maxIdle="30" maxWait="10000" username="root" password="tunespray2008" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/2_db">
<Resource name="3_db" auth="Container" type="javax.sql.DataSource" maxActive="50" maxIdle="30" maxWait="10000" username="root" password="tunespray2008" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/3_db">
<Resource name="common" auth="Container" type="javax.sql.DataSource" maxActive="50" maxIdle="30" maxWait="10000" username="root" password="tunespray2008" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/common">
Java code:
public static Connection getDBConnection(String url)
{
Connection con = null;
try
{
Context ctx = new InitialContext();
BasicDataSource ds = (BasicDataSource)tx.lookup("java:comp/env/"+url);
con = ds.getConnection();
}catch(Exception e) {}
return con;
}
After that I call:
String url ="common";
LoginDAO ldcom = DAOFactory.getLoginDAO(url);
url ="1_db";
LoginDAO ldcom = DAOFactory.getLoginDAO(url);
StatusDAO ldcom = DAOFactory.getStatusDAO(url);
After that when we watch through JProfiler it shows a lot of open connections, though we call con.close(), rs.close() or st.close().
Please mention how can we use a Datasource in the proper way?
There are 2 pojnts:
1) Allways close connections (and other DB resources) in a finally block. In your case, it might be something:
Connection conn = null;
try {
conn = getDBConnection(xxx);
// do stuff with the connection
}
// optionally catch any errors that you can handle
finally {
// close other DB resources that depend on conn, e.g. Statements, ResultSets
if( conn != null ) try { conn.close(); }
catch(Exception ignore) {}
}
2) The open connections you are seeing are probably the connection pool. Creating DB connections with DriverManager.getConnection() is an expensive (time consuming) process. In an application server environment, where there are many concurrent requests, creating a new connection per request would be a performance killer. The javax.sql.Datasource wraps a connection pool managed by the application server. When you close() a connection taken from that pool (the Datasource) it is not destroyed, rather returned to the pool for future usage.
I have the following resource tag in my context.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/myApp">
<Resource name="jdbc/myDS" auth="Container"
type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="1000"
username="user" password="passwd"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/myDB" />
</Context>
I am developing a Java web app using the Stripes framework in NetBeans.
How can I get this resource from within a Java class?
You need your bean to be instantiated by something (a dependecy injection framework) which knows how to handle the #Resrouce annotation. JSP itself doesn't know how.
In this case it would be simpler to locate the DataSource in the JNDI context:
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/myDS");
Thank you Bozho for the answer. I only had to change the lookup string to get it to work:
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/myDS");
Connection conn = ds.getConnection();