I am using spring jdbc. How can I get the current Connection object for an Oracle database? I'm using connection pooling with JBOSS Wildfly server. I am getting the connection url in my DaoImp by using this code:
Connection con;
try {
con = getJdbcTemplate().getDataSource().getConnection();
dataSource.getConnection().getMetaData().getURL();
connectionUrl = con.getMetaData().getURL();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
If I write the same code in the setJdbcTemplate method then I am not getting connections over there.There error as follows
No managed connections available within configured blocking timeout (0
[ms])
my setJdbcTemplate method as follwos
public void setDataSource(DataSource dataSource){
this.dataSource = dataSource;
setJdbcTemplate(new JdbcTemplate(this.dataSource));
setNamedParamdbcTemplate(new NamedParameterJdbcTemplate(this.dataSource));
if(connectionUrl==null){
Connection con;
try {
con = getJdbcTemplate().getDataSource().getConnection();
connectionUrl = con.getMetaData().getURL();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Try increase blocking timeout in ds.xml file. see configure data source in JBOSS
blocking-timeout-millis : This element specifies the maximum time in
milliseconds to block while waiting for a connection before throwing
an exception. Note that this blocks only while waiting for a permit
for a connection, and will never throw an exception if creating a new
connection takes an inordinately long time. The default is 5000.
Default values
- the length of time to wait for a
connection to become available when all the connections are checked
out (default 5000 == 5 seconds, from 3.2.4 it is 30000 == 30 seconds)
<blocking-timeout-millis>5000</blocking-timeout-millis>
You can specify the max and min connection pool size in the -ds.xml file.
<!--pooling parameters-->
<min-pool-size>5</min-pool-size>
<max-pool-size>100</max-pool-size>
<blocking-timeout-millis>5000</blocking-timeout-millis>
Related
I have a java application running on WebSphere 8.5.5.12 server. I connect to other applications via MQ. I have faced a performance issue with the application and found that whenever the MQ reply is getting timeout, the Queue connection was not closed properly. I have fixed the issue. I am planning to increase the Maximum connection for the particular Queue Connection factory and i want to get the number of connection used/opened in the Queue Connection Factory via code, so that i can increase the maximum connections accordingly based on the traffic/volume. Any leads would be much helpful.
To learn the number of connections used and the number of queues opened by an application, you can use the MQSC DISPLAY CONN command like this:-
DISPLAY CONN(*) TYPE(ALL) ALL WHERE(OBJNAME EQ reply-q-name)
This will show you all the connections and all the open handles.
You can also discover exactly the same data using a programatic interface called PCF commands, although given how many excellent MQ admin tools there are out there, I'm not sure why you would need to do this "via code" as you put it?
For your second part of your question, how do you change the maximum connections based on load.
I have a some sample code using a datasource that may help to answer you question. Where I using name=built-in-derby-datasource, you can change the name to your Queue Connection factory name. If you need the lookup, change this jndi name jdbc/built-in-derby-datasource to your Queue Connection factory jndi name.
The code will get the admin client giving you access to queryMBeans. After you have the mbean, you can change maximum connections dynamically while the server is running.
#SuppressWarnings("unchecked")
public void AdminClientExample()
{
Object adminClient = null;
// Need to set the properties, type, host and port, defaults likely will work for most
Properties acProps = new Properties();
acProps.setProperty(AdminClient.CONNECTOR_TYPE, AdminClient.CONNECTOR_TYPE_SOAP);
acProps.setProperty(AdminClient.CONNECTOR_HOST, "localhost");
acProps.setProperty(AdminClient.CONNECTOR_PORT, "8880");
// Set if security is enabled
//acProps.setProperty(AdminClient.CONNECTOR_SECURITY_ENABLED, "true");
//acProps.setProperty(AdminClient.USERNAME, "userid");
//acProps.setProperty(AdminClient.PASSWORD, "userid password");
try
{
adminClient = AdminClientFactory.createAdminClient(acProps);
}
catch (Exception e)
{
e.printStackTrace();
}
ObjectInstance obi = null;
ObjectName obn = null;
Set<ObjectInstance> s = null;
try {
// The two types to use are J2CConnectionFactory and DataSource if searching through a list of mbeans of that type.
// type=J2CConnectionFactory
// type=DataSource
// obn = new ObjectName("WebSphere:type=DataSource,*");
// s1 =((AdminClient)adminClient).queryMBeans(obn, null); // search through s1
// You can provide the name like this,
obn = new ObjectName("WebSphere:name=built-in-derby-datasource,*");
s =((AdminClient)adminClient).queryMBeans(obn, null);
// s should contain WebSphere:name=built-in-derby-datasource,process=server1,platform=dynamicproxy,node=DefaultNode01,JDBCProvider=Derby JDBC Provider (XA),diagnosticProvider=true,j2eeType=JDBCDataSource,J2EEServer=server1,Server=server1,version=9.0.0.11,type=DataSource,mbeanIdentifier=cells/DefaultCell01/resources.xml#DataSource_9007001,JDBCResource=Derby JDBC Provider (XA),cell=DefaultCell01,spec=1.0
} catch (Exception e) {
e.printStackTrace();
}
if (s == null) {
System.out.println("Did not find MBeans querying for object name " + obn.toString());
return;
} else {
obi = s.iterator().next();
}
// Normally the application using the connection pool will have
// already done the lookup which creates the objects
// required to change maxConnections. This lookup is only for
// this example.
InitialContext ctx;
try {
ctx = new InitialContext();
ctx.lookup("jdbc/built-in-derby-datasource");
} catch (Exception e) {
e.printStackTrace();
}
// show the connection pool contents
Object [] parms = null;
String [] parmsTypes = null;
try {
String ss = (String) ((AdminClient)adminClient).invoke(obi.getObjectName(), "showPoolContents", parms, parmsTypes);
System.out.println(ss);
} catch (Exception e) {
e.printStackTrace();
}
// get maxConnections
try {
Object maxConnections = ((AdminClient)adminClient).getAttribute(obi.getObjectName(), "maxConnections");
System.out.println(maxConnections);
} catch (Exception e) {
e.printStackTrace();
}
// change the maxConnections to 11,
try {
Integer it = new Integer(11);
Attribute at = new Attribute("maxConnections", it);
((AdminClient)adminClient).setAttribute(obi.getObjectName(), at );
} catch (Exception e) {
e.printStackTrace();
}
// show the connection pool contents, maxConnection now should be 11.
// or you can use the get maxConnection to check
// the changed value.
try {
String ss = (String) ((AdminClient)adminClient).invoke(obi.getObjectName(), "showPoolContents", parms, parmsTypes);
System.out.println(ss);
// or
Object maxConnections = ((AdminClient)adminClient).getAttribute(obi.getObjectName(), "maxConnections");
System.out.println(maxConnections);
} catch (Exception e) {
e.printStackTrace();
}
}
I'm trying to run the following code but It always results in a "http 500 Internal Server Error"
Could someone help me debug this error
I just started learning Servlets and JSP..So please excuse me if I miss any details in the question. Looking in the MYSQL database error logs, I found the following entries:
Aborted connection 44 to db: 'sakila' user: 'root' host: 'localhost' (Got an error reading communication packets)
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.setContentType("text/html");
PrintWriter out=response.getWriter();
final String DB_URL="jdbc:mysql://localhost:3306/sakila";
final String user="root";
final String password="pass1234";
Statement stmt=null;
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
out.println("Cannot load driver");
}
Connection conn=null;
try {
conn=DriverManager.getConnection(DB_URL,user,password);
} catch (SQLException e) {
// TODO Auto-generated catch block
out.println("Cannot Connect to Database");
}
//out.print("Connected to Database");
out.println("<html>");
out.println("<body>");
String str= "SELECT actor_id, first_name last_name FROM temp where actor_id='1';";
try {
ResultSet rs=stmt.executeQuery(str);
while(rs.next()){
out.println(rs.getString("actor_id"));
}
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
/*
try {
ResultSet rs;
rs = stmt.executeQuery(str);
while(rs.next()){
int i=rs.getInt("actor_id");
String fn= rs.getString("first_name");
String ln=rs.getString("last_name");
out.print(i+"::");
out.print(fn+"::");
out.print(ln+"::");
}
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
*/
out.print("hkshfdkhfakfshdkha");
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.println("</body>");
out.println("</html>");
}
Aborted connection 44 to db: 'sakila' user: 'root' host: 'localhost'
(Got an error reading communication packets)
This error trace is appearing in your console because you are trying to making new db connection to the mysql database on every doGet() request without properly closing your db connection.
And thats why whenever a communication error occurs it increments the status counter for either Aborted_clients or Aborted_connects, which describe the number of connections that were aborted because the client died without closing the connection properly and the number of failed attempts to connect to MySQL server (respectively).
Out of the various reasons causing this issue, here are few important ones that you might want to check.
The client connected successfully but terminated improperly (and may
relate to not closing the connection properly)
The client slept for longer than the defined wait_timeout or
interactive_timeout seconds (which ends up causing the connection to
sleep for wait_timeout seconds and then the connection gets forcibly
closed by the MySQL server)
The client terminated abnormally or exceeded the max_allowed_packet
for queries
So as right mentioned by #Matt Clark you should be going for a connection pool mechanism to avoid this issue and also to follow best pratices around interfacing with databases.
If you check your application logs, it is my assumption that you will see the stacktrace generated by
e1.printStackTrace();
This is because you have an error in you SQL syntax.
SELECT actor_id, first_name last_name FROM temp where actor_id='1';
/\ add missing comma
On a side note - you should not be establishing the connection to the databse inside each request. This slows everything down.
Instead, you should be using a connection pool, I recommend C3P0.
The reason for abrupt termination in your database logs, is because your application throws an exception and abandons the connection without properly closing it.
We have a Web Application which will serve more than 1000 concurrent users
Currently , the Utility class for obtaining the DB Connnection is
public static Connection getDBConnection()
{
Connection conn = null;
try
{
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:/comp/env/jdbc/MyLocalDB");
try
{
conn = ds.getConnection();
}
catch ( SQLException sqlEx )
{
System.out.println( "cannot get JDBC connection: " + sqlEx );
}
}
catch ( NamingException nEx )
{
nEx.printStackTrace();
}
return conn;
}
Option 2 :
public class DBConnection2 {
private static DataSource dataSource;
static {
try {
dataSource = (DataSource) new InitialContext().lookup("java:/comp/env/jdbc/MyLocalDB");
} catch (NamingException e) {
try {
throw new Exception("'jndifordbconc' not found in JNDI",e);
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
}
Please let me know whats the better option (I guess its second operation as lookup is a costly operation and i am doing it only for once in a application .)
please share your views .
You should adopt the second approach. As you say you don't need to keep looking up the datasource in JNDI.
I am assuming that you are using a pooled data source as provided by the tomcat-jdbc project, otherwise performance will be terrible.
On the second approach you should be sure to use connection pooling. Otherwise users will have to wait for others.
For example To Tomcat brings it own connection pool.
Or if you don't use Tomcat maybe you could have a look at C3p0: JDBC DataSources/Resource Pools.
see: Instantiating and Configuring a ComboPooledDataSource
The second option initialize dataSource only once when the class is loaded, then it is shared around all DBConnection2 instances. The first option initialize a new DataSource instance every time you call getDBConnection(). Thus the second option has better performance. But please be pay attention to connection release issue. Make sure close the connection if you choose the first option. I prefer use a framework to handle DB connection, like Spring JDBC: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jdbc.html
I have a website i am running using tomcat 7 and MYSQL. It runs on a dedicated server. I am using the simple connection pool and simple DAO's
classes outlined below:
I have also attached the screen shot of all the localhost connections on the server. I run another application on a different server using similar DAO's and the same connection pool and i only ever see 4 connections on that server.
Why would there be so many connections and is there a way to trace it back to my application to see why so many are spawning or is this normal?
public class ConnectionPool {
private static ConnectionPool pool = null;
private static DataSource dataSource = null;
public synchronized static ConnectionPool getInstance()
{
if (pool == null)
{
pool = new ConnectionPool();
}
return pool;
}
private ConnectionPool()
{
try
{
InitialContext ic = new InitialContext();
dataSource = (DataSource) ic.lookup("java:comp/env/jdbc/DBNAME");
}
catch(Exception e)
{
e.printStackTrace();
}
}
public Connection getConnection()
{
try
{
return dataSource.getConnection();
}
catch (SQLException sqle)
{
sqle.printStackTrace();
return null;
}
}
public void freeConnection(Connection c)
{
try
{
c.close();
}
catch (SQLException sqle)
{
sqle.printStackTrace();
}
catch (NullPointerException npe){
npe.printStackTrace();
}
}
}
DAO
public static DefaultMetaInfo loadDefaultMetaData() {
ConnectionPool pool = ConnectionPool.getInstance();
Connection connection = pool.getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
String query = "SELECT META_TAG, TITLE_TAG FROM SITE_SETTINGS";
try {
ps = connection.prepareStatement(query);
rs = ps.executeQuery();
if (rs.next()){
DefaultMetaInfo settings = new DefaultMetaInfo();
settings.setMetaTag(rs.getString("META_TAG"));
settings.setTitleTag(rs.getString("TITLE_TAG"));
return settings;
}
} catch(SQLException e) {
e.printStackTrace();
return null;
} finally {
DaoUtil.closeResultSet(rs);
DaoUtil.closePreparedStatement(ps);
pool.freeConnection(connection);
}
return new DefaultMetaInfo();
}
context
<?xml version='1.0' encoding='utf-8'?>
<Context>
<Resource name="jdbc/DBNAME"
auth="Container"
type="javax.sql.DataSource"
maxActive="1200"
maxIdle="30"
maxWait="10000"
testOnBorrow="true"
validationQuery="select 1"
removeAbandoned="true"
removeAbandonedTimeout="60"
logAbandoned="true"
username="user"
password="pw"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://127.0.0.1:3306/dbname?autoReconnect=true"/>
</Context>
If you notice that almost all of your connections from the pool are into SLEEP state.
In the finally block of your loadDefaultMetaData() method you have used below statement to free up the connection for you and return it to the configured connection pool.
pool.freeConnection(connection);
This statement releases your "reservation" on that connection and returns it to the pool. It will not necessarily close the underlying, actual database connection. Interesting part is that freeConnection(connection) do nothing to prevent you from using the connection object again after freeing it (if you still had a reference to it).
And since it could be remaining open (usually will be), unclosed PreparedStatement or ResultSet could be interpreted by the pool layer as an indication of being still busy.
You will be able to inspect or debug the Connection object to identify its state at run-time, to confirm this.
The actual resolution for this probelm is to RTM and configure the connection pool & strategy correctly, as described in below reference URLs.
Resource Definitions in Apache Tomcat Configuration Reference
Java+Tomcat, Dying database connection.
Shishir
Your configuration states maxIdle=30 and it seems like you have less than 30 idling (sleeping) connections. To me this looks like an expected behaviour.
Shishir Kumar already stated that connections don't necessarily get closed when returned to the pool. The reason is that creating connections is actually an expensive operation, thus you typically want to keep them open and reuse them - the validationQuery, that you also configure, is used to check if the connection is still operative.
IMHO What you see is expected behavior when working with a connection pool. Also, please check if you really need (and can handle) 1200 maxActive connections. This looks like an extremely high number. If you ever get into the area where you need that many open connections, you'll want to have more than 30 of them idling.
I am getting stale connection error when there is no requests to the database from my java application for couple of hours.
Its a simple java application runned on Linux box with OCI (type driver). Dont ask me why OCI, why not thin. I am using OracleDataSource and OracleConnectionCacheManager for maintaining the cache of connection objects. Here is the code snippet:
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import oracle.jdbc.pool.OracleConnectionCacheManager;
import oracle.jdbc.pool.OracleDataSource;
import org.apache.log4j.Logger;
import com.exception.DataException;
public class ConnectionManager {
private static OracleDataSource poolDataSource = null;
private final static String CACHE_NAME = "CONNECTION_POOL_CACHE";
private static OracleConnectionCacheManager occm = null;
public static void init(String url,String userId,String password) throws PCTDataException{
Properties cacheProps = null;
try {
poolDataSource = new OracleDataSource();
poolDataSource.setURL(url);
poolDataSource.setUser(userId);
poolDataSource.setPassword(password);
cacheProps = new Properties();
cacheProps.setProperty("MinLimit", "1");
cacheProps.setProperty("MaxLimit", "5");
cacheProps.setProperty("InitialLimit", "1");
cacheProps.setProperty("ValidateConnection", "true");
poolDataSource.setConnectionCachingEnabled(true);
occm = OracleConnectionCacheManager.getConnectionCacheManagerInstance();
occm.createCache(CACHE_NAME, poolDataSource, cacheProps);
occm.enableCache(CACHE_NAME);
} catch (SQLException se) {
throw new DataException("SQL Exception while initializing connection pool");
}catch(Exception e){
throw new DataException("Exception while initializing connection pool");
}
}
public static Connection getConnection() throws PCTDataException {
try{
if (poolDataSource == null) {
throw new SQLException("OracleDataSource is null.");
}
occm.refreshCache(CACHE_NAME, OracleConnectionCacheManager.REFRESH_INVALID_CONNECTIONS);
Connection connection = poolDataSource.getConnection();
return connection;
}catch(SQLException se){
se.printStackTrace();
throw new DataException("Exception while getting Connection object");
}catch(Exception e){
e.printStackTrace();
throw new DataException("Exception while getting Connection object");
}
}
public static void closePooledConnections() {
try{
if (poolDataSource != null) {
poolDataSource.close();
}
}catch(SQLException se){
}catch(Exception e){
}
}
}
The error is as follows:
ConnectionManager.java:getConnection:87 - Exception while getting Connection object:
java.sql.SQLException: Invalid or Stale Connection found in the Connection Cache
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:208)
at oracle.jdbc.pool.OracleImplicitConnectionCache.getConnection(OracleImplicitConnectionCache.java:390)
at oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.java:404)
at oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.java:189)
What am I missing?
Maybe you need to set keep alives on? what this does is periodically, when not in use it send a ping to the database server basically saying I am still here and don't close me out. This is not that fun to try to debug though. The problem could be a setting on your database server where there is a max connection age, or a time to kill idle connections. There also could be some settings in your pool that you could use to that would check for this and then just tell it to get a new one when this happens. I wish I could be more help but I have not worked with oracle.
Instead of using OracleDataSource + OracleConnectionCacheManager, I would recommend using the OracleOCIConnectionPool, which was specifically designed for caching OCI connections.
It is a drop in replacement for OracleDataSource, except the PoolConfig properties for OracleDataSource and the OracleOCIConnectionPool are a bit different.
You will get the "Invalid or Stale Connection" error when you have a connection in the connection pool which is no longer connected to the Database actively. Below are few scenarios which can lead to this
Connection is manually aborted from the database by a dba. For example, if
the connection was killed using "ALTER SYSTEM KILL SESSION"
When a connection exists in the connection pool without being used for a
long time and is disconnected due to the timeouts enforced by the
database (idle_time)
A database restart
A network event has caused
the connection to drop, probably because the network has become
unavailable or a firewall has dropped a connection which has been
open for too long.
Run the below query to determine the IDLE_TIME enforced by the Database
select * from dba_profiles dp, dba_users du
where dp.profile = du.profile and du.username ='YOUR_JDBC_USER_NAME';
Now try with the below configuration
Properties cacheProps = new Properties();
cacheProps.setProperty("MinLimit", "0");
cacheProps.setProperty("MaxLimit", "5");
cacheProps.setProperty("InitialLimit", "1");
cacheProps.setProperty("ValidateConnection", "true");
cacheProps.setProperty("InactivityTimeout", "17000"); //something lower than the DB IDLE_TIME
cacheProps.setProperty("PropertyCheckInterval", "16000") /*something lower than the inactivity timeout
- to make sure that connections which were inactive for more than InactivityTimeout
are always removed from the pool*/