Tomcat JNDI resource for Datanucleus (JDO) - java

I have developed an application on Tomcat 7.0 that uses Datanucleus / JDO to access to a database. I currently have the JDO connection properties stored in the "datanucleus.properties" located in the application itself. The connection is working fine, but I would like to store the connection information as JNDI, to have it on the server and no longer in the war itself (I always have to replace the file in the war when deploying it remotely).
I tried the following:
Create a in the web.xml of the application (jdbc/ConnectionDB)
In "Server.xml", I tried to add the following the context of my application
<Resource name="jdbc/ConnectionDB" auth="Container" type="javax.jdo.PersistenceManagerFactory" /> <ResourceParams name="jdbc/ConnectionDB
<parameter>
<name>javax.jdo.PersistenceManagerFactoryClass</name>
<value>org.datanucleus.api.jdo.JDOPersistenceManagerFactory</value>
</parameter>
<parameter>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</parameter>
<parameter>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://localhost/TomcatTest</value>
</parameter>
...
I then try to create a new PMF with the following syntax:
Context context = null;
PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory("java:comp/env/jdbc/ConnectionDB",context);
When I run my application, I get a javax.jdo.JDOUserException: You have either specified for this PMF to use a "persistence-unit" of "datanucleus.properties" (yet this doesnt exist!)
I don't really understand what is wrong in my setup.
Regards,
Marcel

I finally found the solution I was looking for, I post it here, it might help somebody else:
Create a resource in "Context.xml" file of the server
<Resource name="jdbc/SyncTestDB"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="root"
password="mysql"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost/SyncTestDB"/>
Create a reference to that resource in the "web.xml" file of your application
<resource-ref>
<description>MySQL Database Connection</description>
<res-ref-name>jdbc/SyncTestDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
And finally get a Persistence Manager Factory using the JNDI connection:
PersistenceManagerFactory pmf;
Properties properties = new Properties();
properties.setProperty("datanucleus.ConnectionFactoryName","java:comp/env/jdbc/SyncTestDB");

Read the javadoc for JDOHelper.getPersistenceManagerFactory(String) and it is obviously not for passing in some JNDI data source string.
Read the docs for Tomcat and you will also see that specifying a datasource you do not provide JDO connection details.
You can equally specify a persistence.xml with that JNDI string for the "javax.jdo.option.ConnectionFactoryName" property. As per the JDO spec and DataNucleus/Tomcat docs then

Related

porting web app to Tomcat: javax.naming.NameNotFoundException:

New user of Tomcat (8.5.9) on Linux CentOS 7 with Java SE 8. I must be making a simple mistake. This should be a textbook example how to configure a JDBC connection pool for tomcat.
I have this error:
javax.naming.NameNotFoundException: Name [jdbc/pool1] is not bound in this Context. Unable to find [jdbc]
Any idea what I could doing wrong? Tomcat states It is NOT recommended to place <Context> elements directly in the server.xml file. Thus, my setup:
$CATALINA_HOME/webapps/myapp/META-INF/context.xml is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/pool1"
auth="Container"
type="javax.sql.DataSource"
username="xx"
password="xx"
driverClassName="oracle.jdbc.OracleDriver"
url="xx"
maxTotal="256"
maxIdle="8"
initialSize="4"
removeAbandonedTimeout="7200"
removeAbandonedOnBorrow="true"/>
<Resource name="jdbc/pool2"
auth="Container"
type="javax.sql.DataSource"
username="xx"
password="xx"
driverClassName="oracle.jdbc.OracleDriver"
url="xx"
maxTotal="256"
maxIdle="8"
initialSize="4"
removeAbandonedTimeout="7200"
removeAbandonedOnBorrow="true"/>
<ResourceLink name="jdbc/pool1"
global="jdbc/pool1"
type="javax.sql.DataSource"/>
<ResourceLink name="jdbc/pool2"
global="jdbc/pool2"
type="javax.sql.DataSource"/>
</Context>
$CATALINA_HOME/webapps/myapp/WEB-INF/web.xml is as follows:
...
<resource-ref>
<description>xxx</description>
<res-ref-name>jdbc/pool1</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<resource-ref>
<description>xxx</description>
<res-ref-name>jdbc/pool1</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
...
The code causing the exception:
Context context = new InitialContext();
DataSource ds = (DataSource)context.lookup("jdbc/pool1");
conn = ds.getConnection();
I have not modified $CATALINA_HOME/conf/server.xml at all. Did I configure something incorrectly, or am I missing setting another file up somewhere?
UPDATE 1
I tried adding the above ResourceLinks to the GlobalNamingResources tag in the $CATALINA_HOME/conf/server.xml file, then stopping/starting Tomcat, but I got the same error.
UPDATE 2
I then added the Resource tags from context.xml above also to the server.xml file (GlobalNamingResources tag), stopping/starting tomcat, and got same error.
UPDATE 3
I got everything working with Andreas' expert help (thanks!) by changing the way java calls the pool:
Context initCtx = new InitialContext();
Context context = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource) context.lookup("jdbc/pool1");
conn = ds.getConnection();
Also, the ResourceLinks should not be in server.xml (they simply generate a warning in tomcat log).
Your $CATALINA_BASE/conf/server.xml file should contain the full <Resource> element. Remember to also add the JDBC driver jar file to Tomcat's $CATALINA_BASE/lib folder, since it is Tomcat, not your webapp, that needs it when the <Resource> is defined in server.xml.
Next, the META-INF/context.xml is a template that is used the first time your webapp is deployed. It gets copied to $CATALINA_BASE/conf/Catalina/localhost/myapp.xml, and is likely not updated/refreshed if you change META-INF/context.xml.
The .../Catalina/localhost/myapp.xml file should contain the <ResourceLink> element, mapping the name used by the webapp to the name used in server.xml. Keeping those two names the same is easiest, but not required.
Tomcat works fine without the <resource-ref> elements in WEB-INF/web.xml, but it's better if they are there, for compatibility with other Servlet containers.
Note: $CATALINA_BASE is usually the same as $CATALINA_HOME, i.e. the folder where Tomcat is installed, unless you explicitly configure it otherwise.
So, $CATALINA_BASE/conf/server.xml:
<?xml version='1.0' encoding='utf-8'?>
<Server ...>
...
<GlobalNamingResources>
...
<Resource name="jdbc/pool1" auth="Container" type="javax.sql.DataSource" ... />
<Resource name="jdbc/pool2" auth="Container" type="javax.sql.DataSource" ... />
...
</GlobalNamingResources>
...
</Server>
and $CATALINA_BASE/conf/Catalina/localhost/myapp.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<ResourceLink name="jdbc/pool1" global="jdbc/pool1" type="javax.sql.DataSource"/>
<ResourceLink name="jdbc/pool2" global="jdbc/pool2" type="javax.sql.DataSource"/>
</Context>
and place ojdbcXXX.jar in $CATALINA_BASE/lib.

connecting to derby database with tomcat as the server

How do i connect to derby database (that comes with the netbeans) ? I am using Tomcat as the server. Earlier i used the following statements to connect to the derby database,but then i used glassfish as the server.
Context context = new InitialContext();
DataSource ds = (DataSource)context.lookup("java:comp/env/jdbc/PollDatasource");
Connection connection = ds.getConnection();
But now using Tomcat as the server i am unaware how to do this.
Note : Tomcat and Derby are pre installed with netbeans IDE that i am using currently
In Tomcat find conf/context.xml, then edit and write something like this:
<Resource name="jdbc/PollDatasource" auth="Container" type="javax.sql.DataSource"
driverClassName="com.YourDriver"
url="jdbc:derby://localhost:1527/nameOfTheDatabase;create=true"
username="username" password="password" maxActive="20"
maxIdle="10" maxWait="-1" />
Note 1: With the above URL the driver will be org.apache.derby.jdbc.ClientDriver
Note 2 : You can also add the above information in META-INF/context.xml of your project. This becomes application specific.If you add the information in tomcat's context.xml that becomes global.
Note 3: Download the jar from this website.Download db-derby-10.9.1.0-bin.zip.It contains many files, including derby.jar and derbyclient.jar (along with much documentation).derbyclient.jar contains our friend org.apache.derby.jdbc.ClientDriver.class. derby.jar contains org.apache.derby.jdbc.EmbeddedDriver. Keep the downloaded jar in lib folder of Tomcat.
and in your application web.xml "resource-ref":
<resource-ref>
<description>my connection</description>
<res-ref-name>jdbc/PollDatasource</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
You may want to look at these questions :
Isn't it necessary to mention the name of archive in the Resource tag?
When is the tag I added in context.xml gets read?
What are steps followed in the look-up? what is looked first web.xml or context.xml?
You need to:
1) Copy your derbyclient-*.jar to ${TOMCAT_HOME}/lib.
2) Edit your server.xml and add the following lines to the section GlobalNamingResources:
<Resource auth="Container"
driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
maxActive="8" maxIdle="4"
name="jdbc/my-ds" type="javax.sql.DataSource"
url="jdbc:derby:mydb;create=true"
username="myuser" password="mypassword" />
3) In your context definition, add:
<Context docBase="myapp"
path="/myapp"
reloadable="true"
...>
<ResourceLink name="jdbc/my-ds"
global="jdbc/my-ds"
type="javax.sql.DataSource" />
</Context>
4) Restart Tomcat.
The example you have requires JNDI. See the relevant tomcat versions docs on setting that up.
Or use a connection string, here's a page from derby docs http://db.apache.org/derby/integrate/plugin_help/derby_app.html

How can I use Java console app and Hibernate using Tomcat Context?

I have some Java-console-apps. which are using Hibernate to take care some database stuff (I use MySQL). Now, I want Hibernate to use datasource from Tomcat Context. Could anyone tell me how?
Tomcat wiki contains the needed configuration.
in context.xml:
<?xml version="1.0" encoding="UTF-8"?> <Context antiJARLocking="true" path="/DVDStore">
<Resource auth="Container"
driverClassName="com.mysql.jdbc.Driver" maxActive="30" maxIdle="10" maxWait="10000" name="jdbc/sakila" password="*****"
type="javax.sql.DataSource" url="jdbc:mysql://localhost/sakila" username="*****"/>
</Context>
In WEB-INF/web.xml .
<resource-ref>
<description>This is a MySQL database connection</description>
<res-ref-name>jdbc/sakila</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
In hibernate.cfg.xml:
<!-- using container-managed JNDI -->
<propertyname="hibernate.connection.datasource">
java:comp/env/jdbc/sakila
</property>
You can find more in The TomcatHibernate Wiki
Edit:
In case you want to access the context directly, this is the way to do it problematically
ServletContext sc = getServletContext();
String parameterValue = sc.getInitParameter("parameterName");

tomcat oracle datasource

I have apache tomcat 5.5.28 on my windows box and I am trying to deploy a web application (WAR) which works fine on other servers.
However I am having trouble creating a datasource. I am not sure of the format. The db is oracle.
Here is what I have in server.xml.
<GlobalNamingResources>
<Environment
name="simpleValue"
type="java.lang.Integer"
value="30"/>
<Resource
name="tomdb11"
type="oracle.jdbc.pool.OracleDataSource"
maxActive="4"
maxIdle="2"
username="tomdb11"
maxWait="5000"
driverClassName="oracle.jdbc.driver.OracleDriver"
validationQuery="select * from dual"
password="remotedb11"
url="jdbc:oracle:thin:#dbserver:1521:orcl"/>
<Resource
auth="Container"
description="User database that can be updated and saved"
name="UserDatabase"
type="org.apache.catalina.UserDatabase"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml"/>
</GlobalNamingResources>
How do I access this in the web.xml where usually what I have which works in other servers is
<context-param>
<param-name>databaseUser</param-name>
<param-value>tomdb11</param-value>
</context-param>
<context-param>
<param-name>databasePassword</param-name>
<param-value>tomdb11</param-value>
</context-param>
<context-param>
<param-name>databaseSchema</param-name>
<param-value>TOMDBADMINN11</param-value>
</context-param>
Also am I missing something?
Edit: I get the following exception:
javax.naming.NameNotFoundException: Name tomdb11 is not bound in this Context
at org.apache.naming.NamingContext.lookup(NamingContext.java:770)
at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
at org.apache.naming.SelectorContext.lookup(SelectorContext.java:137)
at javax.naming.InitialContext.lookup(Unknown Source)
at com.taw.database.DatabaseService.<init>(DatabaseService.java:19)
at com.taw.database.DatabaseServices.init(DatabaseServices.java:40)
If exception tells that it cannot find jdbc in the JNDI context, then it roughly means that you tried to obtain the DataSource as follows
dataSource = new InitialContext().lookup("jdbc/tomdb11");
while your server.xml file tells the following:
<Resource
name="tomdb11"
>
Those names are not the same. In fact, you should have been used:
dataSource = new InitialContext().lookup("tomdb11");
In Tomcat, however, the InitialContext doesn't directly point to java:comp/env/, so you'll need to replace it by:
dataSource = new InitialContext().lookup("java:comp/env/tomdb11");
The normal practice, however, is that you specify JDBC datasources with the jdbc prefix. So I would rename the resource as
<Resource
name="jdbc/tomdb11"
>
and access it by
dataSource = new InitialContext().lookup("java:comp/env/jdbc/tomdb11");
In the webapp's web.xml you should however also have the following resource declaration:
<resource-env-ref>
<resource-env-ref-name>jdbc/tomdb11</resource-env-ref-name>
<resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
</resource-env-ref>
For more details about Tomcat JNDI check this HOWTO: http://tomcat.apache.org/tomcat-6.0-doc/jndi-resources-howto.html. Hope this helps.
First... Make sure you have an Oracle JDBC Jar in your $TOMCAT_HOME/common/lib.
Second... Make sure your web.xml also contains a block like this...
<resource-ref>
<description>Oracle Datasource</description>
<res-ref-name>tomdb11</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
</resource-ref>
As for your <context-param>, I'm not sure that is doing anything as you already have those things defined in your <Resource>.

PoolableConnectionFactory Invalid handle

I'm deploying an old app on a new box. When hitting the database for the first time I get
File input error: Cannot create PoolableConnectionFactory (Invalid handle)
I've set up my resource in context.xml, my dsn with unixODBC, and my resource-ref in web.xml. What else am I missing?
from content.xml -->
<Resource name="jdbc/MoleComp" auth="Container"
type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="-1"
removeAbandoned="false" removeAbandonedTimeout="60"
username="userName" password="passWord"
driverClassName="sun.jdbc.odbc.JdbcOdbcDriver"
url="jdbc:odbc:DSNName"/>
from app/WEB-INF/web.xml -->
<resource-ref>
<description>DB connection</description>
<res-ref-name>jdbc/MoleComp</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Thanks.
First, you should remove the <resource-def> from web.xml. This is just another way to define data source, which you've already done in context.xml.
That error is from ODBC-JDBC bridge driver. So either ODBC is not running or the url="jdbc:odbc:DSNName" is invalid.
After getting this problem on yet another server, I switched the application from using unixODBC and odbc.jdbc to java type 4 driver jTDS jtds.jdbc. Performance is a bit better too!

Categories

Resources