tomcat datasource and jdbctemplate - java

I have been earlier injecting datasource (and using jdbctemplate for db operations) using spring DI individually for my two web application but then i consider its better to use datasource and connection pool on the Tomcat Level. So, now i am getting datasource from jndi and creating jdbctemplate using this datasource
public static DataSource getTomcatDataSource() {
DataSource dataSource = null;
try {
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env");
dataSource = (DataSource) envContext.lookup("jdbc/vendorDB");
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
return dataSource;
}
Adding more details for explaining my scenario, I am updating an sub-arraylist into db inside a for loop. So,i thought having connection pool would complete the task faster
for(int fromIndex = 0, toIndex = (fromIndex + batchSize - 1);
fromIndex < (sheetList.size() - 1) ;
fromIndex = toIndex + 1, toIndex += batchSize){
....
List<GoogleSheetPojo> subSheetList = sheetList.subList(fromIndex, toIndex);
try {
jdbcTemplate = new JdbcTemplate(DatabaseUtility.getTomcatDataSource());
rowsEffected = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
#Override
public void setValues(PreparedStatement pstmt, int i) throws SQLException {
MyPojo bean = subSheetList.get(i);
....
}
}
}
}
So, I had few doubts here:
1) Do update operations will become fast ?
2) my datasource method is static, so application would single database connection or should i get datasource without static in order to use database connection pool?
2) since, i created jdbctemplate using new operator, will jdbctemplate and pstmt will be closed safely by application
Lastly, would multithreading would make update operation faster ?
I hope my problem statement is understandable

Related

JSF Database connection Managedbean or POJO

I'm working on a small JSF Project where I use a DB.
I'm working with DAO's. I'm not sure if I did it right because I never used JSF before.
My DAO's are Managedbeans with the Annotation #RequestScoped
My DB connector is a POJO.
My Question is, can my DB connector be a POJO or does it Need to be a Managedbean?
You could have a connection service class like follows: (this example assumes you already have a datasource setup in your application server)
public class ConnectionDB {
private Context initContext;
private static Context webContext;
private static DataSource dataSource = null;
private ConnectionDB() {
try {
initContext = new InitialContext();
webContext = (Context) initContext.lookup("java:/comp/env");
dataSource = (DataSource) webContext.lookup("name_ds");
} catch (NamingException e) {
e.printStackTrace();
}
}
public static DataSource getDS() {
if (dataSource == null) {
new ConnectionDB();
}
return dataSource;
}
}
In your web.xml you would need to add the following:
<resource-ref>
<res-ref-name>name_ds</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Notice that I don't have it as a #ManagedBean.
Then you can use that class to initiate your connection in your other service classes, like follows:
public class Test{
private Connection conn;
private PreparedStatement prstmt;
private ResultSet rs;
public void testMethod() {
try {
conn = ConnectionDB.getDS().getConnection();
//create your sql, result sets and prepare statements
}
catch (SQLException e) {
e.printStackTrace();
}
}
}

Is a pooled db-access using method-level connection in a static class/method safe?

have been a long-time reader here and now I`ve got a problem I canĀ“t really get my head around.
For ease of access and to save object creation overhead I have a static class realizing database accesses. The used JVM implementation is Tomcat and for connection pooling org.apache.commons.dbcp is used.
I've read a lot about thread-safety, heap and stack here and elsewhere but I can`t get to a definitive conclusion if multiple method calls on my static class won't interfere with each other. Most topics I've read deal with instance methods while I use static ones which might have implications I overlooked.
If I understood everything correctly, as the variables connection, statement, resultset are on the method level, each function call should have a unique reference on the stack to a unique object in the heap and it should not be possible that multiple method calls interfere with each other.
Am I right or do I stand corrected? Any help would be appreciated.
The (shortened) code is :
public class DBQuery{
private static String pathToDataSource = "";
private static javax.naming.Context cxt = null;
private static javax.sql.DataSource ds = null;
private static void getDataSource() throws Exception {
if(pathToDataSource.equals("")){ pathToDataSource = Config.getParam("PathToDataSource"); }
cxt = new javax.naming.InitialContext();
ds = (javax.sql.DataSource) cxt.lookup(pathToDataSource);
}
private static Connection connect() throws Exception {
if(ds==null){ getDataSource(); }
return ds.getConnection();
}
public static Vector doDBquery(String querystring) throws Exception {
Vector retVec = new Vector();
Connection connection = null;
Statement statement = null;
ResultSet resultset = null;
try {
connection = getConnection();
statement = connection.createStatement();
resultset = statement.executeQuery(querystring);
...
} catch(Exception e) {
...
} finally {
myFinallyBlock(resultset, statement, connection);
}
return retVec;
}
// more methods like doDBInsert() following, hence closure in separate myFinallyBlock
private static void myFinallyBlock(ResultSet resultset, Statement statement, Connection connection) {
try {
if (resultset != null) resultset.close();
} catch (SQLException e) { resultset = null; }
try {
if (statement != null) statement.close();
} catch (SQLException e) { statement = null; }
try {
if (connection != null) connection.close();
} catch (SQLException e) { connection = null; }
}
} //close class
Yeah, you are right inside method there is no concurrency problems , until you are using shared variables inside it, in other words "Stateless objects are always thread-safe."
Servlet is quite good example of it ;)
edited.
For making your code safe I recommend you to do follow:
private static Connection connect() throws Exception {
if (ds == null) {
synchronized (Connection.class) {
if (ds == null) {
getDataSource();
}
}
}
return ds.getConnection();
}

Cannot find datasource in JUnit tests

I have this simple CDI bean which displays content into JSF page:
#Named("ZonesController")
#ViewScoped
public class Zones implements Serializable
{
#Resource(name = "jdbc/Oracle")
private DataSource ds;
...........
public int countDBRowNum() throws Exception
{
String SqlStatement = null;
if (ds == null)
{
throw new SQLException();
}
Connection conn = ds.getConnection();
if (conn == null)
{
throw new SQLException();
}
PreparedStatement ps = null;
ResultSet resultSet = null;
int count = 0;
try
{
conn.setAutoCommit(false);
boolean committed = false;
try
{
SqlStatement = "SELECT COUNT(1) FROM component x, componentstats y WHERE x.componentstatsid = y.componentstatsid AND y.componenttypeid = 1100";
ps = conn.prepareStatement(SqlStatement);
resultSet = ps.executeQuery();
if (resultSet.next())
{
count = resultSet.getInt(1);
}
conn.commit();
committed = true;
}
finally
{
if (!committed)
{
conn.rollback();
}
}
}
finally
{
ps.close();
conn.close();
}
// Returns total rows in table.
return count;
}
.............
}
I created this JUnit test case which calls the Java method:
public class ZonesTest
{
#BeforeClass
public static void setUpClass() throws Exception
{
try
{
// Create initial context
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.naming.java.javaURLContextFactory");
System.setProperty(Context.URL_PKG_PREFIXES,
"org.apache.naming");
InitialContext ic = new InitialContext();
ic.createSubcontext("java:");
ic.createSubcontext("java:/comp");
ic.createSubcontext("java:/comp/env");
ic.createSubcontext("java:/comp/env/jdbc");
// Construct DataSource
OracleConnectionPoolDataSource ds = new OracleConnectionPoolDataSource();
ds.setURL("jdbc:oracle:thin:#192.168.1.104:1521:oracle");
ds.setUser("admin");
ds.setPassword("qwerty");
ic.bind("java:/comp/env/jdbc/oracle", ds);
}
catch (NamingException ex)
{
//Logger.getLogger(MyDAOTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Test
public void testCountDBRowNum() throws Exception
{
Zones instance = new Zones();
int rows = instance.countDBRowNum();
System.out.println(rows);
}
}
I get error at these lines:
if (ds == null)
{
throw new SQLException();
}
How I can solve this problem? I want to use the datasource from the JUnit test during the testing. Can I somehow use the JUnit datasource?
You can make DataSource ds a JavaBean property and set its value on your JUnit test. This way you hide the complexity of the JNDI binding and focus your tests only on the business logic.
Your controller:
#Named("ZonesController")
#ViewScoped
public class Zones implements Serializable
{
#Resource(name = "jdbc/Oracle")
private DataSource ds;
public void setDs(DataSource ds){this.ds=ds;}
public DataSource getDs(){return ds;}
...
}
And you test class:
public class ZonesTest
{
private static OracleConnectionPoolDataSource ds;
#BeforeClass
public static void setUpClass() throws Exception
{
try
{
// Construct DataSource
ds = new OracleConnectionPoolDataSource();
ds.setURL("jdbc:oracle:thin:#192.168.1.104:1521:oracle");
ds.setUser("admin");
ds.setPassword("qwerty");
}
catch (NamingException ex)
{
//Logger.getLogger(MyDAOTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Test
public void testCountDBRowNum() throws Exception
{
Zones instance = new Zones();
instance.setDs(ds);
int rows = instance.countDBRowNum();
System.out.println(rows);
}
}
As a side note, following the MVC design pattern I would even decouple the controller business logic from the database connection, so no valid connection is needed to execute the unit tests and your focus is entirely on the behavior of your controller.
If you are using Spring and want to use all Spring beans within your JUnit class you can always use the #RunWith JUnit annotation.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class ZonesTest
{
#Autowire
Zones zones;
// your BeforeClass method here
#Test
public void testCountDBRowNum() throws Exception
{
int rows = zones.countDBRowNum();
System.out.println(rows);
}
}

session.connection() deprecated on Hibernate?

We need to be able to get the associated java.sql.Connection of a hibernate session. No other connection will work, as this connection may be associated with a running transaction.
If session.connection() is now deprecated, how am I supposed to do that?
You now have to use the Work API:
session.doWork(connection -> doSomething(connection));
Or, in Java < 8 :
session.doWork(
new Work() {
public void execute(Connection connection) throws SQLException
{
doSomething(connection);
}
}
);
If session.connect() is now deprecated, how am I supposed to do that?
You have to use Session#doWork(Work) and the Work API, as mentioned in the Javadoc:
connection()
Deprecated. (scheduled for removal in 4.x). Replacement depends on need; for doing direct JDBC stuff use doWork(org.hibernate.jdbc.Work); for opening a 'temporary Session' use (TBD).
You have some time before Hibernate 4.x but, well, using a deprecated API somehow looks like this:
:)
Update: According to RE: [hibernate-dev] Connection proxying on the hibernate-dev list, it seems that the initial intention of the deprecation was to discourage the use of Session#connection() because it was/is considered as a "bad" API, but it was supposed to stay at that time. I guess they changed their mind...
Try This
((SessionImpl)getSession()).connection()
Actuly getSession returns Session Interface type, you should see what is the original class for the session, type cast to the original class then get the connection.
GOOD LUCK!
Here is a way to do it in Hibernate 4.3, and it is not deprecated:
Session session = entityManager.unwrap(Session.class);
SessionImplementor sessionImplementor = (SessionImplementor) session;
Connection conn = sessionImplementor.getJdbcConnectionAccess().obtainConnection();
This is what I use and works for me.
Downcast the Session object into a SessionImpl and get the connection object easily:
SessionImpl sessionImpl = (SessionImpl) session;
Connection conn = sessionImpl.connection();
where session is the name of your Hibernate session object.
There's another option with still a lot of casts involved, but at least it doesn't need reflection, which will give you back compile time checking:
public Connection getConnection(final EntityManager em) {
HibernateEntityManager hem = (HibernateEntityManager) em;
SessionImplementor sim = (SessionImplementor) hem.getSession();
return sim.connection();
}
You could of course make that even "prettier" with a few instanceof checks, but the version above works for me.
connection() was just deprecated on the interface. It is still available on SessionImpl. You can do what Spring does and just call that one.
Here is the code from HibernateJpaDialect in Spring 3.1.1
public Connection getConnection() {
try {
if (connectionMethod == null) {
// reflective lookup to bridge between Hibernate 3.x and 4.x
connectionMethod = this.session.getClass().getMethod("connection");
}
return (Connection) ReflectionUtils.invokeMethod(connectionMethod, this.session);
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException("Cannot find connection() method on Hibernate session", ex);
}
}
I found this article
package com.varasofttech.client;
import java.sql.Connection;
import java.sql.SQLException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.SessionImpl;
import org.hibernate.jdbc.ReturningWork;
import org.hibernate.jdbc.Work;
import com.varasofttech.util.HibernateUtil;
public class Application {
public static void main(String[] args) {
// Different ways to get the Connection object using Session
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
// Way1 - using doWork method
session.doWork(new Work() {
#Override
public void execute(Connection connection) throws SQLException {
// do your work using connection
}
});
// Way2 - using doReturningWork method
Connection connection = session.doReturningWork(new ReturningWork<Connection>() {
#Override
public Connection execute(Connection conn) throws SQLException {
return conn;
}
});
// Way3 - using Session Impl
SessionImpl sessionImpl = (SessionImpl) session;
connection = sessionImpl.connection();
// do your work using connection
// Way4 - using connection provider
SessionFactoryImplementor sessionFactoryImplementation = (SessionFactoryImplementor) session.getSessionFactory();
ConnectionProvider connectionProvider = sessionFactoryImplementation.getConnectionProvider();
try {
connection = connectionProvider.getConnection();
// do your work using connection
} catch (SQLException e) {
e.printStackTrace();
}
}
}
It helped me.
With Hibernate >= 5.0 you can get the Connection like this:
Connection c = sessionFactory.
getSessionFactoryOptions().getServiceRegistry().
getService(ConnectionProvider.class).getConnection();
For hibenate 4.3 try this:
public static Connection getConnection() {
EntityManager em = <code to create em>;
Session ses = (Session) em.getDelegate();
SessionFactoryImpl sessionFactory = (SessionFactoryImpl) ses.getSessionFactory();
try{
connection = sessionFactory.getConnectionProvider().getConnection();
}catch(SQLException e){
ErrorMsgDialog.getInstance().setException(e);
}
return connection;
}
Try this:
public Connection getJavaSqlConnectionFromHibernateSession() {
Session session = this.getSession();
SessionFactoryImplementor sessionFactoryImplementor = null;
ConnectionProvider connectionProvider = null;
java.sql.Connection connection = null;
try {
sessionFactoryImplementor = (SessionFactoryImplementor) session.getSessionFactory();
connectionProvider = (ConnectionProvider) sessionFactoryImplementor.getConnectionProvider().getConnection();
connection = connectionProvider.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
Connection conn = null;
PreparedStatement preparedStatement = null;
try {
Session session = (org.hibernate.Session) em.getDelegate();
SessionFactoryImplementor sfi = (SessionFactoryImplementor) session.getSessionFactory();
ConnectionProvider cp = sfi.getConnectionProvider();
conn = cp.getConnection();
preparedStatement = conn.prepareStatement("Select id, name from Custumer");
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
System.out.print(rs.getInt(1));
System.out.println(rs.getString(2));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (preparedStatement != null) {
preparedStatement.close();
}
if (conn != null) {
conn.close();
}
}
Here is a Java 8 method to return the Connection used by an EntityManager without actually doing anything with it yet:
private Connection getConnection(EntityManager em) throws SQLException {
AtomicReference<Connection> atomicReference = new AtomicReference<Connection>();
final Session session = em.unwrap(Session.class);
session.doWork(connection -> atomicReference.set(connection));
return atomicReference.get();
}

Proper usage of JDBC Connection Pool (Glassfish)

I need a database connection in Java Web service implemented as a session bean, and I'm not sure if I do it right.
I created a class
public final class SQLUtils {
//.....
private static DataSource m_ds=null;
static
{
try
{
InitialContext ic = new InitialContext();
m_ds = (DataSource) ic.lookup(dbName); //Connection pool and jdbc resource previously created in Glassfish , dbName contains the proper JNDI resource name
}
catch (Exception e)
{
e.printStackTrace();
m_ds = null;
}
}
public static Connection getSQLConnection() throws SQLException
{
return m_ds.getConnection();
}
}
Whenever I need a connection I do
Connection cn = null;
try
{
cn = SQLUtils.getSQLConnection();
// use connection
}
finally
{
if (null != cn)
{
try
{
cn.close();
}
catch (SQLException e)
{
}
}
}
Is it ok to use it this way, or I DataSource must be a member of the bean ?
#Stateless
#WebService
public class TestBean {
private #Resource(name=dbName) DataSource m_ds;
}
I'm sorry if it is a nube question, but I'm pretty new to Java. Thanks in advance.
Apart from the C-style formatting, a few unnecessary lines and a bit poor exception handling, you can just do so.
Here's how I'd do it:
public final class SQLUtil {
private static DataSource dataSource;
// ..
static {
try {
dataSource = (DataSource) new InitialContext().lookup(name);
} catch (NamingException e) {
throw new ExceptionInInitializerError(e);
}
}
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
}
I throw here ExceptionInInitializerError so that the application will immediately stop so that you don't need to face "unexplainable" NullPointerException when trying to obtain a connection.
In the ancient J2EE world, the traditional way to manage this was to use a ServiceLocator. Below, a sample implementation (non optimized, the DataSource could be cached):
public class ServiceLocator {
private Context initalContext;
private static ServiceLocator ourInstance = new ServiceLocator();
public static ServiceLocator getInstance() {
return ourInstance;
}
private ServiceLocator() {
try {
this.initalContext = new InitialContext();
} catch (NamingException ex) {
throw new ServiceLocatorException(...);
}
}
public DataSource getDataSource(String dataSourceName) {
DataSource datasource = null;
try {
Context ctx = (Context) initalContext.lookup("java:comp/env");
datasource = (DataSource) ctx.lookup(dataSourceName);
} catch (NamingException ex) {
throw new ServiceLocatorException(...);
}
return datasource;
}
}
To use it, simply call it like this:
DataSource ds = ServiceLocator.getInstance().getDataSource("jdbc/mydatabase");
But this was prior to the EJB3 and Dependency Injection era. Now, when using EJB3, if you have setup your DataSource in your EJB container, all you have to do to automatically inject the DataSource in your Stateless Bean is to write (where mydatabase is the name of the datasource):
#Resource
private DataSource mydatabase;
Use the name attribute if you want to explicitly, well, set the name:
#Resource(name="jdbc/mydatabase")
private DataSource dataSource;
EJB3 actually make the ServiceLocator pattern obsolete and you should really prefer injection when working with them.
Um, isn't this an example to a JDBC DataSource, not a Glassfish Connection Pool?

Categories