11
votes

I know there's many questions regarding this exception, however, I believe I've tried everything for many days, without any luck yet. As this is a production server, I can only work on this after midnight :(

I have a Tomcat app. Recently, I've updated the connection pool, in order to use Tomcat's jdbc-connection pool. In my Windows developing machine, everything works fine, but now that I'm trying to implement this on my Linux Server, I get this exception (see title) when ever my app tries to connect to MySQL.

I'm using "Easy Tomcat 7" which is supposed to be the same as the regular version of Tomcat, only it comes with the CPanel software.

I just need this DB to be available for this app (not multiple app's).

This is my java DB class:

public class DBUtil {

static DataSource ds;
static {
    try {
        Context context = new InitialContext();
        ds = (DataSource)context.lookup("java:comp/env/jdbc/rhwebDB");
    } catch (NamingException e) {
        e.printStackTrace();
        System.out.println("DBUtil.NamingException" + e);
    } catch(Exception e) {
        System.out.println(e);
    }
}

public static Connection getConnection() throws SQLException {
    return ds.getConnection();
}

This is my context.xml file, which is located on myAppDirectory/META-INF

<?xml version="1.0" encoding="UTF-8"?>

<Context>
<Resource
    name="jdbc/rhwebDB"
    auth="Container"
    type="javax.sql.DataSource"
    factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
    testWhileIdle="true"
    testOnBorrow="true"
    testOnReturn="false"
    validationQuery="SELECT 1"
    validationInterval="30000"
    timeBetweenEvictionRunsMillis="30000"
    maxActive="20"
    minIdle="3"
    maxIdle="15"
    maxWait="10000"
    initialSize="3"
    removeAbandonedTimeout="60"
    removeAbandoned="true"
    logAbandoned="true"
    minEvictableIdleTimeMillis="30000"
    username="dbuser"
    password="dbpwd"
    driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://127.0.0.1:3306/rhmexweb_rhweb"/>
</Context>

I don't use WAR files. I just upload files to my server and re-start tomcat when needed, which normally works just fine.

In case this is relevant too, Tomcat's server.xml file has this settings for this website. I've also tried adding parameter copyXML="true", with no luck so far:

       <Host name="rhweb.net" appBase="webapps">
       <Alias>www.rhweb.net</Alias>
       <Context path="" reloadable="false" docBase="/home/rhweb/public_html" debug="1"/>
       </Host>

Here's the full stacktrace I get when my app tries to establish a connection with MySQL:

javax.naming.NameNotFoundException: Name [jdbc/rhwebDB] is not bound in this Context. Unable to find [jdbc].
    at org.apache.naming.NamingContext.lookup(NamingContext.java:820)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:154)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:831)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:154)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:831)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:168)
    at org.apache.naming.SelectorContext.lookup(SelectorContext.java:158)
    at javax.naming.InitialContext.lookup(InitialContext.java:415)
    at util.DBUtil.<clinit>(DBUtil.java:23)
    at Solutio.AdminRH.Entity.ISeguridadAdminDB.verificaUsuario(ISeguridadAdminDB.java:142)
    at org.apache.jsp.menu_jsp._jspService(menu_jsp.java:115)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:200)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

I've also tried adding these lines in my app's web.xml file (which I hadn't had to include in my windows machine)

   <resource-ref>
       <description>MySQL RhWeb Datasource</description>
       <res-ref-name>jdbc/rhwebDB</res-ref-name>
       <res-type>javax.sql.DataSource</res-type>
       <res-auth>Container</res-auth>
   </resource-ref>

And when I include those lines, the exception I get is this one:

org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null'

It seems that Tomcat can't find my META-INF/context.xml file, or it doesn't recognize this link:

ds = (DataSource)context.lookup("java:comp/env/jdbc/rhwebDB");

My linux, Tomcat and JDK versions are:

CentOS release 6.8 (Final)
Apache Tomcat/7.0.42
java version "1.7.0_131"

I don't know what else can I try to fix this. Any help will be really appreciated

UPDATE

I still haven't found a solution yet. I've realized some probable configuration issues that may be related to all this:

The app is located here:

/home/rhmexweb/public_html

However, on the Tomcat's server.xml file the host definition for this website is:

<Host name="rhweb.mx" appBase="webapps">
<Context path="" reloadable="false" docBase="/home/rhmexweb/public_html" />
</Host>

The reason why is not located on the webapps directory, is because CPanel automatically creates every account in /home/account-name/public_html, so that's why a context element is needed here (I guess). If I remove the whole Context tag, and instead I use appBase="/home/rhmexweb/public_html", then Tomcat won't find all the jars and content from the WEB-INF folder (/home/rhmexweb/public_html/WEB-INF). I mentioned this because I added the parameter copyXML="true" just to see where would tomcat tries to copy context.xml file, and if it changes it's name, but it turns out that there are two different paths. First I got a writing permissions exception when I first include that parameter, and it was trying to create a folder here:

/var/lib/easy-tomcat7/webapps/

This path, only contains folders of the default tomcat app's (manager, examples & host-manager)

The folder where all the websites are listed and all the compiled jsp files are is this one:

/usr/local/easy/etc/easy-tomcat7/Catalina/

however, in /usr/local/easy/etc/easy-tomcat7/Catalina/rhweb.mx/ there is no WEB-INF directory.

Anyway, what I'd like to know is if having a Context element in the host definition might be a problem for Tomcat in order to find the appPath/META-INF/context.xml file.

2
Please post the full exception stack trace.Mark Rotteveel
that's was the only exception stack trace since the Exception was handled inside a "try catch". I can mofify the code in order to get the full stack trace, however, I'll have to do it after midnight since this is a production server.Sergio
After some changes I've made, now the exception I'm getting is this one: DBUtil.NamingException - javax.naming.NameNotFoundException: Name [rhwebDB] is not bound in this Context. Unable to find [rhwebDB]. Should I put this on a new question?? By the way, the exception I was getting last night was because I tried to use JDK 1.8 with Tomcat 7. Then I read they weren't compatible, so now I'm using JDK 1.7Sergio
Your question doesn't contain the full stacktrace, just the error message. In any case. Maybe change the name of the resource to jdbc/rhwebDB (I'm not sure if jdbc/ is required, but all examples contain it), and change the JDNI lookup accordingly. Also checkout tomcat.apache.org/tomcat-7.0-doc/…Mark Rotteveel
Comments are not really suitable for code, in any case, you need to use e.printStackTrace() to get the full stack trace (or an actual logging framework that does it for you). The toString() only shows the exception name + message.Mark Rotteveel

2 Answers

7
votes

It looks like there is something wrong with the context.xml setup. Try server.xml or /META-INF/context.xml to see if it behaves any different.

You can try moving the configuration to the server.xml as per Tomcat 7 docs:

<GlobalNamingResources>
  <Resource
    name="jdbc/rhweb_rhwebDB"
    auth="Container"
    type="javax.sql.DataSource"
    ...
  />
</GlobalNamingResources>

link to global resource in the context.xml:

<Context>
  <ResourceLink
    global="jdbc/rhweb_rhwebDB"
    name="jdbc/rhwebDB"
    type="javax.sql.DataSource"
  />
</Context>

and then refer to it in /WEB-INF/web.xml like you already do:

<resource-ref>
  <res-ref-name>jdbc/rhwebDB</res-ref-name>
  <res-ref-type>javax.sql.DataSource</res-ref-type>
  <res-auth>Container</res-auth>
</resource-ref>

If this won't work you can check few other approaches discussed in this answer.

3
votes

I finally solved it!!

Maybe it's a workaround but it works.

I copied the app-directory/META-INF/context.xml file to:

$CATALINA_BASE/conf/[enginename]/[hostname]/context.xml.default (notice the "default" part of the filename)

As it's stated in the Tomcat's documentation

Now I don't need to add any entry in my app's web.xml file, neither a META-INF/context.xml file in my app directory (which is not located on the Tomcat's/webapps directory)

All I need is to put a context.xml.default file (containing it's DB information) in every folder listed in this path:

$CATALINA_BASE/conf/[enginename]/

which in my server is:

/usr/local/easy/etc/easy-tomcat7/Catalina/

so for this website, I copied it to:

/usr/local/easy/etc/easy-tomcat7/Catalina/myDomain.com/

You'll notice my path is different from the one specified in Tomcat's documentation, and that's because I'm using CPanel's easy-tomcat 7 which has a different structure than the regular Tomcat. That fact made everything more complicated when looking for a solution, even if it's called easy-tomcat.

About why Tomcat could never read the /META-INF/context.xml, that remains a mistery, but honestly, I don't care much since this method it's easier (one file instead of two)