Obtaining connection to database in JBoss? - java

This is my jboss/deploy/postgres-ds.xml file. The connection url, username and password is given here. How do I obtain a connection to this database in my servlet.
<local-tx-datasource>
<jndi-name>PostgresDS</jndi-name>
<connection-url>jdbc:postgresql://localhost:5432/postgres</connection-url>
<driver-class>org.postgresql.Driver</driver-class>
<user-name>postgres</user-name>
<password>qwerty</password>
<!-- sql to call when connection is created
<new-connection-sql>some arbitrary sql</new-connection-sql>
-->
<!-- sql to call on an existing pooled connection when it is obtained from pool
<check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
-->
<!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
</local-tx-datasource>
Should I obtain the connection like this in every servlet :
Connection conn =null; // Create connection object
String database = "postgres"; // Name of database
String user = "postgres"; //
String password = "qwerty";
String url = "jdbc:postgresql://localhost:5432/" + database;
ResultSet rs = null;
ResultSetMetaData rsm = null;
try{
Class.forName("org.postgresql.Driver").newInstance();
//.newInstance()
} catch(Exception e)
{
System.err.println(e);
}
try{
conn = DriverManager.getConnection(url, user, password);
}catch(SQLException se)
{
System.err.println(se);
}
If this has to be done everytime, then why give the url, username and password in the postgres-ds.xml file?

you can use DataSource to get Connection like
javax.naming.Context ic = new javax.naming.InitialContext();
javax.naming.Context ctx = (javax.naming.Context) ic.lookup("java:");
javax.sql.DataSource ds = (javax.sql.DataSource) ctx.lookup("PostgresDS");
java.sql.Connection con = ds.getConnection();

No - using a "data source" in a J2EE app (like a JBoss-based app) and opening a standard JDBC connection (as you'd do in a simple Java application) are more or less mutually exclusive.
Your app would generally do one or the other. In your case, use the data source.
Here's a great snippet that illustrates both approaches: using a JNDI datasource, and opening a JDBC connection directly:
http://www.javapractices.com/topic/TopicAction.do?Id=127
/** Uses JNDI and Datasource (preferred style). */
static Connection getJNDIConnection(){
String DATASOURCE_CONTEXT = "java:comp/env/jdbc/blah";
Connection result = null;
try {
Context initialContext = new InitialContext();
if ( initialContext == null){
log("JNDI problem. Cannot get InitialContext.");
}
DataSource datasource = (DataSource)initialContext.lookup(DATASOURCE_CONTEXT);
if (datasource != null) {
result = datasource.getConnection();
}
else {
log("Failed to lookup datasource.");
}
}
catch ( NamingException ex ) {
log("Cannot get connection: " + ex);
}
catch(SQLException ex){
log("Cannot get connection: " + ex);
}
return result;

If you are working with JBoss, it is advisable to take advantage of the included EE APIs like JPA.
Thus you would not need to retype your connection information anywhere. Just let the container inject an EntityManager into your servlet (provided you are using EE 6 with CDI) or create something like a DAO (without EE6).
You might want to take a look at this JPA example using Hibernate on JBoss.

Related

How to tell when there is a connection database issue?

I need to make a special treatment when a connection problem to the database is occurring like database server down and not an sql problem.
In the source code we can get various exceptions but which ones are belonging to the connection ones ?
We would like if this kind of problem occurs to make less logs.
EDITED
I have many methods that perform connection to the database but all get the session from the same method (initSession):
Here an example:
private Session initSession(HibernateUtil hibernateUtil) {
Session oSession = null;
try {
oSession = hibernateUtil.getSession();
} catch (Exception e) {
log.error("unable to log, Please check the details of your database");
}
return oSession;
}
public List findAlerts(int pFirstLine, int pNbElement) throws AnalyzerException {
List oAlerts = new ArrayList();
Session oSession = initSession(lHibernateUtil);
try {
oAlerts = AlertFinders.instance().findAlertByStatus(oSession, false, pFirstLine, pNbElement);
Iterator iterAlerts = oAlerts.iterator();
while (iterAlerts.hasNext()) {
...
}
} catch (UnableToLocateObjectException eU) {
throw new AnalyzerException(eU.getMessageSource(), eU.getClassNameSource(), eU.getMethodSource(), eU);
} finally {
oSession.close();
}
return oAlerts;
}
Multiple possible ways.
Use Java Connection isValid method.
Use connection pool - All major connection
pools support this functionality (including c3p0 and dbcp).They can
throw SQLException has getErrorCode() and getSQLState() methods
Write Java code & poll frequently - sample code below
Run arguments sample: jdbc:oracle:thin:#localhost:1521:XE system mypassword123 oracle.jdbc.driver.OracleDriver
public class DbConnCheck {
public static void main(String[] args) throws Exception {
String url = args[0];
String username = args[1];
String password = args[2];
String driver = args[3];
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, username, password);
try {
Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery("SELECT SYSDATE FROM DUAL");
while(rs.next()) {
System.out.println(rs.getObject(1));
}
} finally {
conn.close();
}
}
}
Edit : Adding details on hibernate part
Not done in Hibernate but to be precise you can check in connection pool configuration.
If using c3p0 then check how you can best use setting like idle_test_period, preferredTestQuery and testConnectionOnCheckout;
If using dbcp then validationQuery can do the job.
If you want to use c3p0 with Hibernate and Spring check this link

Proper way of obtaining the DBConnection for a Web Application

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

Tomcat connection pool & idle connections

We are developing a website using
Tomcat 7
JDBC
PostgreSQL 9.2
We've had some connection leaks and think we corrected them (the database no longer stops responding), but the behaviour of the connection pool still seems leaky, as we have a number of idle connections greater than the maxIdle set in context.xml. I'd like to be sure the problem is fixed.
For testing purposes, I'm using the following context.xml :
<Resource
auth="Container"
name="jdbc/postgres"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
type="javax.sql.DataSource"
username="admin"
password="..."
driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://127.0.0.1:5432/..."
initialSize="1"
maxActive="50"
minIdle="0"
maxIdle="3"
maxWait="-1"
minEvictableIdleTimeMillis="1000"
timeBetweenEvictionRunsMillis="1000"
/>
If I understand correctly, we should have 1 idle connection on startup and from 0 to 3 depending on the load, right ?
What is happening is : 1 connection on startup, up to 3 idle connections if the load is low, and more than 3 idle connections after a high load. Then these connections are not closed immediatly, and we don't know when/if they will be closed (sometime some of them are closed).
So the question is : is this behaviour normal, or not ?
Thanks for your help
EDIT : added factory attribute, didn't change the problem
EDIT 2 : using removeAbandoned & removeAbandonedTimeout make the idle connexions being closed every removeAbandonedTimeout. So we probably still have some connection leaks. Here are some pieces of code we are using to connect to the database and execute requests :
PostgreSQLConnectionProvider, just a static class to provide a connection :
public class PostgreSQLConnectionProvider {
public static Connection getConnection() throws NamingException, SQLException {
String dsString = "java:/comp/env/jdbc/postgres";
Context context = new InitialContext();
DataSource ds = (DataSource) context.lookup(dsString);
Connection connection = ds.getConnection();
return connection;
}
}
DAO abstract class :
public abstract class DAO implements java.lang.AutoCloseable {
// Private attributes :
private Connection _connection;
// Constructors :
public DAO() {
try { _connection = PostgreSQLConnectionProvider.getConnection(); }
catch (NamingException | SQLException ex) {
Logger.getLogger(DAO.class.getName()).log(Level.SEVERE, null, ex);
}
}
// Getters :
public Connection getConnection() { return _connection; }
// Closeable :
#Override
public void close() throws SQLException {
if(!_connection.getAutoCommit()) {
_connection.rollback();
_connection.setAutoCommit(true);
}
_connection.close();
}
}
UserDAO, a small DAO subclass (we have several DAO sublasses to request the database) :
public class UserDAO extends DAO {
public User getUserWithId(int id) throws SQLException {
PreparedStatement ps = null;
ResultSet rs = null;
User user = null;
try {
String sql = "select * from \"USER\" where id_user = ?;";
ps = getConnection().prepareStatement(sql);
ps.setInt(1, id);
rs = ps.executeQuery();
rs.next();
String login = rs.getString("login");
String password = rs.getString("password");
String firstName = rs.getString("first_name");
String lastName = rs.getString("last_name");
String email = rs.getString("email");
user = new User(id, login, password, firstName, lastName, email);
}
finally {
if(rs != null) rs.close();
if(ps != null) ps.close();
}
return user;
}
}
An example of a DAO subclass use :
try(UserDAO dao = new UserDAO()) {
try {
User user = dao.getUserWithId(52);
}
catch (SQLException ex) {
// Handle exeption during getUserWithId
}
}
catch (SQLException ex) {
// Handle exeption during dao.close()
}
Looking at the code it appears the connection is grabbed for the lifetime of the DAO, not the lifetime of the statement, which is the usual expectation. Normally, you would grab a connection from the pool just as you're about to execute the statement, and call close() on it when you're done in order to return it to the pool.
Additionally, in your finally clause, both rs.close() and ps.close() can throw exceptions resulting in missing the last call against the prepared statement.
In Java 7 you can also use a try with resources statement that will close both the prepared statement and the connection for you. According to the spec, the driver is supposed to close the result for you when the statement is closed.

Database connection stops after period of time for no apparent reason

I deployed my first Java web application a couple of days ago and realized a strange thing was happening. After a period of time all the dynamic content and functionality that relied on a connection to my database (testimonial submission, admin login) stopped working. It seems like this is happening every 24 hours or so. Every morning I realize it isn't working again.
I solve the issue by going in to the Tomcat web application manager and clicking "reload" on the web app in question. Immediately the dynamic features of the website work again.
My server is running Tomcat 7 and MySQL and the web app uses the JDBC driver to establish the connection to the database. I've made no alterations to Apache or Tomcat settings.
I have other web apps written in PHP that work persistently without fault it just seems to be this Java web app that has this problem.
What would cause this to happen and how can I make it so the web app doesn't need to be reloaded before it can establish a database connection again?
EDIT: attached some code for database connection
Database connection
public class DBConnection {
private static Connection conn;
private static final Configuration conf = new Configuration();
private static final String dbDriver = conf.getDbDriver();
private static final String dbHostName = conf.getDbHostname();
private static final String dbDatabaseName = conf.getDbDatabaseName();
private static final String dbUsername = conf.getDbUsername();
private static final String dbPassword = conf.getDbPassword();
public Connection getConnection(){
try{
Class.forName(dbDriver);
Connection conn = (Connection) DriverManager.getConnection(dbHostName + dbDatabaseName, dbUsername, dbPassword);
return conn;
} catch(Exception e){
e.printStackTrace();
}
return conn;
}
public void disconnect(){
try{
conn.close();
} catch (Exception e){}
}
}
Controller for login form:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String form = request.getParameter("form");
// check login details
if(form.equals("loginForm")){
String username = request.getParameter("username").trim();
String password = request.getParameter("password").trim();
password = loginService.hashPassword(password);
boolean isValidUser = loginService.checkUser(username, password);
if(isValidUser){
Cookie loggedIn = new Cookie("loggedIn", "true");
loggedIn.setMaxAge(60*60*24);
response.addCookie(loggedIn);
out.print("success");
}else{
out.print("nope");
}
}
}
Login service checks login details are correct:
public boolean checkUser(String username, String password){
boolean isValid = false;
try{
sql = "SELECT username, password FROM morleys_user WHERE username=? AND password=? AND isActive=1 LIMIT 1";
prep = conn.prepareStatement(sql);
prep.setString(1, username);
prep.setString(2, password);
rs = prep.executeQuery();
if(rs.next()){
return true;
}
}catch(Exception e){
e.printStackTrace();
}finally{
connection.disconnect();
}
return isValid;
}
UPDATE
If I understand correctly I should not be handling a direct connection to a database and instead be using a service that will manage connections for me.
This is my example of establishing a DataSource connection to a MysQL database.
Establish a new DataSource instance of this class:
package uk.co.morleys;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import javax.sql.DataSource;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
public class DataSourceFactory {
public static DataSource getMySQLDataSource() {
Properties props = new Properties();
FileInputStream fis = null;
MysqlDataSource mysqlDS = null;
try {
fis = new FileInputStream("db.properties");
props.load(fis);
mysqlDS = new MysqlDataSource();
mysqlDS.setURL(props.getProperty("MYSQL_DB_URL"));
mysqlDS.setUser(props.getProperty("MYSQL_DB_USERNAME"));
mysqlDS.setPassword(props.getProperty("MYSQL_DB_PASSWORD"));
} catch (IOException e) {
e.printStackTrace();
}
return mysqlDS;
}
}
Instantiating a new DataSource for checking user login details
public boolean checkUser(String username, String password){
boolean isValid = false;
DataSource ds = DataSourceFactory.getMySQLDataSource();
Connection con = null;
ResultSet rs = null;
PreparedStatement ps = null;
try{
con = ds.getConnection();
sql = "SELECT username, password FROM morleys_user WHERE username=? AND password=? AND isActive=1 LIMIT ";
ps = con.prepareStatement(sql);
ps.setString(1, username);
ps.setString(2, password);
rs = ps.executeQuery();
if(rs.next()){
return true;
}
}catch(SQLException e){
e.printStackTrace();
}finally{
try {
if(rs != null) rs.close();
if(ps != null) ps.close();
if(con != null) con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return isValid;
}
Given that you've never heard of a connection pool before I'm assuming that you not are not very effectively managing database resources.
The most basic way to access the database is to obtain a connection, execute some statements & close the connection.
In the code you provided I don't see you obtaining or closing a connection, so I assume that you create a single connection when you start your application and keep the connection open "forever". After a certain amount of time your MySql server decides to kill the connection as it's been open for too long.
When you create and close a connection each time you need one, you normally won't encounter any connection timeouts, but you might experience a lot overhead from creating a connection each time your application needs one.
This is where a connection pool comes in; a connection pool manages a number of database connections and your application borrows one each time it needs one. By properly configuring your connection pool the pool will normally transparently take care of broken connections (you might for example configure the pool to renew a connection once it's x minutes/hours old).
You also need to pay attention to resource management; e.g. close a statement as soon as you no longer need it.
The following code demonstrates how your "check user" method can be improved:
public boolean checkUser(String username, String password) throws SQLException {
//acquire a java.sql.DataSource; the DataSource is typically a connection pool that's set-up in the application of obtained via jndi
DataSource dataSource = acquireDataSource();
//java 7 try-with-resources statement is used to make sure that resources are properly closed
//obtain a connection from the pool. Upon closing the connection we return it to the pool
try (Connection connection = dataSource.getConnection()) {
//release resources associated with the PreparedStatement as soon as we no longer need it.
try(PreparedStatement ps = connection.prepareStatement("SELECT username, password FROM morleys_user WHERE username=? AND password=? AND isActive=1 LIMIT 1");){
ps.setString(1, username);
ps.setString(2, password);
ResultSet resultSet = ps.executeQuery();
return resultSet.next();
}
}
}
Common connections pools are Apache Commons-DBCP and C3P0.
As managing sql resources can be quite repetitive and cumbersome you might want to consider using a template: for example Spring's JdbcTemplate
Example C3p0 configuration:
public ComboPooledDataSource dataSource(String driver, String url, String username,String password) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(driver);
dataSource.setJdbcUrl(url);
dataSource.setUser(username);
dataSource.setPassword(password);
dataSource.setAcquireIncrement(1);
dataSource.setMaxPoolSize(100);
dataSource.setMinPoolSize(1);
dataSource.setInitialPoolSize(1);
dataSource.setMaxIdleTime(300);
dataSource.setMaxConnectionAge(36000);
dataSource.setAcquireRetryAttempts(5);
dataSource.setAcquireRetryDelay(2000);
dataSource.setBreakAfterAcquireFailure(false);
dataSource.setCheckoutTimeout(30000);
dataSource.setPreferredTestQuery("SELECT 1");
dataSource.setIdleConnectionTestPeriod(60);
return dataSource;
}//in order to do a "clean" shutdown you should call datasource.close() when shutting down your web app.
MySQL times out the connection after some period of time. The standard way to deal with this is to use a properly configured connection pool (with a configured DataSource) instead of using DriverManager directly.
The connection pool will check for and discard "stale" connections.

Create a class to connect to any database using jdbc

I am trying to design a Java swing application. I want to experiment and use an MVC type of architecture whereby my UI is separated from the actual logic to access data and connect to a database. I have decided that I need to create a custom class that contains all the logic to connect to the database and then simply call methods from this class in my action event for any particular form and button. This way I can switch databases and all I need to do (if I have a large code base with many many forms) is change the JDBC connection string to connect to oracle instead of MySQL. So far I have the code to connect to a database but I am trying to figure out how I can make this a class.
try
{
Class.forName("com.mysql.jdbc.Driver");
Connection con=(Connection)DriverManager.getConnection("jdbc:mysql://localhost:3306/prototypeeop","root","triala");
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery(sql);
I will then return the result set from a member function of my connection class to process and display on the screen.
Just create a separate class and delegate to him a getting of connection to database:
public class ConnectionManager {
private static String url = "jdbc:mysql://localhost:3306/prototypeeop";
private static String driverName = "com.mysql.jdbc.Driver";
private static String username = "root";
private static String password = "triala";
private static Connection con;
private static String urlstring;
public static Connection getConnection() {
try {
Class.forName(driverName);
try {
con = DriverManager.getConnection(urlstring, username, password);
} catch (SQLException ex) {
// log an exception. fro example:
System.out.println("Failed to create the database connection.");
}
} catch (ClassNotFoundException ex) {
// log an exception. for example:
System.out.println("Driver not found.");
}
return con;
}
}
Then get the connection in a code as follows:
private Connection con = null;
private Statement stmt = null;
private ResultSet rs = null;
con = ConnectionManager.getConnection();
stmt = con.createStatement();
rs = stmt.executeQuery(sql);
You can try MySQL JDBC Utilities API for MySQL connectivity.
This API offers very cool features and also fulfill your requirement!
Two ways you can make it
Override determineCurrentLookupKey() method of Spring's AbstractRoutingDataSource class.
You can create a class which will return Connection based on system.
You can either use fancier stuff like Hibernate or if your database usage is simple then you can try Commons DbUtils
Ceremonial connection code
String db = "jdbc:h2:mem:;INIT=runscript from 'classpath:/prototypeeop.sql'";
//for H2 in-memory database:
Connection DriverManager.getConnection(db);
Remember the core classes and interfaces in Commons DbUtils are QueryRunner and ResultSetHandler.

Categories

Resources