 wonder if it has to be synchronized or not. I guess you only need to synchronize access to these: m_aNumOpenConnections and m_aConnectionPoolNames.
Probably the synchronization you need is to be done outside this method: getConnection. Basically, if you're iterating over those arrays, or deleting or setting objects on them, you must synchronize there like
synchronized(m_aConnection
for(...) {
m_aConnectionPoolNames[i] = something;
}
}
You can also cache these:
Properties env = new Properties();
String propsFilePath=System.getPr
String url = System.getProperty("url");
env.put(Context.PROVIDER_U
env.put(Context.INITIAL_CO
You're reading from a file one very request to a connection. It's ok if you change it dinamically outside the application, but if you don't, you're just wasting time.
Hope it helps somehow.
Thanks a lot for your reply.
If i remove the Synchronize key from the getConnection method signature ....
1) how do we ensure thread safety on the database access methods themselves ?
Because we wouldn't want a single connection to have half of one query and half of another when it executes.
Does the underlying DataSource getConnection handles this ?
Please elt me know
Thank you do we ensure thread safety on the database access methods themselves ?
getConnection () is only getting a connection. After that if you want to synchronize calls to the method which does DB access, you need to synchronize it too.
I don't know if the getConnection method itself is thread safe, but if it isn't, you can use a global class variable and use it as a lock. Say:
private Object getConnLock = new Object();
...
...
synchronized(getConnLock) {
getConnection();
}
Now to invoke DB queries on the connection, you must do your own pool management. Seems you have an array where you push / pop connection. Just be carefull on getting them from your arrays. You can have a Stack object for that, and synchronize access to it. Once a client gets one connection, it's removed from the stack (no one will use it), and when the client is done, just push it again on the stack.
You're not using Enterprise Java Beans because you have decided not to use them right ? Because the app server already does all this for you with beans (cache pooling). You just have to invoke EJB instances and call methods on them. No worries.
Thank you
then your other method getConnection will retrieve connections to a Stack object. Pushing and poping on this stack should be synchronized (you can synchronized on calls to the stack object itself: say:
synchronized(stack) {
stack.push(connection);
or
stack.pop(connection);
}
You are suggesting me to use the lock on the DataSource.getConnection()
But my guess is that even it will give the same problem at peak loads (time delays) . Because all the methods that are waiting for connection (methods that called getConnection( )) will wait at this Synchronized block until the App server ready with the new pool connections. This wil give the same performance issue.
we don't want the app to hang up at this point.
Is this a standalone Java application ?
If it is, you can do it differently. Your getConnection method must be run on a new thread (decoupling from the AWT thread). You must create some kind of manager where every party interested in a conncetion registers. When the connection is available, you notify the registered parties with an event listening mechanism.
Anyway, you can also implement some kind of threshold (suppose, when you reach connection 15 out of 20) you start getting pools at this point, even if they may not be used. But then with this look-ahead mechanism you guarantee that there will be connections available. But the you'll need to dispose some of the connections when the peak comes down... maybe with some kind of timer.
Everything looks fine in the Normal load situations. But getting timedelays in Peak load period.
With the mechanism you described above.. the appserver will never create the New pool of connections (when you reach connection 15 out of 20) if there are 5 more free connections. Is there any mechanism to do that ?
Why do you have to write your own connection pool then? Most (if not all) J2EE application servers provide sophisticated connection pooling. I think you are better off letting the application server do the pooling job for you, that's why application servers exist at first place :)
If there's a mechanism to do that kind of threshold thing, it will be implemented by the application server, so it may depend on which one you're using. I don't know if it's possible to do that.
The event mechanism will stop the main threads from blocking on your getConnection method. However the server delay to get a connection for you will still be there. So, it it's a web app, it will take longer for you to get a reply. But if it's a standalone app, your application will not hang graphically.
Let me explain you clearly ..
We have initial maxpoolCapacity of 20 connections.
In my application we have Synchronized getConnection method (look at this in my first comment) which is calling DataSource.getConnection method to get the connection from Pool.
Now, at the peak load situations all 20 connections are busy and say thread 10 is calling Synchronized getConnection method to request for the new pooled connections. Obviously it is going to take sometime to create the 20 more physical connections and to update the pool with new connection. While above thread on process of making the connection pool, i could see lot of other threads stuck at Synchronized getConnection method which calls the DataSource.getConnection method with makes the lock here. Because of this we are seeing timedelays and effecting the performance of the application.
My consern is Can i make the getConnection method non -synchronize ? if so,
1) how do we ensure thread safety on the database access methods themselves ?
Because we wouldn't want a single connection to have half of one query and half of another when it executes.
Does the underlying DataSource getConnection handles this ?
With mindMkr suggestion i understood that we can make lock at DataSource.getConnection. But i guess we will experience the same delays by doing so.
is there anything that i can do to avoid time delays ?
Well it depends, from what I can see in your code you do not have access to a class variable so it might be safe not to synchronize the method to get the connection from the database, but it heavily depends on the driver implementation. Most of the database drivers are thread safe, datasources also, so you might not need synchronization at all. I suggest you take a look at your application server's document to see if the jdbc drivers it uses and your datasources are thread safe. if they are you do not need to synchronize your method if you do not have any class variables that you use in that method.
The other solution is simply to increase the connection pool so as to have more conenctions available on peak time.
The underlying Datasource getConnection only get you a connection (and I don't know if this is thread safe). After you have the connection, if 2 threads use the SAME connection to prepare a statement and get resultsets, I don't know what could happen here. Best to stick to 1 connection per thread.
The only way I see now to get connections non-blocking is to get them asynchronously. Create a new Thread to get the datasource connection. Use a runnable that takes as constructor the caller instance. You need a new interface to signal the caller that the thread has been fetched.
Let me check with some of my team mates..
Get back to you shortly
Appriciate your prompt reply
Thank you
We are using OracleJDBC Drive. Is that thread safe when accessing the Database ?
Thanks for your reply. I will try to test this.
Thanks
Thank you
Plz Let me know so that i will proceed further...
Thank you
Can i chache the Data Source and get the Connection from the Cached DataSource ?
If yes, How can i request the App Server to increase the Pool size in the Peak load situatons if all the Connections in the Cached DataSource are busy ? (Please provide me sample code )
Please elt me know
> If yes, How can i request the App Server to increase the Pool size in the Peak load situatons if all the Connections in the Cached DataSource are busy ? (Please
>provide me sample code )
You do not have to dfo it programmatically. You will need to do it in application server level. You could probably do it from the console (if there is any) or from the config file. For more info you better take a look at the application server's documentation.
For the firest request to the connection i am calling
DataSource . getInstance( ) .getConnection( );
Where my DataSource class is like this ...
public class DataSource {
private static DataSource instance = null;
private Map dataSources = new HashMap();
private DataSource(){
Context ctx = null;
//Get the Properties from the Properties file
Properties env = new Properties();
String propsFilePath = System.getProperty("propfi
String url = System.getProperty("url");
env.put(Context.PROVIDER_U
env.put(Context.INITIAL_CO
try
{
ctx = (Context) new InitialContext(env);
//Get the DataSource from JNDI initial context
DataSource DataSource = (DataSource) ctx.lookup("jdbc/datasourc
//Cache the Data Source object.
dataSources.put("DataSourc
}
catch (Exception e)
{
Log.write(" Failed Initializing the DataSource ---> ");
}
}
/* This method ensures that all the classes running on same JVM uses the single instance of DataSource.
* If the instance not exists, this method creates new instance of DataSource class.
*/
public static synchronized DataSource getInstance(){
if (instance == null){
instance = new DataSource();
}
return instance;
}
public Connection getConnection() throws SQLException {
return this.getConnection("DataSo
}
/* This method returns a Connection from the cached datasource to the calling method.
*
*/
public Connection getConnection(String dataSourceKey) throws SQLException {
DataSource ds = (DataSource)dataSources.ge
Connection connection = ds.getConnection();
return connection;
}
}
For the first request to get the connection from the DataSource, the logic in the constructor of the DataSource class will get the data source from the Server and Cache that. So i have no problem until 30 connections in the pool are used up.
At the request for the 31 st connection what logic should i implement to request for additional connections from the server ?
Thank you
Now my question is what happen if i need more than 30 connections ?
Thank you for your prompt reply
I dont want that to happen.. that is root cause of our app hanging up at the peak load.
Do you have any other idea ?
Go to the WebLogic console and set a number in the "Capacity Increment" field of your connection pool (click on the connection pool you want and then on the "Connection" tab). The number you will set there is the number of the connections WebLogic will create if the pool is empty and a new request for a connection comes in. This number should not be bigger then the maximum capacity number.
The second thing you can do is to set an initial capacity of more connections.
The problem is with the code above (DataSource class) . DataSource Object is created for the first Connection. That object is not null until all the connections are busy ( 30 connection) and even at the time of requesting more connections (more than 30). So there is no way to get the updated pool from the Weblogic server. Because in the constructor of the class i am looking in the JNDI. As the object is not null there is no way that the constructor of DataSource class is called. In this case my request for the more connections is not going upto Weblogic server.
What code i need to do to achieve this.
I am on the way to test that is Dev environment. Thank for your patience and help..
Get back to you as soon as i am done with the testing