Is it possible to setup multiple urls for tomcat datasource - java

We have a backup database (which we want tomcat to failover in case primary database is down).
Trying to setup as following, but it is not working, am I missing something ?
<Resource auth="Container"
driverClassName="oracle.jdbc.driver.OracleDriver"
initialSize="5"
maxIdle="10"
maxTotal="15"
maxWaitMillis="15000"
name="jdbc/dbcporacle"
username="username"
password="xxxxxxxx"
testOnBorrow="true"
type="javax.sql.DataSource"
validationQuery="select 1 from dual"
url="jdbc:oracle:thin:#dbhost11111.com:3203/dbsvc111, jdbc:oracle:thin:#dbhost22222.com:3203/dbsvc111"/>
Note 2 urls (comma separated) in the url attribute

I'm not aware that there ever was such an option to provide two URLs and assume that they both have the same username/password. Where did you get this information? Or have you just been blindly trying?
Failing over to a different database is not as trivial as connecting to a different URL. Well, at first it is, but what happens when the original database comes back online? How does it get all the updates that were written to the secondary database? How will you determine that it's time to connect back to the original one?
One proper way to deal with failures is to configure your backend databases as cluster - they'll have a single URL that the application connects to, and transparently handle failover independently of your application.
So: Are you missing something? Yes: Configuring a datasource to two URLs never was supposed to work (let alone to work this way), and it won't solve your problem anyway.
And if your database is read-only, so that you can transparently switch between the alternatives: Handle this on the application level and just configure two databases that your application can failover to. This way your application will have to deal with it. Of course, you could implement your own DataSource to handle such a handover on failure of one of them.

Related

Remote MySQL DB and eclipse

I am currently trying to implement a simple servlet that has to communicate with our database.
I have no real prior experience with databases, so I was wondering how I should I go about this? I have downloaded the mysql-connector-java-5.1.40 from dev.mysql.
Going over some of the directions on the web for setting up the connection, it seems to only be for local mysql, but what of remote? The remote's user and pass is demo/demo; of course I would also need to log into the the remote server with my credentials. How do I go about connecting to this remote db?
Edit: So I believe I successfully connected to the DB, at least I can see it in my eclipse under data sources and the tables are present (company and stock_prices), however my eclipse still says I have an unsuitable driver even though I do have one associated with it.
The proper way of consuming a database resources in a web container (or in an application server) is through the javax.sql.DataSource abstraction. So you should configure a data source in your container. For tomcat it's as simple as creating a file named context.xml in your war's META-INF folder with the following content (replace address and credentials with your own):
<Context>
<Resource name="jdbc/[YourDatabaseName]"
auth="Container"
type="javax.sql.DataSource"
username="[DatabaseUsername]"
password="[DatabasePassword]"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql:/[yourserver]:3306/[your-db]"
maxActive="20"
maxIdle="20"/>
</Context>
Then when you want to perform a DB operation:
you either look up the data source:
DataSource ds =(DataSource) new InitialContext().lookup("java:comp/env/jdbc[YourDatabaseName]");
or simply use dependency injection for managed components like servlets:
#Resource(name="jdbc/YourDataSource")
Datasource ds;
The you just get a connection from the datasource in order to execute statements to the database.
The DB driver can be put in one of two places:
the war's lib folder
tomcat's lib folder
It's recommended to put it in tomcat's lib, because drivers are singletons and if you have several apps with different versions of the driver in the same container bad things will happen.
How do I go about connecting to this remote db?
Connecting to a remote DB is the same as connecting to alocal DB. Just pass the correct DB address in the connection string.

Fundamental issue in connection pooling of Tomcat

I am using Tomcat 7 connection pooling (as a Tomcat resource in server.xml and context.xml) in a web application and it works.
My question is: Is it possible to "tell"/"force" tomcat to dispose the connection pool after it is created?
The reason I ask is the following:
I am using H2 and run into some "racing" issue on shutdown.
H2 remains open as long as there is a connection open but Tomcat does not dispose the connection pool and so connections remain open. And as a result I have various issues on shutdown.
I found that I could issue an SQL SHUTDOWN command to close H2 but I want to explore all the alternatives for my case.
So is it possible to "tell"/"force" tomcat to dispose the connection pool (at least on shutdown)?
I think you can try to put debug log on and check whether its issue with connection not released by application or something else like datasource configuration parameter in server.xml.
mostly it should be the case where application is not releasing connection.
How about writing a custom ServletContextListener and then having it shut down the pool when the context is destroyed. Here's an article about ServletContextListener being used to create shutdown hooks:
shutdown hook for java web application
The API for context listeners seems pretty straightforward:
http://docs.oracle.com/javaee/5/api/javax/servlet/ServletContextListener.html
please see my answer in : Context specific JNDI parameters problem in tomcat 6. There's a lot of stuff you can do with jndi resource.
<Resource name="jdbc/NAME" auth="Container" type="javax.sql.DataSource"
maxActive="100" minIdle="10" maxWait="10000" removeAbandoned="true"
removeAbandonedTimeout="60" logAbandoned="true"
testWhileIdle="true" testOnBorrow="true" testOnReturn="false"
timeBetweenEvictionRunsMillis="5000"
validationQuery="SELECT 1" initialSize="10"
username="usrname" password="password"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/databb?autoReconnect=true"/>
As described in documentation http://tomcat.apache.org/tomcat-7.0-doc/config/context.html#Resource_Definitions it possible to set closeMethod of container datasource. I'm not sure about 'disposing' connection pool, but i think it worth a try.
Name of the zero-argument method to call on a singleton resource when
it is no longer required. This is intended to speed up clean-up of
resources that would otherwise happen as part of garbage collection.
This attribute is ignored if the singleton attribute is false. If not
specificed, no default is defined and no close method will be called.
Also you can deploy DataSource programmatically and start/stop it in ServletContextListener, example for dbcp (sorry, it from my unit-tests, but easy to rewrite):
import org.apache.commons.dbcp.BasicDataSource;
static BasicDataSource bds = new BasicDataSource();
#BeforeClass
public void setUp() throws Exception {
bds.setDefaultAutoCommit(false);
bds.setDriverClassName("org.h2.Driver");
bds.setInitialSize(0);
bds.setMaxActive(2);
bds.setMaxWait(10000);
bds.setPassword(null);
bds.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
bds.setUsername("sa");
bds.setValidationQuery("select 1 as test");
}
#AfterClass
public void tearDown() throws Exception {
bds.close();
}
Maybe I don't understand the question. To be more clear, if you shutdown Tomcat (and hence it's JVM), then neither Tomcat nor it's connection pools, nor any of it's daemon threads would still be alive ... and thus no memory references would be left in tack.
How exactly have you come to the conclusion that a Tomcat resource has a reference to a connection pool, after Tomcat is shutdown? You wouldn't be able to see that in a profiler, and frankly, it doesn't quite make sense. For example, is it possible that the OS keeps connections open for a short period of time before destroying them? Have you tried the same tests using the same OS, but instead with a different container, something like Jetty? Are you using keep-alives, or some form of persistent connections?
If you want to get down-and-dirty with Tomcat's management of a resource exposed through JNDI, you can make your own DataSource implementation that delegates to the H2 DataSource. You can do this my using the factory-method attribute within your server.xml (or context.xml)
Here's a working example on github : https://github.com/tvollmer/connection-factory
Beyond that, it would help if you could further clarify what you mean by "various issues on shutdown". Those details matter, and it's not clear to me how you've logically gone from "various issues" to saying that Tomcat "does not dispose the connection pool". You could be dealing with 2 completely separate issues here, and you may want to check out antiResourceLocking and antiJARLocking settings for Tomcat on Windows.

Building Production Release - DB Connection Credentials

We have a build that can package war files for specific environments where all our property files are embedded in the archive (war file).
We are now about to build for production. My concern is the codebase will need to expose the production database password and although unlikely there is a risk where the production build profile could be run with a negative effect.
Options I thought of to negate this risk is to not store the production details in SVN and:
Have the administrators override system properties which are used to connect to the DB, or
Have the container manage the DB connection instead of c3p0, this way they can manage this configuration themselves.
Do you have any advice?
You should definitely not be putting the production DB username and password into your source control system. Your app should be getting its DB connection (eg a DataSource) using JNDI which is controlled/restricted by the admins on the production environment.
For example, if your app is deployed to Tomcat, you have the following in tomcat/conf/context.xml
<Resource name="jdbc/myDB"
auth="Container"
type="javax.sql.DataSource"
maxActive="20"
maxIdle="10"
maxWait="3000"
username="myusername"
password="mypassword"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://myhost:3306/myschema"
defaultAutoCommit="false"/>
..and the connection is obtained from java:/comp/env/jdbc/myDB without your app ever having to provide a username or password. The tomcat installation is protected on the prod servers by the admins, so it is unavailable to anyone without admin access on your prod server.
In production I favor the approach to not store credentials on property files at all. Instead I prefer the application server to supply the credentials using jndi.
If you are using Apache Tomcat, see for instance their jndi reference.
I have tried both having properties in the archive and outside of the archive, and having them outside of the archive is much easier to manage this kind of problem.
Some things to note:
To the extent that is possible, you can have defaults for properties, so that if the property is not found it will use the default (for example, using "localhost" as the default database connection URL).
You can still keep property files for non-production environments in source control alongside the code.
Using these two policies, developers can be responsible for managing non-production property files, which also therefore serve as examples to the production admin. It also keeps most of the properties centralized in source control, giving some of the benefits of keeping things centralized, while still decoupling the properties enough.
EDIT: Note that JNDI is an option, but architecturally it is the same as storing property files outside - you still need to take care to version these not have them be loose in different environments.

How to configure tomcat 6.0 for mysql

I'm using Tomcat 6.0, and I want to know how can I configure Tomcat's server.xml file to connect to mysql database, and enable form based authentication in java.
I'm currently using mysql 5.1, and I've already downloaded mysql connector jar file, and put in lib directory of Tomcat.
I'm guessing you want Tomcat to create connection pool to MySQL database. In that case, you don't need to configure server.xml file. In the context.xml file you need to add a <Resource> element, something like this:
<Resource name="jdbc/MySQLPool" auth="Container" type="javax.sql.DataSource"
factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
maxActive="100" maxIdle="30" maxWait="10000"
username="USERNAME" password="PASSWORD"
driverClassName="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource"
url="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=Cp1251"
removeAbandoned="true" />
(I'm not sure if that's the correct driverClassName for MySQL, but your Resource should look somewhat like this).
For more info, try checking Tomcat's documentation on JNDI Resources and JDBC DataSources.
Typically context.xml and server.xml are separated, and you usually configure a data source on web-app level, that is in the context of that web app. The reason for that is that a data source connects not so much to a server but to a database within that server, and having multiple apps accessing the same database is not always a good idea (if you didn't design the apps for that).
That said, have a look at this tomcat wiki page which describes what you want (or what I think you want).
For authentication check out this thread on velocity reviews.

Do Tomcat JDBC Connection pools get shared between instances?

We have a web application right now that we deploy a copy for each client. Our current deployment strategy is to create a uniquely named jdbc connection pool for each instance.
so say jdbc/client. They are specified like this...
< Context path="/"
reloadable="true"
docBase="\home\client\ROOT"
debug="5" >
< Resource name="jdbc/client"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
validationQuery="SELECT 1"
testWhileIdle="true"
timeBetweenEvictionRunsMillis="300000"
numTestsPerEvictionRun="6"
minEvictableIdleTimeMillis="1800000"
maxWait="10000"
username="user"
password="pass"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://databaseserver:3306/client ?zeroDateTimeBehavior=convertToNull&jdbcCompliantTruncation=false"/>
< /Context>
The question is, if I were to standardize it so that instead of unique names the connection pool is called jdbc/database on all deployed instances, is there a chance of database crossing, ie one customer in another customer's database, or are these localized to a specific deployed instance?
Thoughts?
Thanks,
Scott
No. The scope of the data source name is one Tomcat instance.
If you are starting a separate Tomcat process for each customer, all that matters is how the data source is configured, not what Tomcat calls it. As long as each data source is configured to use a different database, there won't be any cross talk.
This depends on how you deploy application for each client,
If each client gets their own Tomcat installation (they have different CATALINA_HOME), there is no chance for it to cross.
If they all use the same installation but run as different host in Tomcat, you need to make sure you don't define the datasource in conf/context.xml, which is shared by all hosts.
If all clients share the same Tomcat instances and they are simply different web apps, more attention is required. You need to define the datasource either in META-INF/context.xml or WEB-INF/web.xml. For further isolation, you should copy dbcp.jar to WEB-INF/lib of each application so they use their own DBCP instance.
If you're defining the JNDI DataSource resource within the Context for a deployment of the application, I believe you could even have multiple copies of the same application running in the same Tomcat instance and using the same JNDI name to access different databases. If each application instance is running in a different instance of Tomcat completely, there is certainly no way that one instance would be referring to the database specified for another instance.
No there is no chance of database crossing becoz the scope of the data source name is one Tomcat instance and you can have multiple data source in single tomcat instance .... so as long as data source is different there is no chance of database crossing.....

Categories