Tomcat7 MySQL connector inconsistency - java

This is a bit of a weird one question and I cannot for the life of figure out what's going on. I have two applications (WARS) running on a Tomcat7 instance. Both of them connect to a database and get that connection using JNDI. The datasource reference specified in the tomcat context.xml file as follows.
Tomcat7/conf/context.xml
<Resource name="jdbc/dataSourceOne" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="user" password="pass" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/databaseone" />
<Resource name="jdbc/dataSourceTwo" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="user" password="pass" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/databasetwo" />
WEB-INF/lib
Both applications have a copy of the mysql connector jar in their lib folders.
mysql-connector-java-5.1.34.jar
Now here's where it gets weird, application 1 works straight out of the box. I just need to deploy the WAR on my tomcat instance and it's all systems go. It gets its datasource and can connect to it's database with absolutely no problems.
However, when I try and deploy application 2, I get a MySQL class not found exception. Now the fix for this is to add the above mysql connector jar to the tomcat7/lib folder.
My question is why do I need only need to add this for my second application? If tomcat7 requires the mysql connector jar why does my first application work without any modification to the tomcat7 setup at all?
It just doesn't make sense that one application will work but the other won't without the modification.
Any help would be greatly appreciated folks.

#Gimby - Turns out you were right, application 1 wasn't actually using the datasource defined in tomcats context.xml file. Thanks for the input, really appreciate the help.

Related

JNDI Resources in web-fragment

I'm working on a web-fragment to isolate a specialized process needed in only one part of our overall production process. I'm trying to define a JNDI resource specific to the web-fragment, but I keep running into a brick wall.
The application is running in Tomcat 9.
I am using Web-Fragment specification 4.0.
The working model, right now, is I have the database connection defined as a global resource in the server.xml as such:
<Resource name="localappserver"
auth="Container"
driverClassName="oracle.jdbc.OracleDriver"
factory="org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory"
initialSize="5"
logAbandoned="true"
minEvictableIdleTimeMillis="30000"
maxTotal="15"
maxIdle="3"
maxWaitMillis="1000"
removeAbandonedOnBorrow="true"
removeAbandonedOnMaintenance="true"
removeAbandonedTimeout="15"
testOnBorrow="true"
testWhileIdle="true"
timeBetweenEvictionRunsMillis="300000"
type="javax.sql.DataSource"
username="${jdbc.user}"
password="${jdbc.password}"
url="${jdbc.url}" />
and is referenced in the larger web application context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context docBase="..." path="/..." reloadable="true" swallowOutput="true">
...
<ResourceLink global="localappserver" name="localappserver" type="javax.sql.DataSource" />
...
</Context>
This works as expected and I can connect to the resource and retrieve data. However, I do not want to pollute the main application's context.cml with items that do not pertain to the main application.
I've tried moving the resource link from the main context.xml to the web-fragment's context.xml but that results in the following error:
INFO: javax.naming.NameNotFoundException: Name [localappserver] is not bound in this Context. Unable to find [localappserver].
at org.apache.naming.NamingContext.lookup(NamingContext.java:833)
at org.apache.naming.NamingContext.lookup(NamingContext.java:160)
at org.apache.naming.NamingContext.lookup(NamingContext.java:843)
at org.apache.naming.NamingContext.lookup(NamingContext.java:160)
at org.apache.naming.NamingContext.lookup(NamingContext.java:843)
at org.apache.naming.NamingContext.lookup(NamingContext.java:174)
at org.apache.naming.SelectorContext.lookup(SelectorContext.java:163)
at java.naming/javax.naming.InitialContext.lookup(InitialContext.java:409)
at com.obj.Data.Connect(Data.java:141)
I've moving the resource definition from the server.xml to the web-fragment's web-fragment.xml and even the web-fragment's context.xml. Both instances return the same error.
While I can live with this one instance, I know we will be adding and/or migrating more pieces to web-fragments and I really want to separate the resource references to their specific jar.
EDIT
I should mention I am testing all of this while running tomcat from inside Eclipse. I don't think that will make a difference, but I want to mention it
Is this even possible?
We have decided to containerize the application. Thus, as we have multiple locations in our production process, this will become a non-issue.
By placing the resource link <ResourceLink global="localappserver" name="localappserver" type="javax.sql.DataSource" /> in the individual location's [TOMCAT_HOME]/conf/context.xml we eliminate the need to clutter the main application's /META-INF/context.xml
This should work as we divide up each location's requirements into individual web-fragment projects.

Tomcat Connection Pool under WEB-INF/context.xml or TOMCAT_HOME/conf/server.xml?

This is the first time I'm trying to set up a connection pool in tomcat (version 8), and I'm kind of confused. It seems that I have 2 options available to me, 1) I can add something similar to this:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!-- Specify a JDBC datasource for oracle -->
<Resource name="jdbc/testdb"
auth="Container"
type="javax.sql.DataSource"
username="DB_USERNAME"
password="DB_PASSWORD"
driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:#xxx:1525:dbname"
maxActive="10"
maxIdle="4" />
</Context>
In a file called 'context.xml' in my projects WEB-INF folder. OR, 2) I can add something like this:
<Context path="/dbcp" docBase="dbcp" debug="5"
reloadable="true" crossContext="true">
<Resource name="jdbc/TestDB" auth="Container"
type="javax.sql.DataSource" removeAbandoned="true"
removeAbandonedTimeout="30" maxActive="100"
maxIdle="30" maxWait="10000" username="kunal"
password="java_facier"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost/dbcptest"/>
</Context>
in TOMCAT_HOME/conf/sever.xml and then add this:
<resource-ref>
<description> DB Connection Pooling</description>
<res-ref-name> jdbc/TestDB</res-ref-name>
<res-type> javax.sql.DataSource</res-type>
<res-auth> Container</res-auth>
</resource-ref>
to my WEB-INF/web.xml file in my project...
If I'm correct in both instances here, which one is better to use? Also where would I put my database vendors jdbc-driver?
Put JDBC libraries to $tomcat/lib folder so that webapp reloads don't touch it. I have found this the best common rule and even an official Apache Tomcat documentation instructs $CATALINA_HOME/lib folder so please follow their wisdom.
$tomcat/webapps/mywebapp/META-INF/context.xml
This provides you an application level pool. You having two or more webapps connecting to a same database each have own pool. It means they obye own private max-limit and such meters. Distributing and installing mywebapp.war file is easy, this is a self-contained application.
$tomcat/conf/server.xml
This provides a global pool where two or more webapps share same max-limit and such meters. If you must control the overall number of connections opened to the db engine this is where you should put jdbc settings. Tomcat admin must put this setting in place before deploying a webapp.
edit: Oh I see you have put jdbc settings inside the <Context> element in server.xml file. Well, in that case I think its still a webapp-private pool. If you need global pool you add it inside <GlobalNamingResources> element at the top of xml file.
Either approach has it pros and cons :
1. Application level packaging creates App local connection pools.
2. Independent from Tomcat's setup
but,
Application on release requires environment specific releases.
While, if tomcat maintains connection pool then app only depends on "Registered Name" and single package can be distributed for all environments.
Just to summarize, App level packaging is developer centric whereas Tomcat-maintained connection pools are Operational friendly.

How to configure a global JNDI datasource in Tomcat 6?

I'm struggling to configure a simple JNDI pooled datasource in Tomcat 6.0.32.
I want to create the datasource definition outside my web application artifact. Basically I don't want my application to know the credentials to access the database server.
I was under the assumption that, like in Weblogic, it should be possible to create a "global" JNDI datasource in Tomcat, but so far I have been unsuccessful.
I have tried to add the datasource definition in CATALINA_HOME/conf/context:
<Resource name="jdbc/mydb"
auth="Container"
type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
factory="oracle.jdbc.pool.OracleDataSourceFactory"
url="jdbc:oracle:thin:#1.1.1.1.:xxx"
user="xxxx"
password="yyyy"/>
The result is that the server outputs the following line, when booting:
SEVERE: Null component Catalina:type=DataSource,path=/,host=localhost,class=javax.sql.DataSource,name="jdbc/mydb"
Any pointer would be appreciated.
Move your data source configuration to server.xml <GlobalNamingResources>. (And don't forget to add the driver jar file to tomcat lib).
Configure your context.xml so that all Application are aware of the global resource.
<Context>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<ResourceLink global="jdbc/mydb" name="jdbc/mydb" type="javax.sql.DataSource"/>
</Context>
Your mistake: user="xxxx", you need to write username="xxxx" instead.

DB connection pool in Standalone Axis2?

For my services in production environment I always set up DB connections pool in Tomcat's context.xml:
<Resource name="jdbc/MyDB" auth="Container" type="javax.sql.DataSource"
maxActive="256" maxIdle="5" maxWait="10000"
removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true"
username="xxx" password="xxx" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://host:3306/dbname?autoReconnect=true"
validationQuery="SELECT 1"
/>
Then later in my service I use:
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/MyDB");
Connection db = ds.getConnection();
For development I want to run Axis2 standalone - is there a way how I could set up somewhere DB connections pool in Axis as well so I would not need to modify service code and use it the same way as with Tomcat?
Why not have different context.xml files for different environments.
e.g.
context_DEV.xml
context_UAT.xml
context_PROD.xml
and then use a symlink to point to the correct one.
e.g.
context.xml -> context_DEV.xml
Also, see this thread which recommends using a servlet container (such as Tomcat) rather than axis2 standalone server for stability.

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.

Categories