Injecting datasource in EJB - java

When you inject a datasource in your application and get a connection by invoking getConnection() on it, are you supposed to close the connection?

Even though the datasource itself is container managed, the API indeed requires the programmer to close connections. This is different from a couple of other container managed resources (like the entity manager), where the container takes care of closing. Note that closing here in the majority of cases doesn't actually closes the connection here, but returns the connection to a connection pool.
As a rule of thumb, if you use a factory-ish resources to obtain one or more other resources from that can be closed, you have to close them. Otherwise the container does this.
Since Connection implements AutoCloseable, you can use a try-with-resources block for this:
#Stateless
public class MyBean {
#Resource(lookup = "java:/app/datasource")
private DataSource dataSource;
public void doStuff() {
try (Connection connection = dataSource.getConnection()) {
// Work with connection here
} catch (SQLException e) {
throw new SomeRuntimeException(e);
}
}
}

Of course, otherwise you'll exhaust your connection pool. It's best to do this in finally block:
#Resource(mappedName="jndi/yourDatasource")
DataSource ds;
..
Connection conn = null;
try {
conn = ds.getConnection();
//PERFORM QUERY, ETC..
}
catch(SQLException ex) {
//EXCEPTION HANDLING
}
finally {
try {
if(conn != null)
conn.close();
}
catch(SQLException ex) {..}
}

Related

Why close method of class that implements Autoclosable interface is called first than Sql connection close?

I found solution to rollback transaction when commit fails and It works perfectly.
But could you explain why Autorollback object close method is called first than connection close?
Autorollback class :
public class AutoRollback implements AutoCloseable {
private Connection conn;
private boolean committed;
public AutoRollback(Connection conn){
this.conn = conn;
}
public void commit() throws SQLException {
conn.commit();
committed = true;
}
#Override
public void close() throws SQLException {
if(!committed) {
conn.rollback();
}
}
}
example of service method that use Autorollback:
try(Connection connection = MySQLDAOFactory.getConnection();
AutoRollback autoRollback = new AutoRollback(connection)){
result = carDao.insertCar(connection,car);
autoRollback.commit();
} catch (SQLException | NamingException | MySQLEXContainer.MySQLDBExecutionException throwables) {
throw new ApplicationEXContainer.ApplicationCanNotChangeException(throwables.getMessage(),throwables);
}
Why does Autorollback's close method works?If connection is closed how can it call rollback method?So the only explanation is autorollback close method is called earlier thah connection close, but why?
Because that's how JLS says it has to work:
A try-with-resources statement is parameterized with variables (known as resources) that are initialized before execution of the try block and closed automatically, in the reverse order from which they were initialized, after execution of the try block.
Source

ActiveMQ inactive broker

The problem is that I have defined some broker uri which could be inactive.
Then createConnection from ActiveMQConnectionFactory doesn't throw any exception. I need to handle such situation and if createConnection doesn't work because of uri won't be available then I should mark my service as unhealthy.
boolean healthy = true;
Connection conn = null;
try {
final ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("failover:(tcp://localhost:8080)?jms.prefetchPolicy.all=0&initialReconnectDelay=1000&maxReconnectDelay=30000&maxReconnectAttempts=20");
conn = factory.createConnection(this.userName, this.password);
} catch (JMSException e) {
healthy = false;
} finally {
if (conn != null) {
try {
conn.close();
} catch (JMSException e) {
healthy = false;
}
}
}
So you want create connection to fail with an exception but you are also using the failover transport? Doesn't that seem at odds to you?
The failover transport usage is resulting in the create to succeed because the failover transport is doing exactly what you asked it to do which is to try and establish a connection repeatedly until the configured number of attempts is made. Calling a method like create session will block and eventually throw an error once the failover transport gives up. Alternately you could set an exception listener that will be signalled once the connection is closed because the failover transport runs out of reconnect attempts.

Proper way to handle JDBC connection in EJB 3 (SLSB)

I ask this question especially for Stateless Session Bean. I knew that I can easily inject the DataSource with the #Resource annotation. But I don't know what is the proper way to get the Connection. Is it in each method of the bean, or in the method annotated with #PostConstruct? And also for the closing of the Connection. Do I have to close it within the finally block in each method call, or in the method annotated with #PreDestroy?
Is it safe to create an instance variable for the Connection, for example:
#Stateless
public class MyBean {
#Resource private DataSource ds;
private Connection conn;
#PostConstruct
public void onCreate() {
conn = ds.getConnection(); // within try catch block
}
#PreDestroy
public void onDestroy() {
conn.close() // within try catch block
}
}
Or should I create them locally in each method like this:
#Stateless
public class MyBean {
#Resource private DataSource ds;
public void method1() {
Connection conn = null;
// get and close connection...
}
public void method2() {
Connection conn = null;
// get and close connection...
}
}
Some people in the Internet do this way, and some other do that way. What is the proper method to be implemented in an application with a high request traffic? When the bean instance is returned back to the EJB pool, does the Connection remains opened or does it returned to the database pool?
Note: The application is using native JDBC API. There are no JPA, JDO, etc.. The application server is Wildfly.
TL;DR
The second approach is the correct one. Just make sure to close the connection to return it to the Pool.
The Datasource is a pool of connections, every time you get a connection it borrows one from the datasource and when you close that connection it will be returned to the pool, so you will always want to release the connection as soon as possible.
In the first approach you will retain the connection for as long as the EJB lives in memory. Since the EJB is an Stateless bean it will be alive for long and reused by diferent consumenrs. Making you have at least 1 connection open per EJB that is alive thus this approach is not practical.
The second approach is the correct one. Just make sure to close the connection to return it to the Pool. With this approach the Bean will only retain the connection while in use. Just make sure to close the connection to return it to the Pool.
#Stateless
public class MyBean {
#Resource private DataSource ds;
public void method1() {
try(Connection conn = ds.getConnection()){
// Do anything you need with the connection
}
}
public void method2() {
Connection conn = ds.getConnection();
try {
// Do anything you need with the connection
} finally {
connection.close();
}
}
}

The best way to implement producer-consumer in web app

Here is my scenario:
Each minute one thread checks database looking for some items.
When items are found, they are passed to the another thread(consumer).
I use spring in my application, but it doesn't meant that I must use spring's classes, right?
So, now I'm totally lost in the woods of ScheduledExecutorService (java), ExecutorService (java), TaskExecutor (spring), TaskScheduler (spring), #Scheduled (spring).
Help me please to understand what is the right way to implement my scenario.
If I understand your question, you are using a Shared Database Pattern which, for for many reason is somewhat discouraged and used as a last resource.
If you want multiple application to communicate, and be decoupled, you should use Messaging ( eg: Spring Cloud Stream ).
Anyway, if you need to have a Shared Database, you may want what Listen / Notify provide.
From https://jdbc.postgresql.org/documentation/81/listennotify.html:
import java.sql.*;
public class NotificationTest {
public static void main(String args[]) throws Exception {
Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://localhost:5432/test";
// Create two distinct connections, one for the notifier
// and another for the listener to show the communication
// works across connections although this example would
// work fine with just one connection.
Connection lConn = DriverManager.getConnection(url,"test","");
Connection nConn = DriverManager.getConnection(url,"test","");
// Create two threads, one to issue notifications and
// the other to receive them.
Listener listener = new Listener(lConn);
Notifier notifier = new Notifier(nConn);
listener.start();
notifier.start();
}
}
Listener
class Listener extends Thread {
private Connection conn;
private org.postgresql.PGConnection pgconn;
Listener(Connection conn) throws SQLException {
this.conn = conn;
this.pgconn = (org.postgresql.PGConnection)conn;
Statement stmt = conn.createStatement();
stmt.execute("LISTEN mymessage");
stmt.close();
}
public void run() {
while (true) {
try {
// issue a dummy query to contact the backend
// and receive any pending notifications.
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT 1");
rs.close();
stmt.close();
org.postgresql.PGNotification notifications[] = pgconn.getNotifications();
if (notifications != null) {
for (int i=0; i<notifications.length; i++) {
System.out.println("Got notification: " + notifications[i].getName());
}
}
// wait a while before checking again for new
// notifications
Thread.sleep(500);
} catch (SQLException sqle) {
sqle.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}
Notifier
class Notifier extends Thread {
private Connection conn;
public Notifier(Connection conn) {
this.conn = conn;
}
public void run() {
while (true) {
try {
Statement stmt = conn.createStatement();
stmt.execute("NOTIFY mymessage");
stmt.close();
Thread.sleep(2000);
} catch (SQLException sqle) {
sqle.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}
Instead of using ScheduledExecutorService you can user quartz scheduler that is used to schdule some jobs in specific intervals, in your case every minute. It can be easily integrated with spring.
Cron expressions are used to specify the time when to schedule.
You can write your logic that checks database looking for some items in a class that extends QuartzJobBean class.
See:
https://examples.javacodegeeks.com/enterprise-java/quartz/spring-quartz-scheduler-example/

Java Connection Pooling - garbage collection or call close()?

My fear is that I have a fundamental issue with understanding connection pooling in Java.
I'm using IDBCDataSource as a connection pool.
At the entry point of my application I instantiate a BasicDataSource with for instance setMaxActive=50. The instance of that DataSource is than handed into various DAOs that are utilized by some business logic.
Each DAO calls getConnection(), but there is no single close() called. My assumption is that after a DAO is not used the garbage collector closes the connections.
My issue is that Im constantly running out of connections (i.e. code waiting for an available connection).
Now lets say I would add a close() call at the end of each database operation. What happens with thrown Exceptions. I would have to catch every Exception in the DAO, make sure to close the connection and then re-throw the occurred Exception!
Example - Current Approach:
public class MyDAO {
private Connection con;
public MyDAO (DataSource ds) {
con = ds.getConnection();
}
public MyReturnClass execSomeQuery() throws SQLException {
String sql = String.format("SELECT * FROM foo");
PreparedStatement ps = con.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
…
...
}
return result;
}
}
public class MyAppLogic() {
DataSource ds;
public MyAppLogic(DataSource ds) {
this.ds = ds;
}
public void doSomeStuff() {
MyDAO myDAO = MyDAO(ds);
myDAO.execSomeQuery();
}
}
You need to close the connections so that they return in the connection pool. GC will not call close on your connections!
You could create a wrapper or parent class that manages the connection, so that you don't have to replicate the logic in each method. Here's an example (note that I haven't actually compiled or tested this).
public interface DAOClass {
public void execSomeQuery() throws SQLException;
}
public class MyDAOWrapper {
private DAOClass dao;
private DataSource ds;
public MyDAOWrapper(DataSource ds, DAOClass dao) {
this.dao = dao;
this.ds = ds;
}
public void exec() throws SQLException {
Connection con = ds.getConnection();
try {
dao.execSomeQuery();
}
finally {
con.close();
}
}
}
// usage
public void doSomeStuff() throws SQLException {
MyDAOWrapper dao = new MyDAOWrapper(ds, new MyDAO());
dao.exec();
}
Regarding error handling, you don't need to rethrow an exception unless you catch it. Your finally clause should close the connection (if it exists) and when that exits, the exception will continue propagating up.
try {
do_something();
}
finally {
cleanup();
// throw is not necessary
}

Categories

Resources