JDBC/Connectorj: When to load drivers? - java

I was wondering what is the 'correct' way to load drivers for my Java servlet.
Currently, I have a InitializeDrivers() function that I call at the beginning of my application.
public static boolean InitializeDrivers()
{
try {
Class.forName("com.mysql.jdbc.Driver");
return true;
} catch (ClassNotFoundException ex) {
// log error
return false;
}
}
After that is done, I go on performing my various requests/inserts to the database depending on the HTTP request that was received. However, since my servlet can receive hundreds of requests per seconds, InitializeDrivers() will be called one time for each request.
Is it the correct way to do this, or is there a way to load the drivers only once?

When you're using a database in a servlet, then it is better to let the servlet container manage database connections through a connection pool instead of directly getting a database connection yourself in the servlet.
Opening a connection to a database server is a relatively slow operation. Also, the number of connections that a database can handle at the same time is limited. Your application will be slow and not very scalable when you open a database connection each time you need to access the database. Also, database connections are not thread-safe, so you cannot store a database connection in a static member variable of the servlet and use that every time.
A connection pool manages a number of open connections for you (so that you don't have to open the connection each time you need to access the database), and manages the number of connections that are open at the same time. In for example Apache Tomcat, you can configure this so that you lookup a javax.sql.DataSource object via JNDI, which you then use to get a Connection object from.
This page explains how to configure Tomcat and use a DataSource in your servlet:
JNDI Datasource HOW-TO
If you do not want to do this and you want to continue using database connections from your servlet (which I do not recommend), then you could load the driver in a static initializer block in your servlet:
public class MyServlet extends HttpServlet {
static {
Class.forName("com.mysql.jdbc.Driver");
}
// ...
}
Note that in JDBC 4.0, loading the driver explicitly is not necessary anymore; JDBC will automatically find drivers as long as they in the classpath.

Related

how to get one JDBC Connection for one user in application, if I have 50 users

I am creating a jdbc connection in web application.suppose ,50 users will use the application. currently, my application taking more than 20 connection for single user. how to improve the performance?
public class AuditConnection
{
private static String URL =
"jdbc:postgresql://localhost:5432/MDM_Audit?
user=rajan&password=rajan";
private static String driverName = "org.postgresql.Driver";
private static Connection con;
public static Connection getConnection() {
try {
Class.forName(driverName);
try {
con = DriverManager.getConnection(URL);
} catch (SQLException ex) {
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;
}
}
Session & Context
In a web app, you should not be thinking about one database connection per user. Defining “user” in a web app is a bit amorphous. A user could be using multiple browser tabs/windows, or even multiple browsers. The user could be starting and closing sessions, or sessions could be expiring, and the user reconnecting.
Instead, think in terms of:
SessionEach time a user accesses your web app in a browser tab/window, a session is launched. The Java Servlet environment is built to handle the technical details on your behalf, handing you a HttpSession object. The session is closed when the user closes the browser tab/window, or after a time-out of inactivity, or when you programmatically close it, or when the Servlet container determines a problem such as failed network connection.
Each session includes a key-value store of “attributes” where you can keep objects scoped for this session.
ContextThe word “context” is Servlet-speak for your entire web app at runtime. The context is established before the first user request is processed, and is closed after the last response is sent.
On the ServletContext object you will find a key-store of “attributes” similar to the session’s attributes store.
The Servlet spec defines hooks into the lifecycle of both the session and context.
The hook for the context lifecycle is to write a class that implements ServletContextListener. You implement a pair of methods, one called by the Servlet container before the first user connection is handled (your web app is launching), and the other called after the last response is sent out (your web app is shutting-down). Search Stack Overflow for much existing coverage of this topic.
DataSource
Rather than establishing connections as you show there, it is generally better to use a DataSource object.
The JDBC driver from jdbc.postgresql.org provides an implementation of DataSource. See this Question for details: Produce a DataSource object for Postgres JDBC, programmatically.
One benefit of using the DataSource interface is that if you ever change to using a different JDBC driver (such as the pgjdbc-ng driver for Postgres), you need not change any of your calls to getConnection littered throughout your codebase.
The context starting-up hook discussed above is an ideal place for you to load your driver, test a connection to the database, and configure a DataSource object. Store that DataSource object in the “attributes” key-value store on the ServletContext mentioned above.
When you need a connection, access the ServletContext object to retrieve the DataSource your stored there as an attribute. Call DataSource::getConnection to obtain a Connection for your database.
Be sure to close the Connection object when finished with it. Learn to use the try-with-resources feature to make this closing chore a bit more elegant and easy in your code.
Connection pooling
Many people will suggest using connection-pooling. The theory here is that obtaining a connection is relatively expensive, taking a significant amount of time and CPU cycles.
Without pooling, we get a fresh connection to the database, do a bit of limited work, and then close and discard that connection. The Connection object goes out of scope and becomes a candidate for garbage-collection. On the database side, the process that was established by the Postgres Postmaster to handle that connection is closed, and memory freed-up. When a new connection is requested, the Postmaster must go to the bother of setting up a new process and allocating memory in the host OS.
With pooling, a bunch of existing database connections are held open, waiting to be used. When your app needs database work done, a connection is retrieved from the pool, you do your work, and then when you think you are closing the connection, the pool actually intervenes to keep that connection open and at the ready for future use. So every interaction with the database no longer means creating and destroying a connection with the database server.
If you go this route, the work you did above to use DataSource pays off. You switch from using a fresh-connection-each-time implementation of the DataSource interface with a connection-pooling implementation of the interface. So none of your code using the database need change.
Personally, I no longer use database connection pooling. Experiments of mine showed the premise of expensive connections to be exaggerated. Another problem: you must worry about connections being left in proper connection. For example, no pending transactions left open. Yet another problem: Trying to decide on a connection pooling implementation. There have been several over the years, and all have had various issues and problems, thereby inspiring yet another implementation. The upshot: The risk-benefit ratio of pooling is not good enough in my judgement.
You can keep the Connection opened without closing
Use Connection Pooling
(or)
Or you can save the connection object in the session and retrieve it in the servlet and pass it to the function in your DAO class whenever needed.

Issue on opening MongoDB Connections after calling close Method

I am working on a web project using java with mongoDB as back-end database.To open a connection once and reusing the same for each service contained in the project, i am following the below URL
mongodb open connection issue .For closing the connections which are opened, i'm using the function MongoDBClass.INSTANCE.close(); during the user logout of the session in web site.But the problem is, once the user login the session again it produces the following error java.lang.IllegalStateException: state should be: open.That means the connection is not opened , MongoDBClass INSTANCE is not reinitialized so MongoClient is not reopening the connection.But after the server restarts login works perfectly for first time. How to build a new connection again after when i call close method during logout the session of user without restarting the server. I am using the following code
public enum MongoDBClass {
INSTANCE;
private static final String MONGO_DB_HOST = "hostURL";
private Mongo mongoObject;
private DB someDB;
String DB_NAME = null;
MongoClientOptions options = null;
MongoDBClass() {
options = MongoClientOptions.builder().connectionsPerHost(100)
.readPreference(ReadPreference.secondaryPreferred()).build();
mongoObject = new MongoClient(new ServerAddress(MONGO_DB_HOST, 27001),
options);
someDB = mongoObject.getDB(Nutans_Mongo.getNameOFDB());}}
public DB getSomeDB() {
return someDB;
}
public void setSomeDB(String dbName) {
someDB = mongoObject.getDB(dbName);
DB_NAME = dbName;
}
public String close() {
mongoObject.close();
return "true";
}
}
MongoClient maintains a connection pool internally so there is no need to open/close a client for each request. Also, Java enums are not meant to be used this way. Any state an enum has should be globally usable as there will only be one instance of a enum value per ClassLoader/VM. When you call close(), you're globally closing that enum's MongoClient. Since you open the connection in the constructor it never gets reopened because a another INSTANCE is never created.
There are several approaches to ensuring a singleton-like lifecycle of objects in a servlet context. Using CDI to create and inject a MongoClient in to your servlet is one way. Using a ServletContextListener and static field is another, if slightly less savory, approach.
I have the same problem. I'm using the Mongo Java driver 3.0.0.
I upgraded my database from 2.4 to 2.6. But the problem persists.
When I don't close the connection, next time it connects successfully, but in this case open connections raises quickly.

HikariCP - Setting connected database dynamically on connection check-in and check-out from connection pool

I need to switch the database when a connection is checked-in and checked-out from pool. For instance, session X needs to receive a connection to database A and session Y needs to receive connection to database B.
I amd able to do it with C3P0 using a connection customizer. It calls the methods onCheckIn and onCheckOut of AbstractConnectionCustomizer, so I can do something like:
public class MyConnectionCustomizer extends AbstractConnectionCustomizer {
#Override
public void onCheckOut(Connection c, String parentDataSourceIdentityToken) throws Exception {
if (something) {
c.setCatalog("some database name");
}
}
#Override
public void onCheckIn(Connection c, String parentDataSourceIdentityToken) throws Exception {
c.setCatalog("some other database name");
}
}
I am trying to switch to HikariCP but it calls the customize method of the IConnectionCustomizer only once, when the connection gets created. So, how can I manage to implement such functionality?
One use case is multi-tenancy where there is single Database with multiple schemas. Based on the tenant logged into the application we need to switch the schema dynamically
I'm trying to understand the use-case for this? Why wouldn't you use separate pools, if session X really needs a connection to database A, and session Y needs a connection to database B?
HikariCP will likely never support such functionality (I can say that as one of the authors). A connection pool should provide a DataSource that is completely transparent to the application, such that if the pool was removed and the native DataSource was used instead the application would function identically (albeit less efficiently).
The very fact that you can do something like this in C3P0, but not in HikariCP, Vibur, or Apache DBCP should be a red-flag. Using such functionality locks you into a specific pool implementation, which is never a good thing.
Sorry, I can't provide a happy answer. If I were you I would consider writing an application level helper class to get/return connections that provides the semantics you are looking for.

How to get ServletContext attribute from a java class (not servlet)

Good evening! I have a web app with login-logout, where you can buy or sell some products. My queries are stored in a java class, called DBManager, which has just static methods that are called from servlets (I can't use JSP because in this project we can't use them, the professor gives us this constraint).
So here's the problem: I used to manage connection with ServletContextListener. In contextInitialized I set up connection, and in contextDestroyed I shutdown it. The attribute "Connection" is stored using ServletContext.setAttribute(Connection).
How can i get this parameter through the java class (not servlet) DBManager? I must get the object using getServletContext() inside a servlet and than passing it as an attribute, or there's a shortcut to avoid that?
Opening a connection in the method contextInitialized and closing it in contextDestroyed is a bad solution. Imagine that your web site has two visitors at the same time. They would now share the same database connection. If you work with transactions, you would end up with unexpected results where one visitor commits an intermediate state of a transaction executed by the other visitor. And if the connection is ever lost (maybe because the DB server is restarted), your application will fail because it does not re-establish the connection (unless you have a very smart JDBC driver).
A very expensive but safe solution would be to open a new connection for every database operation, and close it again immediately after the operation.
For a perfect solution, you would use some kind of connection pool. Whenever you need to execute a database statement (or a sequence of statements), you would borrow a connection from the pool. Once you're finished, you would return the connection to the pool. Most pool implementations take care of things like validation (check whether the connection is still "alive"), and multiple threads (different HTTP requests send by different visitors at the same time) can execute statements in parallel.
If you want to go for this solution, maybe the Commons DbUtils library is something for you: http://commons.apache.org/dbutils/
Or you check out the documentation of your Java application server or servlet engine (Tomcat?) to see what built-in DB connection pooling features it provides.
Instead of arbitrary getting the connection, you could change your class to receive a connection. That allows you to pass any instance of connection (what happens if you need to get data from another database?).
Also, imagine that the code will be ported to desktop. With this approach you can reuse your DAO without any changes.
class DBManager {
private Connection connection;
public DBManager(Connection connection) {
this.connection = connection;
}
//methods that will use the connection
}
In your HttpServlet doPost or doGet methods you can call getServletContext().
ServletContext sc = getServletContext();
DataSource ds = (DataSource) sc.getAttribute("ds");
Connection conn = ds.getConnection();
A servlet can bind an object attribute into the context by name. Any attribute bound into a context is available to any other servlet that is part of the same Web application.
Context attributes are LOCAL to the JVM in which they were created. This prevents ServletContext attributes from being a shared memory store in a distributed container. When information needs to be shared between servlets running in a distributed environment, the information should be placed into a session, stored in a database, or set in an Enterprise JavaBeans component.

Dynamically configuring datasources

The situation is this: a table that is used in a query (name it SUMMARY) was formerly in the same server and database that I'm doing all the queries of the application (name it server1 and DB1). But recently the SUMMARY table was deleted from this database, which makes it necessary to consult other server / database combinations.
The data from the server name and the database to be used for access to the SUMMARY table are parameterized in a table for this purpose. These data depend on the database which is connected, this way: for example, if I'm in the database DB1 of server1 then parameters will be server21 and DB21, whereas if someone refers to the parameters from the DB5 from server1 parameters will be server16 and DB16.
On that side I have no problem because I have listed the SQL query of the two parameters, ready to give the name of the server and database to consult in each case. This query is necessary in order to give server name and database name with which dynamically generate the datasource to connect to.
The problem, and the topic of this entry is, whether anyone has ever had to dynamically configure the datasource to be used in hibernate.properties, since this is usually a single, fixed value and in this case should be allowed changes in order to view the SUMMARY table (using parameters retrieved by my SQL query) only in this specific case, while all other database operations must be performed by using the original connection properties.
That is: What I need is to dynamically generate the datasource based on the parameters coming from the query, so the approaches which handle this by knowing beforehand how many and what are the possible connections should be discarded because they are not viable to solve my problem.
The application specifications are:
Database engine: SQL Server 2005
Prog. Language: Java 5.0
Frameworks: Spring 2.0.4, Hibernate 3.0.5
App. Server: WAS 6.1
Thanks in advance to anyone who has that knowledge and willing to share.
You can use a ConnectionProvider in hibernate to decide how to get the connection to be used by a session. We use something like this in our application:
public Connection getConnection() throws SQLException {
DataSource ds = (DataSource) BeanFactory.getBean("dataSource" + UserInfo.getDSName());
return ds.getConnection();
}
UserInfo is a class that store stuff in a ThreadLocal. This code will chose a datasource from Spring depending on the name that was passed in the ThreadLocal. What we do is to set the name of the datasource we want to use before opening the session (the actual logic is a little bit more complicated than that, as it depends on user preferences and other stuff).
You can do something like that to choose what Database to connect to.
You can check the javadocs for the ConnectionProvider interface. Make your own implementation, set the hibernate.connection.provider_class property in your hibernate configuration file to point to your class, and you're done.
I guess, it depends on the number of database/server combinations and the frequency of using them, but if there are a lot of database/servers and low use frequency, using plain JDBC without Hibernate and data sources might be an option. I don't think Hibernate is meant for situations like that.
or extend org.apache.commons.dbcp.BasicDataSource
public class MyDataSource extends BasicDataSource {
private void init() {
username = ...
password = ...
url = ...
}
#Override
protected synchronized DataSource createDataSource() throws SQLException {
init();
return super.createDataSource();
}
}

Categories

Resources