Getting Datasource instance which is configured in Application Server? - java

I have configured a Datasource in JBOSS EAP 6.3.2 using Admin console.
I want to know what are the ways in which we can get the instance of this Datasource? Can we use #Resouce , #Inject annotations to get the Datasource?
Or should we use the old JNDI lookup?
Can anyone please help me understand this?

I have never used Jboss EAP but as it's a Java EE 6 Server, you should be able to inject your datasource through #Resource annotation.
If it works the same as JBOSS AS 7, you should :
Define your datasource in standalone.xml
Inject the datasource specifying the lookup attribute of #Resource
#Resource(lookup = "java:jboss/MyDataSource")
private DataSource m_dataSource;

I am using weblogic and I am using the lookup for getting connection.
This may help you.
public Connection getConnection(){
DataSource dataSource = null;
Connection connection = null;
try {
InitialContext initContext;
initContext = new InitialContext();
dataSource = (DataSource) initContext.lookup("jdbc/MyDatasource");
try {
connection = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
}catch (Exception e) {
e.printStackTrace();
}
return connection;
}

Related

How to create oracle connection in java application, deployed in JBoss Server? (WrappedConnectionJDK8 cannot be cast to oracle.jdbc.OracleConnection)

I want to create oracle connection. Currently i am passing jdbc connection to create struct descriptor and here i am getting exception as below. so to avoid this, required to create a java.sql.connection or oracle connection instead of getting from data source.
org.jboss.resource.adapter.jdbc.jdk8.WrappedConnectionJDK8 cannot be cast to oracle.jdbc.OracleConnection
I found for JDK6 a solution, but it does not work for JDK8
How to create oracle connection in Spring application deployed in JBoss Server? (WrappedConnectionJDK6 cannot be cast to oracle.jdbc.OracleConnection)
You should use the unwrap method to obtain your instancedatasource.getConnection().unwrap(OracleConnection.class)
if you use an application server you can configure a Datasource and then use simple code like:
public class JDBCConnection {
#Resource(name = "jdbc/betting-offer-db") private DataSource dataSource;
public void executeQuery() {
logger.info("Reloading {}", getCacheNames());
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(getQuery())) {
processStatement(stmt);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}

How to Close HikariCP JNDI DataSource on Shutdown/Redeploy

I am using HikariCP 2.3.3 with Spring and Jetty 9 and am trying to resolve the fact that when I hot deploy a new war file, all of the Hikari database pool connections to MySQL are left open and idle. I am using a JNDI lookup in my spring applicationContext file to retrieve the datasource from a Jetty context file.
Since I cannot specify a destroy-method in the jndi-lookup like I can if I were to define a dataSource bean, I referred to this question: Should I close JNDI-obtained data source?, where it mentions you can attempt to close the datasource in the contextDestroyed() method of a ServletContextListener. In that case they were using tomcat and c3po so I'm not sure how much the example relates.
I have tried the following in my contextDestroyed method:
InitialContext initial;
DataSource ds;
try
{
initial = new InitialContext();
ds = (DataSource) initial.lookup("jdbc/myDB");
if (ds.getConnection() == null)
{
throw new RuntimeException("Failed to find the JNDI Datasource");
}
HikariDataSource hds = (HikariDataSource) ds;
hds.close();
} catch (NamingException | SQLException ex)
{
Logger.getLogger(SettingsInitializer.class.getName()).log(Level.SEVERE, null, ex);
}
But at HikariDataSource hds = (HikariDataSource) ds; I get the following exception: java.lang.ClassCastException: com.zaxxer.hikari.HikariDataSource cannot be cast to com.zaxxer.hikari.HikariDataSource
I have also tried the following after reading this issue on GitHub: Is it essential to call shutdown() on HikariDataSource?:
InitialContext initial;
DataSource ds;
try
{
initial = new InitialContext();
ds = (DataSource) initial.lookup("jdbc/myDB");
ds.unwrap(HikariDataSource.class).close();
} catch (NamingException | SQLException ex)
{
Logger.getLogger(SettingsInitializer.class.getName()).log(Level.SEVERE, null, ex);
}
But I get the following exception: java.sql.SQLException: Wrapped connection is not an instance of class com.zaxxer.hikari.HikariDataSource
at com.zaxxer.hikari.HikariDataSource.unwrap(HikariDataSource.java:177)
I feel like I'm close to a working solution but can't quite get it. What is the proper way to close a JNDI HikariCP data source, whether in contextDestroyed() or elsewhere?
I can't find where the 2.3.3 code lines up with the HikariDataSource.java:177 line number above. One suggestion is upgrading to the latest HikariCP version, 2.3.8.
While your code looks correct, I suspect that you are running into a classloader issue, whereby the HikariDataSource (class) loaded by Jetty/Spring classloader and registered in JNDI is not the same classloader that is loading HikariDataSource in your web app.
One quick way to check is to log/print both class instances like so:
...
ds = (DataSource) initial.lookup("jdbc/myDB");
logger.info("JNDI HikariDataSource : " + System.identityHashCode(ds.getClass()));
logger.info("Local HikariDataSource: " + System.identityHashCode(HikariDataSource.class));
...
If the two class objects have different hashCodes, they are not the same class. In which case you will have to investigate whether the JNDI instance is registered in the "global JNDI context". If it is, that datasource can be shared across web app instances, and it is not appropriate for your web app to unilaterally shut it down.
UPDATE: Sorry I missed it. Re-reading your question, my guess was correct. Your original error:
java.lang.ClassCastException: com.zaxxer.hikari.HikariDataSource cannot be cast to
com.zaxxer.hikari.HikariDataSource
is a clear indication that there are two classloaders that have loaded two separate instances of the HikariDataSource class. The first is the Jetty classloader (JNDI), and the second is your web application classloader.
This indicates that the pool is shared across web applications and you probably should not try to shut it down from your application context.

JAVA Datasource

I am trying to use a datasource that I set up on my weblogic server.
datasource JNDI name = thinOracleDataSource
in my code I have the following
public class DAOBean implements java.io.Serializable {
private Connection conn;
public void connect() throws ClassNotFoundException,
SQLException, NamingException {
Context ctx = new InitialContext();
// Lookup using JNDI name.
DataSource ds = (javax.sql.DataSource) ctx.lookup("thinOracleDataSource");
conn = ds.getConnection();
}
But I get this error
javax.naming.NameNotFoundException: While trying to look up /thinOracleDataSource in /app/webapp/PreAssignment2/24911485.; remaining name '/thinOracleDataSource'
am I looking the JNDI name in the right way? or am I missing something? Thanks for any help!!
EDIT:
This is the jndi tree that I can get from the weblogic console
Try naming your datasource jdbc/thisOracleDataSource in Weblogic and reference it as:
DataSource ds = (javax.sql.DataSource) ctx.lookup("jdbc/thinOracleDataSource");
Also, make sure the datasource is "targeted" to your weblogic Java server. All of this can be done in the Weblogic admin console.
Your JNDI key should look like approximately "java:comp/env/jdbc/thinOracleDataSource".
You can verify it by using Weblogic console that allows access (and probably search) in JNDI. So, you can check this manually before writing the code.

Tomcat6 connect to mySQL problems

I've followed another stackover flow thread to get to this point, it was this one here:
Tomcat6 MySql JDBC Datasource configuration
The problem I have is that the line that goes:
Connection conn = ds.getConnection();
from this block:
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource) envCtx.lookup("jdbc/TestDB");
Connection conn = ds.getConnection();
... use this connection to access the database ...
conn.close();
Eclipse gives me the error getConnection() is undefined for the type DataSource.
Its solution is to do this:
Connection conn = ((java.sql.Statement) ds).getConnection();
No tutorials show the need to do this, and its not working when I do that. I'm using mySQL jar named, mysql-connector-java-5.1.18-bin I've used it with RMI before but never Tomcat, is it the correct type for use with Tomcat?
TIA
If I look into the Java API docs http://docs.oracle.com/javase/6/docs/api/ I find the javax.sql.DataSource interface with a getConnection() method. I assume your DataSource to be something else than one implementing the javax.sql.DataSource interface. What "DataSource" is imported?

Java Oracle connection pooling - Closed Connection exception

This post is intended to be less of a question and more a confirmation that I'm doing things correctly. I've seen many similar posts but I'm not sure I fully understand everything that's been said.
The problem is that, after a certain amount of time, I get an exception when trying to establish a connection to my oracle database. (I'm using Tomcat 6.0 and Spring)
Previously I had the following configuration:
private PoolDataSource poolDataSource = null;
public MainDAOImpl(String url, String username, String password)
throws Exception
{
poolDataSource = PoolDataSourceFactory.getPoolDataSource();
try
{
poolDataSource.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
poolDataSource.setURL(url);
poolDataSource.setUser(username);
poolDataSource.setPassword(password);
}
catch( SQLException e )
{
...
}
}
public List<Object> getValues(String query)
{
Connection connection = null;
PreparedStatement preparedStatement = null;
try
{
connection = poolDataSource.getConnection();
preparedStatement = connection.prepareStatement(query);
...
}
catch( SQLException e )
{
...
}
finally
{
//close connections
}
}
However, sometimes the preparedStatement = connection.prepareStatement(query); threw an SQLException with a "Closed Exception" message.
It's important to note that the MainDAOImpl's constructor gets called only once per server restart (it's dependency injected via Spring).
I've recently changed my setup like so:
private DataSource dataSource = null;
public MainDAOImpl()
throws Exception
{
try
{
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
dataSource = (DataSource)envContext.lookup("jdbc/myOracleConn");
}
catch( NamingException e )
{
...
}
}
and poolDataSource.getConnection() to dataSource.getConnection().
I've also added the following Resource to my Context in Tomcat:
<Resource name="jdbc/myOracleConn" auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="<myURL>"
username="<myUsername>" password="<myPassword>"
maxActive="20" maxIdle="10" maxWaith="-1" />
This basically follows http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html word-for-word.
Everything seems to be working. My question is, will these changes solve my closed connection problem or is there something different I need to do?
Thanks,
B.J.
First of all, if you are using Spring for dependency injection, I would recommend that you also use DI to inject the DAO's dependencies into it.
In other words, your DAO should have a DataSource injected into it, rather than the DAO implementation knowing either 1) what type of DataSource to construct or 2) how and where to look it up in JNDI. Spring can handle JNDI lookups for you.
I'd also recommend using Spring's JdbcTemplate, as it makes for a great wrapper over raw JDBC calls yourself.
Finally, the actual exception you are getting may just be because the database server is closing long-open connections. Not sure which connection pool implementation you are using, but in commons-dbcp there is an option for a "validationQuery" which the pool will execute before returning a connection to verify the connection is still valid. I'm sure most other pools supply similar features, which I would recommend here - this way your DAO is never receiving stale connections from the pool.

Categories