I need to know if my understanding on the above is correct.
In a connection pool you set multiple connections with the use of java.sql.Datasource.
In jdbc we directly specify the connection url and oracle.jdbc.driver.OracleDriver and it's always one connection, where another request has to wait until the connection has finished processing.
And with JNDI it's similar to direct jdbc where we refer the jdbc setting via a name, so that we can specify the connection url and other setting in the application server and not have them bound to the application, right?
Well these are two different things.
JDBC is Java Database Connectivity API, while JNDI is Java Naming and Directory Interface API.
The main thing here is that in a JNDI directory you're actually storing a JDBC DataSource, so, you're simply using JDBC to obtain a Connection via JNDI lookup.
In short words: JDBC is Database realm, JNDI lets you store Objects in a virtual context (the Directory) that can be local, remote (implementation details usually don't matters).
You access this context via names, obtaining stored objects, is good to share things among different modules.
Application Servers usually have a JNDI Context for sharing global objects among different application, Connection Poolers happen to be one of the most clear example of why sharing via JNDI is good (define 1 connection pooler, share between several webapps).
ConnectionPool
JDBC
JNDI
I know all the acronyms are daunting when you first learned Java, but get used to it, spend a lot of time reading .. especially official resources from Java/Oracle
Related
Everyone seems to say that you should use Tomcat's JNDI contexts to manage your JDBC connections and drivers and so forth. And after reading over the documentation, I understand the draw. But if you use it, your application must use a Tomcat container from now until the end of time. Isn't it a bad programming practice to make your application rely on such an environment configuration (especially for Java, which is supposed to be "Write Once, Run Anywhere")? How is this not a dangerous development decision?
Isn't it a bad programming practice to make your application rely on
such an environment configuration (especially for Java, which is
supposed to be "Write Once, Run Anywhere")?
Yes, in general. However, this design provides several benefits, including managed connection pooling and abstracting the database connection configuration from your application. JNDI itself is a directory service abstraction which protects you from directory API differences.
How is this not a dangerous development decision?
Using JNDI to manage JDBC connections is not specific to Tomcat. Every Java application server (GlassFish, Oracle, WebSphere, etc.) does this. So you're not tying yourself to Tomcat, just to Java.
See also: Using JNDI for Database connections
I don't know which documentation you read, but if you use JNDI, the only thing which you specify in the application, is the JNDI name of the resource you want to use (e.g. for the DB connection). Everything else is configured in the container and not part of your application (like URL of the DB, username, password etc.).
I'm new to java in web application design and I'm getting surprised how many things I don't now.
In particular I'm having problems in understending how servlet containers manage resources like connection pooling classes.
Assuming that I choose a pooling library (let's say c3p0), I read that there are many ways to use and manage the connection pooling classes.
For instance in many examples I saw that a certain class (let's say ComboPooledDataSource) is instantiated in the init() method of the servlet and here I'm getting a bit confusing. I mean, I think that a connection pooling system must exist and have a separate life with respect to all the servlets that will need a connection, otherwise it make no sense. So I think that the class below may be a Thread that is started once from the first servlet that call the init method and then it continues to exist until someone doesn not interrupt it. Is that correct? If not how does it work?
Anyway once I start this class , is it shared among all the servlets in the context (I mean all the servlets that call it in the init method)?
Other examples set up the connection pooling system as a resource by for instance defining it in the context.xml and then any servlet that want a connection just have to access it via JNDI (JNDI is correct?). What i understood (or I think to) is that in this case the thread that will execute the pooling system is started when the application is started and each servlet can access it when it wants to. Is that correct?
In this case can I modify the connection pooling system properties by a servlet or a background thread runtime? (for example if I want to change the number of connections as a function of the statistics on the number of requests and so on)
If I want to create different pools (for example I want to subdivide the database access to N different databases or I want to access using different usernames ) do I need to create as many resources as are the different kind of connection I want?
Is there a "better" way among these two or they are equivalent?
It comes down to ease of use of the webapp and (Tomcat) server maintenance.
You describe 2 use cases:
a connection pool used by one webapp
a connection pool shared between webapps
The first case is suitable for "ease of use": you can drop the war-file in any Tomcat server and it will work (e.g. Jenkins delivers such a war-file) since the webapp contains all the code needed to access a database. No need to change the configuration of the Tomcat server and restart it.
If I can, I like to deliver these kind of war-files since less things can go wrong (e.g. no clashes with configuration for other webapps). You can take it a step further by delivering Tomcat embedded with an application (so you don't need a Tomcat server to start with, an example project is here).
Note that opening a database connection pool (preferably via ServletContextListener.contextInitialized, not a servlet) and closing it (via contextDestroyed) does not involve starting and stopping a thread. The pool implementation may decide to start a background thread (e.g. to remove idle and/or abandoned connections), but it does not have to.
The second case is suitable for several webapps that share a common ground. For example, if several webapps all running in the same Tomcat server all use the same database, it saves time and effort if the Tomcat server already has a connection pool available for the different webapps (via JNDI). The Tomcat server can contain the JDBC driver software and connection pool software in the "lib" directory and configuration is done once in the context.xml of the server. If the database changes or different (patched) software components are required, only the tomcat server needs to be updated and all the webapps can remain the same. In this case, updating the Tomcat server instead of each webapp is a lot easier.
The second case is also more suitable for monitoring: there is a good chance you can monitor the connection pool via JMX. This kind of monitoring may not be available in the first case.
Changing "the number of connections as a function of the statistics on the number of requests " is not needed with connection pools: you set a maximum amount of connections to use and a timeout to remove idle connections. The connection pool will then grow and shrink with the number of requests.
Subdividing the database access to N different databases would require a different connection pool for each database, unless this is "read-only" in which case you could also use a load-balancer.
Access using different usernames is a bit tricky. I read in another question (which I cannot find anymore, sorry) that you can change the schema during runtime, but changing username/password might require a new connection in which case connection pooling is out.
Are you using Tomcat to run your servlets? Tomcat 7 has a new pooling solution that you could investigate. Tomcat also includes the dbcp libraries you can use them by setting the factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory". The DBCP pools are self managed and you can define the configuration values in the context.xml file I am not aware of how to change these values on the fly. I believe the Tomcat 7 pool use the same configuration as the DBCP with a couple of added options to make the conversion between the two simple. We use DBCP in all our applications and have not experienced problems so I have not used the Tomcat 7 pooling. I am thinking you would need to create many pools to handle most of your requirements.
I need to manage connections to multiple databases in my web app. following are facts regarding the current implementation:
1- I use Tomcat
2- databases are created dynamically at runtime ( i am using mysql)
without a doubt, having a connection pool to manage database connections is optimal.
Since the databases are not known at the start of the application, it was not possible for me to set up datasources and make connection pools. (I could not find a way in Tomcat to make dynamic connection pool: a connection pool that is created at runtime).
my question is: what other options do I have to work efficiently with connections to multiple databases ? (I don't have experience to implement connection pools myself)
is there any library that can be used with tomcat and allow me to establish multiple connection pools to different databases at runtime ? if not what do you suggest that I do instead of connection pools ?
i am fairly new with this issue therefore please correct and guide me if I am messing up concepts.
Thank you in advance.
The MySQL JDBC driver allows omitting the database name from the connection URL as follows:
jdbc:mysql://localhost:3306
You only need to specify the database by Connection#setCatalog() or directly in the SQL queries. See also its reference documentation:
If the database is not specified, the connection will be made with no default database. In this case, you will need to either call the setCatalog() method on the Connection instance or fully specify table names using the database name (that is, SELECT dbname.tablename.colname FROM dbname.tablename...) in your SQL. Not specifying the database to use upon connection is generally only useful when building tools that work with multiple databases, such as GUI database managers.
This allows you for creating a single and reuseable connection pooled datasource in Tomcat. You'll perhaps only need to rewrite your connection manager and/or SQL queries.
There are enough connection pooling framework in the open. Proxool is definitely among the best. Its pretty flexible and easy to use.
According to the MongoDB Java driver documentation, database connection pooling is magically handled by the Mongo object.
Does this mean it is safe to create an instance of a singleton object which connects to the MongoDB database in a servlet that will run when Tomcat starts and not worry about configuring database connection pooling in Tomcat via the context.xml?
Is this the right way to think about it? Am I misunderstanding some basic concept of Tomcat / database connection pooling in general?
We've been using the Java drivers via the CFMongoDB project and we use it as you describe, but in a ColdFusion application rather then in Java. Same idea though: one object is created and we reuse it and that object maintains the one connection to the Mongo server.
You can create one Mongo Java instance and it will maintain an internal pool of connections (default size of 10) - to you it's hidden and you don't need to worry about it. The Mongo Java docs recommend this:
http://www.mongodb.org/display/DOCS/Java+Driver+Concurrency
We have it running in production now and there have been no issues. Multiple web request threads use the same Mongo instance and Mongo is quick enough to deal with this using it's internal pool (we're doing logging so it can write very fast!).
It is worth remembering to call close() on any instances that you are finished with - this will stop connections getting used up on the Mongo server over time:
http://api.mongodb.org/java/2.5-pre-/com/mongodb/Mongo.html#close()
So in summary, don't worry about configuring Tomcat.
Hope that helps!
I have been looking into connection pool options and it is somewhat unclear to me what the differences in Tomcat JNDI connection pool approach is, compared to the Spring/Hibernate solution to the same.
Whilst it's possible to achieve the pooling using either 1, 2, the specific application we have would lend itself better to us using Tomcat given the constraints we have.
Reading about, there is some suggestion to just stick with Spring/Hibernate.
Are there any notable differences worth mentioning between each approach? What are other's personal experience of one or the other (or both) - I have successfully been using Spring/Hibernate for years now.
The two approaches are complementary, not mutually exclusive. In production systems, the likes of Spring/Hibernate will obtain a reference to the connection pool from the appserver, in the form of a javax.sql.DataSource, usually by looking for it on the JNDI tree. It generally considered to be the appserver's "job" to manage the connection pool and its connections.
Remember, JNDI is just a place for registering objects for sharing, it does in itself mandate any given connection pool mechanism. The app server creates and configures the pool, and the applications (via Spring/Hibernate/whatever) use it.
It's just as valid, however, for the applications to configure and manage the connection pool themselves. This does mean a bit more work for the application, though, with less reliance on the appserver.