I have been learning about how to set up Tomcat's connection pool through this website. So I made a context.xml file and put it in the directory META-INF. This is what I have right now.
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/gmustudent" auth="Container"
type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver"
username="root" password="root"
url="jdbc:mysql://localhost:3306/official"
maxActive="100" maxIdle="10" minIdle="5" initialSize="5" maxWait="10000" />
</Context>
However I would like to specify the class name of the factory. But everytime I add this attribute
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
I get a huge pile of errors in my console. Here are some of them in no particular order.
WARNING: Failed to register in JMX: javax.naming.NamingException: com.mysql.jdbc.Driver
WARNING: Unexpected exception resolving reference java.sql.SQLException: com.mysql.jdbc.Driver
WARNING: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:gmustudent' did not find a matching property.
So when I do not specify a factory the site works just fine. But when I do errors are thrown and nothing works. I did some research on stack overflow and found this post. Because of this I changed my tomcat version from 7.0.11 to the most recent but am still getting the error. So then I thought maybe it is some kind of clash with my factory in my server.xml file but I am not nearly experienced to make that call. But here is the resource in my server.xml file
<Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
So is this clashing with the factory in my context.xml file? Or am I totally wrong here? In a nut shell I would like to find out how to specify a factory in my context.xml file without getting a huge error. Thank you for reading.
You can actually manage the entire connection in your web app using Spring if you want. Here is an example using PostgreSQL:
<?xml version="1.0" encoding="windows-1252"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://localhost/mydb"/>
<property name="username" value="postgres"/>
<property name="password" value="postgres"/>
</bean>
</beans>
You can just put that in WEB-INF/classes and load it using:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/mycontext.xml");
I wouldn't even bother with having Tomcat manage it at this point.
Related
In our Tomcat 7 app, we sometimes have the following error while trying to access our DB:
javax.naming.NameNotFoundException: Name [comp/env/jdbc/app]
is not bound in this Context. Unable to find [comp].
Sometimes we have this error, sometimes not.
Context file:
<Context path="/app" docBase="/our/path/webapps/app.war" reloadable="true">
<Resource name="jdbc/app"
maxActive="100" maxIdle="30" maxWait="10000"
type="javax.sql.DataSource" username="usr" password="pwd"
driverClassName="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/app" />
</Context>
Beans files:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/app" />
</bean>
Code that sometimes fails:
getSession().createCriteria(OurClass.class).add(Restrictions.eq("key", key)).uniqueResult();
Any idea why this error is happening? And why it's intermittent?
I am using JEE5 with Postgresql, When I try to persist the object the output says
Could not find datasource: java:jdbc/postgres
javax.naming.NameNotFoundException: the name jdbc/postgres is not
asociated with this context
In context.xml (Tomcat7) I have
<Context>
<Resource name="jdbc/postgres" auth="Container"
type="javax.sql.DataSource" driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://127.0.0.1:5433/peopledb"
username="postgres" password="password" maxActive="20" maxIdle="10"
maxWait="-1"/>
</Context>
In persistence.xml I have:
<persistence-unit name="People">
<jta-data-source>java:jdbc/postgres</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true" />
</properties>
</persistence-unit>
In my persistence bean I have
#Stateless
public class PeopleDAOImpl implements PeopleDAO {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("People");
#Override
public void persistPeople(People pep) {
EntityManager em = emf.createEntityManager();
em.persist(pep);
}
}
Tomcat names the context resources differently than Glassfish. You defined the name in context.xml as jdbc/postgres, but in the persistence.xml you have to use java:comp/env/jdbc/postgres.
A late reply, but maybe still useful for others:
JTA can be used in Tomcat with componentized implementations like Atomikos (https://www.atomikos.com).
Cheers
PS: if you want help in setting things up you may want to consider a free trial of Atomikos - which includes Tomcat support / setup.
I am facing issue while starting my project.
Environment:
Tomcat 6, Jdk_6.45,
Alredy added: com.ibm.mq.jar, com.ibm.mqjms.jar,
Context.xml
<Context>
...
<Resource name="jms/sl.mqfactory" type="com.ibm.mq.jms.MQQueueConnectionFactory"
factory="com.ibm.mq.jms.MQQueueConnectionFactoryFactory" description="JMS Queue Connection Factory"
HOST="mqqs01.s.abc.co.uk" PORT="53162" CHAN="MQ.CLT.BLP.CHL.DEV"
TRAN="1" CCS="819" QMGR="QS01" auth="Container" username="" password="" />
</Context>
Spring:
<bean id="jndiConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${sl.mqfactory}" /> <!--from properties file -->
<property name="proxyInterface" value="javax.jms.QueueConnectionFactory"/>
</bean>
Exception:
java.lang.NoClassDefFoundError: Could not initialize class com.ibm.mq.jms.MQQueueConnectionFactory
After going through this link, I added J2ee.jar [without servlet package|folder in jar in my case(1.4.1) ]
And It's working now.
if you add j2ee jar with servlet folder tomcat will ignore it with jar not loaded. See Servlet Spec 3.0, section 10.7.2. Offending class: javax/servlet/..
Actually MQQueueConnectionFactory needs javax.resource-api
I have a problem setting up my configuration for JNDI with Spring. I checked the other posts but could not get my problem solved. I am using Tomcat 6 as my container. From my understanding I need to set up a resource on the server. So in my server.xml file I have this:
<GlobalNamingResources>
<Resource auth="Container" driverClassName="org.postgresql.Driver"
maxActive="100" maxIdle="5" maxWait="10000"
minEvictableIdleTimeMillis="60000" name="jdbc/myTomcatPool"
password="password" testOnBorrow="true" testWhileIdle="true"
timeBetweenEvictionRunsMillis="10000" type="javax.sql.DataSource"
url="jdbc:postgresql://localhost:5432/postgis" username="postgres"
validationQuery="SELECT 1"/>
</GlobalNamingResources>
I have the following in my spring-context.xml (which is on the classpath):
<jee:jndi-lookup id="geoCodeData" jndi-name="java:comp/env/jdbc/myTomcatPool" />
<bean id="geoCodeService" class="com.sample.SampleImpl">
<property name="dataSource" ref="geoCodeData"/>
</bean>
I then have this in file META-INF/context.xml:
<Context path="/myApp" reloadable="true" cacheMaxSize="51200"
cacheObjectMaxSize="2560">
<ResourceLink global="jdbc/myTomcatPool" name="jdbc/myTomcatPool"
type="javax.sql.DataSource"/>
</Context>
My server starts up free of errors.
When I try to run the following test (that worked before I added the JNDI code):
public class Test {
public static void main(String[] args) {
ApplicationContext ctx =
new ClassPathXmlApplicationContext("spring-context.xml");
}
}
I get the following error:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'geoCodeData': Invocation of init method failed;
nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
Is my configuration wrong or is the way I am trying to run the test incorrect?
When you run your testcases, you will want to use JDBC instead of JNDI lookup. The simple reason is because you usually don't run your testcases from the application server. Thus, JNDI lookup will fail.
What I do on my end is to place data source in a separate file. I have one file for production that uses JNDI:-
project-datasource.xml
<jee:jndi-lookup id="geoCodeData" jndi-name="java:comp/env/jdbc/myTomcatPool"></jee:jndi-lookup>
... another another file for unit test that uses JDBC:-
project-datasource-test.xml
// use the same bean name "geoCodeData"
<bean id="geoCodeData" class="...">
<property name="driverClassName" value="..." />
<property name="url" value="..." />
<property name="username" value="..." />
<property name="password" value="..." />
</bean>
The web app will use project-datasource.xml whereas the unit test will use project-datasource-test.xml.
After several hours of tearing out my (already sparse) hair I have managed to get my tomcat server to pool database connections to Oracle and use the Spring framework.
I though I would reply to this question even though there seems to be an answer, just in case it helped anybody else.
What I wanted:
A connection pool administered by Tomcat (rather than per servlet) and the config for the DB connection in the Tomcat server config (again, rather than the servlet config files).
We have several instances of Tomcat and each one connects to a specific Oracle DB, but developers are producing servlets that could be required to run on any one of them, hence I don't want the DB connection details in the WAR file they produce, but to let them look it up and be provided with that server's data source, via JNDI.
In the Tomcat server conf/context.xml I added the following code:
<Resource name="jdbc/banner"
auth="Container"
factory="org.apache.commons.dbcp.BasicDataSourceFactory"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#DBan8DB1.example.ac.uk:1522:bde8"
username="dbsro"
password="verysecret"
initialSize="5"
maxActive="20"
maxIdle="10"
removeAbandoned="true"
global="jdbc/banner"
maxWait="-1"/>
Obviously I have the ojdbc, pool and dbcp JAR files present in Tomcat's lib directory on the server.
An important point to note here is that the type is of "javax.sql.DataSource" rather than "org.apache.commons.dbcp.BasicDataSource" which I originally thought it should be.
Now in the Web Application's WEB-INF/web.xml I added the following:
<resource-ref>
<description>Oracle Banner Datasource</description>
<res-ref-name>jdbc/banner</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
and in my Web Application's servlet-context.xml file (where ever you keep yours might vary) I had this. This is not the whole file but the XML name space is important here, for the jee parts:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/banner" resource-ref="true" />
Again note the fully qualified reference jndi-name="java:comp/env/jdbc/banner" which seemed to be required. Why is isn't needed in the resource-ref section of the web.xml file, I have no idea.
If anyone has any thoughts on this I would be pleased to read them.
By the way, this URL helped: Tomcat6 JNDI data source how-to
After all that, the connection worked. So I mopped the blood, sweat and tears from my work station and enjoyed a delicious cup of fresh coffee.
I've always used Spring's dependency injection to get datasource objects and use them in my DAOs, but now, I have to write an app without that.
With Spring I can write something like this:
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1/app?characterEncoding=UTF-8" />
<property name="username" value="u" />
<property name="password" value="p" />
</bean>
But how can I use datasource in my DAOs without Spring or anything? I'm using servlets and JSPs only. Performance is very important factor.
Believe it or not, people were writing applications before Spring and some are still not using it :) In your case, you could use Tomcat connection pool (and there is a complete configuration example for MySQL in the documentation). Let me summarize it:
First, put your driver in $CATALINA_HOME/lib.
Then, configure a JNDI DataSource in Tomcat by adding a declaration for your resource to your Context:
<Context path="/DBTest" docBase="DBTest"
debug="5" reloadable="true" crossContext="true">
<!-- maxActive: Maximum number of dB connections in pool. Make sure you
configure your mysqld max_connections large enough to handle
all of your db connections. Set to -1 for no limit.
-->
<!-- maxIdle: Maximum number of idle dB connections to retain in pool.
Set to -1 for no limit. See also the DBCP documentation on this
and the minEvictableIdleTimeMillis configuration parameter.
-->
<!-- maxWait: Maximum time to wait for a dB connection to become available
in ms, in this example 10 seconds. An Exception is thrown if
this timeout is exceeded. Set to -1 to wait indefinitely.
-->
<!-- username and password: MySQL dB username and password for dB connections -->
<!-- driverClassName: Class name for the old mm.mysql JDBC driver is
org.gjt.mm.mysql.Driver - we recommend using Connector/J though.
Class name for the official MySQL Connector/J driver is com.mysql.jdbc.Driver.
-->
<!-- url: The JDBC connection url for connecting to your MySQL dB.
-->
<Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="javauser" password="javadude" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/javatest"/>
</Context>
Declare this resource in your web.xml:
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<description>MySQL Test App</description>
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/TestDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app>
And get the datasource with a JNDI lookup in your application:
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource) envCtx.lookup("jdbc/TestDB");
Connection conn = ds.getConnection();
... use this connection to access the database ...
conn.close();
Note that such lookup is usually coded in a ServiceLocator (when you can't have a a DI container or a framework inject it for you).
I used to get error with sybase, I had missing META-INF folder in WebContent folder. Putting context.xml in that fixed the error Cannot create JDBC driver of class '' for connect URL 'null'...
// www.abbulkmailer.com
My context.xml looks like
<Context path="/reports" docBase="reports" debug="5" reloadable="true" crossContext="true">
<Resource name='jdbc/ASCSybaseConnection'
auth='Container'
type='javax.sql.DataSource'
username='fdd'
password='555'
driverClassName='com.sybase.jdbc2.jdbc.SybDriver'
maxActive='100'
maxIdle='100'
minIdle='10'
removeAbandoned="true"
removeAbandonedTimeout="60"
testOnBorrow="true"
logAbandoned="true"
url='jdbc:sybase:Tds:1.3.4.5:654/DB'/>
</Context>
You can declare your data source as a JNDI object and retrieve a datasource via a JNDI lookup:
DataSource ds = (DataSource)
envCtx.lookup("jdbc/EmployeeDB");
as documented here and here.
That's as bare-bones as you can get, so from there on, performance is completely up to you.