So, I'm trying to make a Mongo connection that remains persistent across several uses of the application (page accesses). I'm tired of all these connections building up during my testing, and I want to use proper procedure by having that single persistent connection. Best practices and all that.
Here's what I have:
web.xml
<listener>
<listener-class>com.core.tools.MyServletContextListener</listener-class>
</listener>
com.core.tools.MyServletContextListener
public class MyServletContextListener implements ServletContextListener {
private static Logger log = org.apache.log4j.Logger.getLogger(MyServletContextListener.class);
public void contextInitialized( ServletContextEvent sce ){
try {
EntityManager.setupMongoClient(sce);
} catch (UnknownHostException e) {
log.error("Error setting up Servlet Context");
}
}
public void contextDestroyed( ServletContextEvent sce ){
EntityManager.closeMongoClient(sce);
}
}
EntityManager
public class EntityManager {
private static MongoClient mongoConnection = null;
private static Jongo jongoDatasource = null;
public static void setupMongoClient( ServletContextEvent sce ) throws UnknownHostException{
if( sce.getServletContext().getAttribute("mongo") == null ){
mongoConnection = new MongoClient("localhost");
sce.getServletContext().setAttribute("mongo", mongoConnection );
}else if (mongoConnection == null) {
mongoConnection = (MongoClient) sce.getServletContext().getAttribute("mongo");
}
}
public static Jongo getJongoDatasource(){
if( jongoDatasource == null ){
jongoDatasource = new Jongo(mongoConnection.getDB("coreTest"));
}
return jongoDatasource;
}
public static void closeMongoClient( ServletContextEvent sce ){
if( sce.getServletContext().getAttribute("mongo") != null ){
mongoConnection = (MongoClient) sce.getServletContext().getAttribute("mongo");
mongoConnection.close();
}
}
}
What happens:
Good news - now my connections get cleaned up when the server closes.
Bad news - I still keep getting lots and lots of connections being created. Every time I hit the button, it makes a new connection ... but only for about 4 or 5 connections. Then it suddenly stops adding new connections for a while. Then it'll add 3 more. Then wait. Then another 2. Then nothing. Then a few minutes later, suddenly it'll add another 5 connections.
Confusing: I don't even know how it's managing to make those connections. Tracking the method calls - setupMongoClient is only called once - when the apache server starts up. It's the only place in the whole system that sets mongoConnection.
Whenever I press the button, mongoConnection is not set. And yet, the data is pulled from the mongo database, and testing mongoConnection shows me that it is not null.
How is mongoConnection not null? And why are new connections sporadically being made?
MongoClient is a connection pool; it maintains a number of open connections to the database for performance (creating new connection is costly).
when you call mongoConnection.getDB("DB"), MongoClient will retrieve a database connection from the connection pool. if there are no available connections in the connection pool, it will create a new connection and add it to the pool.
when you call mongoConnection.close(), the connection is not tear down. it is simply returned to the connection pool to be reused.
by default, the pool size is 5. this explains why you will eventually have 5 open connections even though you have closed them (remember, "closed" connections are returned to the pool). you can change this size
Related
I code my Test project and it is prohibited to use Spring and Hibernate there.
I wanted to manage my transactions from Service layer.
For this I have created a class that gets a Connection from the pool and puts it in the ThreadLocal.
This is an example of the fields and the method.
private static ThreadLocal<Connection> threadLocalConnection;
private ComboPooledDataSource comboPooledDataSource ;
public boolean createConnectionIfAbsent() {
boolean isConnectionCreated = false;
try {
Connection currentConnection = threadLocalConnection.get();
if(currentConnection == null) {
Connection conn = this.comboPooledDataSource.getConnection();
conn.setAutoCommit(false);
threadLocalConnection.set(conn);
isConnectionCreated = true;
}
} catch (SQLException e) {
e.printStackTrace();
}
return isConnectionCreated;
}
The class has also close, rollback methods.
Here is the example of how I manage Connections in a Service Layer.
public BigDecimal getTotalOrdersCount() {
boolean connectionCreated = DBManager.getInstance().createConnectionIfAbsent();
BigDecimal ordersCount = BigDecimal.ZERO;
try {
ordersCount = orderDao.getRowNumber();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
if (connectionCreated) DBManager.getInstance().closeConnection();
}
return ordersCount;
}
Dao just uses this to get the connection.
Connection connection = DBManager.getInstance().getConnection();
I found no other way to manage connections in a Servlet project from a Service layer, could you please tell if it is ok? If not - what drawbacks does it have and what should I use instead.
UPD:
Please pay attention to this Service method. Let's assume that Each method in DAO gets the Connection from a pool and closes it.
I do know that I need connection.setAutoCommit(false); to start a transaction, but what to do it in this kind of a situation?
When a single methods calls 2 DAO.
Just give up on a transaction handling?
void setStatusDeclinedAndRefund() {
// sets Order status to DECLINED
// refund money to user's balance
}
No.
Don't second guess the connection pool. Use it in the standard way: get a connection, use it, close it.
There is no need to use the same connection for every database interaction in a given thread. Also, you'll have serious liveliness problems if you allocate each thread a connection, because typically there are way more request processing threads than there are connections in the pool.
I am learning about MySQL database and I cannot quite understand one concept. Lets say there are two methods in the same class as the one shown below. Now, do i have to use Connection connect = dbConnection.getDBConnection(); in each method or is there a different way to declare one connection and use it across multiple methods?:
private void setUpdateButton(ActionEvent event) {
try{
Connection connect = dbConnection.getDBConnection();
Statement stmt = connect.createStatement();
if(txtID.getText().trim().isEmpty()||txtFirstName.getText().trim().isEmpty() || txtSecondName.getText().trim().isEmpty() ||
txtGender.getText().trim().isEmpty() || txtAge.getText().trim().isEmpty() || txtHomeAddress.getText().trim().isEmpty() || txtPhoneNumber.getText().trim().isEmpty()) {
showAlert("Invalid Input!", "All fields need to be populated before updating.");
}else {
String sqlQuery ="update student_information set Age ='"+Integer.parseInt(txtAge.getText())+"',Name ='"+txtFirstName.getText()+"',Surename='"+txtSecondName.getText()
+"',Gender='"+txtGender.getText()+"',Address='"+txtHomeAddress.getText()+"',PhoneNumber='"+txtPhoneNumber.getText()+"'where ID="+Integer.parseInt(txtID.getText());
stmt.executeLargeUpdate(sqlQuery);
setTxtArea();
showConfAlert("Update Completed!", "Record has been updated!");
Creating connections is a costly operation, so I think you should open the connection at the application startup, and close it on exit.
If your program is not multi thread you would be fine with a simple global object, otherwise other strategies should be used.
You can create a singleton for your app with a method returning the connection.
public class App {
private static App self;
private Connection connection;
private App(){
}
public synchronized App getInstance(){
if(self == null){
self = new App();
}
return self;
}
public synchronized Connection getConnection()throws SQLException {
if(connection==null || !isValid(connection)){
// Create a new connection
}
return connection;
}
private boolean isValid(Connection conn) {
// Check if the connection is valid otherwise return false
return false;
}
public static synchronized void close(){
try{
self.connection.close();
} catch (SQLException e){
// Swallow exception
} finally {
self = null;
}
}
}
You can get the connection anywhere like this:
Connection conn = App.getInstance().getConnection();
You should make sure to close the connection on exit, maybe with a shutdown hook.
You could also, create a wrapper around your connection that forwards all connection methods to the original connection , with the exception of close that marks the connection available , this way you create something like 1 connection pool.
If the connection is available you return it otherwise you either wait or throw or do what is most appropriate for your application.
I need to use a connection pool in a standalone (as in non-web) Java application. Where I work, we are not allowed to use APIs without going through layers of security, and the job needs to be completed soon. Below is my attempt at creating this connection pool.
I have unit tested this code and tested it within the context of the overall application a hundred times and in all cases the tests passed with zero errors, and in addition the performance of each run is just under three thousand times faster than a simple connect, retrieve data, disconnect in serial approach; however, I still have nagging concerns that there could be issues with this approach that I simply haven't unearthed yet. I would appreciate any advice anyone has concerning the below code. This is my first post on this site; please let me know if I've made any errors in etiquette. I did search this site about this problem before posting. Please see below the code for an invocation example. Thanks. --JR
package mypackage;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* Note: This class is only instantiated once per application run.
* Multiple instantiations, as specified in the release notes,
* are not supported.
*/
public class ConnectionManager {
// Use a blocking queue to store the database connections.
// The application will only be called once, by a single user,
// but within the application many threads will require
// a connection.
private BlockingQueue<Connection> connectionQueue = null;
// Load the connection queue with a user-defined number of connections.
// Params contains a map of all non hard-coded variables in the
// application.
public ConnectionManager(int howMany, Map<String, Object> params) {
Database database = new Database();
connectionQueue = new ArrayBlockingQueue<Connection>(howMany);
for(int i = 0; i < howMany; i++) {
connectionQueue.add(database.getConn(params));
}
}
// Return a connection from the queue, waiting up to 15 minutes to do so.
// 15 minutes is hard-coded because it is the standard time-out for all
// processes at our agency. This application must complete in less
// than fifteen minutes (is currently completing in thirty five seconds).
public Connection getConnection() {
Connection conn = null;
try {
conn = connectionQueue.poll(15, TimeUnit.MINUTES);
}
catch(InterruptedException e) {
e.printStackTrace();
}
catch(SQLException e) {
e.printStackTrace();
}
return conn;
}
// Returns a connection to the connection queue.
public void returnConnectionToManager(Connection conn) {
connectionQueue.add(conn);
}
// Called on the last line of the application program's dispatcher.
// Closes all active connections (which will only exist if there
// was a failure within one of the worker threads).
public void closeAllConnections() {
for(Connection conn : connectionQueue) {
try {
conn.close();
}
catch(SQLException e) {
e.printStackTrace();
}
}
}
}
Invocation example:
...
private ConnectionManager cm;
...
public Table(Map<String, Object> params, String method) {
...
cm = (ConnectionManager) params.get("cm");
}
// Execute a chunk of SQL code without requiring processing of a
// result set. Acquires connection from pool via cm.getConnection
// and releases connection via cm.returnConnectionToManager.
// (Database is just a helper class with simple methods for
// closing prepared statement, result sets, etc.)
private void execute(String sql) {
PreparedStatement ps = null;
Connection conn = null;
try {
conn = cm.getConnection();
ps = conn.prepareStatement(sql);
ps.execute();
}
catch (SQLException e) {
e.printStackTrace();
}
finally {
database.closePreparedStatement(ps);
cm.returnConnectionToManager(conn);
}
}
Your code looks good, but there is one serious problem, that clients of your API needs to take care of getting and releasing connection, one of them forget, and memory/resource leak is ready.
Make a one place in which you posts your queries to execute, in this place take connection, execute query and return the connection to the pool. It will secure you that the connections are returned. If you need to invoke multiple queries one after another in a single connection make the method accept an array or list of SQL queries to execute in order. The idea is to encapsulate each request to the db, so you manage all connections. It could be donethat you write an interface that has en execute(Connection conn) which you need to implement, and you could have then some Service that takes such object gives it a connection and then releases the resources back to connection pool.
Something like:
interface SqlWork {
execute(Connection conn);
}
SqlWork myWork = new SqlWork () {
execute(Connection conn) {
// do you work with the conn here
}
}
class SqlExecutionService {
ConnectionManager cm = ...;
public void execute(SqlWork sqlWork) {
Connection conn = null;
try {
conn = cm.getConnection();
sqlWork.execute(conn);
} catch (Your exceptions here) {
//serve or rethrow them
}
finally
{
if (conn!=null) {
cm.returnConnectionToManager(conn);
}
}
}
}
Example of use:
SqlExecutionService sqlExecService = ...;
sqlExecService.execute(myWork);
I'm working on a Neo4J database, using it in a little social network. The idea is:
As a user, you connect to the website, and it connects you to a N4J db.
I tried to avoid problem related to multiple instances of the db by creating it through a Singleton. However, I think my users must be able to "connect" and "disconnect", so I created method for that, but when I use disconnect() on a user, the others run through a NullPointerException due to the fact that they can't access the db anymore (which I thought was handled by the Singleton).
Here is the code, which I believe will make things clearer :
The main that I use to test my code :
public static void main(String[] args) {
Node root;
N4JAdmin admin = new N4JAdmin();
Transaction tx = GraphDB.getGraphDb().beginTx();
try {
root = GraphDB.getGraphDb().createNode();
root.setProperty("Nom", "aname");
root.setProperty("Prenom", "afirstname");
tx.success();
} finally {
tx.finish();
}
N4JUser sr = admin.addUser("Ribeiro", "Swen", 1);
//14 more addUser, it creates nodes in the db with the 3 properties, works fine
// The following connect() calls are commented because the errors occurs with or without them
// sr.connect();
// the 14 others...
sr.addAcquaintance(cw.getUserNode());
sr.addAcquaintance(fc.getUserNode());
sr.disconnect();
System.out.println("+++++++++ sr disconnected ++++++++++");
bm.addAcquaintance(cm.getUserNode());
// and more operations...
GraphDB.getGraphDb().shutdown();
}
the addAquaintance code :
public void addAcquaintance(Node target) {
Transaction tx = GraphDB.getGraphDb().beginTx();
try {
this.userNode.createRelationshipTo(target, RelTypes.CONNAIT);
System.out.println(this.userNode.getProperty("Nom")+" "+this.userNode.getProperty("Prenom")+" est maintenant ami avec : "+ target.getProperty("Nom")+" "+target.getProperty("Prenom"));
tx.success();
} finally {
tx.finish();
}
}
And the GraphDB class, which is my Singleton :
public final class GraphDB {
private static final String DB_PATH = "/Workties/database/workties.db";
private static GraphDatabaseService graphDb;
private static boolean instanciated = false;
private GraphDB(){
GraphDB.graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH);
registerShutdownHook(graphDb);
GraphDB.instanciated = true;
}
private static void registerShutdownHook( final GraphDatabaseService graphDb ){
Runtime.getRuntime().addShutdownHook( new Thread(){
#Override
public void run(){
graphDb.shutdown();
}
} );
}
public static GraphDatabaseService getGraphDb(){
if (!GraphDB.instanciated) {
new GraphDB();
System.out.println("New connection : " +GraphDB.graphDb.toString());
}
return GraphDB.graphDb;
}
}
Note : the instanciated attribute was added later, but even without it it didn't work.
My problem comes from the fact that I thought this type of error wouldn't happen using a Singleton, so I'm a bit stuck...
Thanks in advance for your help !
EDIT : the disconnect method :
public void disconnect(){
GraphDB.getGraphDb().shutdown();
}
You should not have to call shutdown for every user- once the DB is instantiated for the first time, it is enough to last you for all your querying etc. Why do you want to connect and disconnect?
The nullpointer is because shutdown shuts down Neo4j but your singleton still thinks instanciated=true, so it returns a handle to a graphDb that isn't really there. Even without the instanciated variable which you added, the singleton maintains a reference to graphDb after it's shutdown.
Strongly advise against doing the shutdown at all unless your app is terminating.
In one of the interviews that I faced,I was asked to implement connection pooling.
So approach was this:
Create a List or HashMap
Create predefined number of connections
Add them to the collection.
Now when the ConnectionImpl getConnection() method of ConnectionPoolingImpl class is invoked return a connection reference.
Now when someone returns the connection (releaseConnection(ConnectionImpl O)) how can I ensure that when the same application again tries to reuse the connection object, my implementation throws an exception?
The same connection object might have been returned to a new application and that should be able to use it.
My point of view would be to maintain a flag variable in another array kind of structure for each Connectionimpl object and set that variable to a valid value. When user returns the connection object I would make that some invalid value. For every operation in my ConnectionImpl, I will have to verify if the user had a valid flag.
What would you say to that approach?
I would not return the "real" connection object from the pool, but a wrapper which gives the pool control of connection life cycle, instead of the client.
Assume you have a really simple connection, which you can read int values from:
interface Connection {
int read(); // reads an int from the connection
void close(); // closes the connection
}
An implementation reading from a stream could look like this (ignoring exceptions, EOF handling, etc):
class StreamConnection implements Connection {
private final InputStream input;
int read(){ return input.read(); }
void close(){ input.close(); }
}
Furthermore, let's assume you have a pool for StreamConnections that looks like this (again, ignoring exceptions, concurrency, etc):
class StreamConnectionPool {
List<StreamConnection> freeConnections = openSomeConnectionsSomehow();
StreamConnection borrowConnection(){
if (freeConnections.isEmpty()) throw new IllegalStateException("No free connections");
return freeConnections.remove(0);
}
void returnConnection(StreamConnection conn){
freeConnections.add(conn);
}
}
The basic idea here is OK, but we can't be sure the connections are returned, and we can't be sure they aren't closed and then returned, or that you don't return a connection which came from another source altogether.
The solution is (of course) another layer of indirection: Make a pool which returns a wrapper Connection which, instead of closing the underlying connection when close() is called, returns it to the pool:
class ConnectionPool {
private final StreamConnectionPool streamPool = ...;
Connection getConnection() {
final StreamConnection realConnection = streamPool.borrowConnection();
return new Connection(){
private boolean closed = false;
int read () {
if (closed) throw new IllegalStateException("Connection closed");
return realConnection.read();
}
void close() {
if (!closed) {
closed = true;
streamPool.returnConnection(realConnection);
}
}
protected void finalize() throws Throwable {
try {
close();
} finally {
super.finalize();
}
}
};
}
}
This ConnectionPool would be the only thing the client code ever sees. Assuming it is the sole owner of the StreamConnectionPool, this approach has several advantages:
Reduced complexity and minimal impact on client code - the only difference between opening connections yourself and using the pool is that you use a factory to get hold of Connections (which you might already do, if you're using dependency injection). Most importantly, you always clean up your resources in the same way, i.e., by calling close(). Just like you don't care what read does, as long as it gives you the data you need, you don't care what close() does, as long as it releases the resources you've claimed. You shouldn't have to think whether this connection is from a pool or not.
Protection against malicious/incorrect usage - clients can only return resources they've retrieved from the pool; they can't close the underlying connections; they can't use connections they've already returned... etc.
"Guaranteed" returning of resources - thanks to our finalize implementation, even if all references to a borrowed Connection is lost, it is still returned to the pool (or does at least stand a chance to be returned). The connection will of course be held longer than necessary this way - possibly indefinitely, since finalization isn't guaranteed to ever run - but it's a small improvement.
I'd just tell them I'd use the JdbcConnectionPool class (here) that comes with H2 (you can probably copy it out). Screw trying to implement one :) It could be a trick question.
ConnectionPool implemenation
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/** A Connection Pool with 5 Available Connections **/
class ConnectionPool {
private List<Connection>availableConnections =
new ArrayList<Connection>();
private List<Connection>usedConnections = new ArrayList<Connection>();
private final int MAX_CONNECTIONS = 5;
private String URL;
private String USERID;
private String PASSWORD;
/** Initialize all 5 Connections and put them in the Pool **/
public ConnectionPool(String Url, String UserId, String password)
throws SQLException {
this.URL = Url;
this.USERID = UserId;
this.PASSWORD = password;
for (int count = 0; count <MAX_CONNECTIONS; count++) {
availableConnections.add(this.createConnection());
}
}
/** Private function,
used by the Pool to create new connection internally **/
private Connection createConnection() throws SQLException {
return DriverManager
.getConnection(this.URL, this.USERID, this.PASSWORD);
}
/** Public function, used by us to get connection from Pool **/
public Connection getConnection() {
if (availableConnections.size() == 0) {
System.out.println("All connections are Used !!");
return null;
} else {
Connection con =
availableConnections.remove(
availableConnections.size() - 1);
usedConnections.add(con);
return con;
}
}
/** Public function, to return connection back to the Pool **/
public boolean releaseConnection(Connection con) {
if (null != con) {
usedConnections.remove(con);
availableConnections.add(con);
return true;
}
return false;
}
/** Utility function to check the number of Available Connections **/
public int getFreeConnectionCount() {
return availableConnections.size();
}
}
OK, so if I understand correctly, your question is basically "how can we can ensure that a thread doesn't return a connection to the pool and then carry on using it?". Provided you don't pass back the "raw" Connection object to the caller, then the answer is essentially "you can put some control in somewhere if you want".
The actual check could involve marking each connection with which Thread "owns" it at a given moment, then making sure this is always Thread.currentThread() during any call to use the connection.
It doesn't matter terribly much what object you do pass back to user of the connection to represent the connection: it could be your own wrapper implementation of Connection, or just some other wrapper object with your methods for executing queries. Whichever you use, you just need to make the abovementioned check before executing any query. Bear in mind that for security you generally shouldn't be allowing "raw" arbitrary SQL to be executed, but that all queries should be based on a well-defined PreparedStatement. So there's no particular compulsion to return an actual implementation of Connection, other than this might in some circumstances help you migrate existing code (and/or if you've decided you really do want to permit execution of arbitrary SQL).
In many circumstances, you could also not bother making this check. You're passing a caller a means to access your database, so it's a bit like trying to stop pilots from crashing planes into buildings by scanning them for explosives at airports: they all ready have a means of messing up your system whether or not you make the additional check.