javatomcatconnection-poolingapache-commons-dbcpjdbc-pool

java.lang.ClassCastException: org.apache.commons.dbcp.BasicDataSource cannot be cast to org.apache.commons.dbcp.BasicDataSource


I'm getting this weird Exception while trying to retrieve a DataSource configured under Tomcat Global resources.

java.lang.ClassCastException: org.apache.commons.dbcp.BasicDataSource cannot be cast to org.apache.commons.dbcp.BasicDataSource
    org.apache.jsp.Monitor_jsp._jspService(Monitor_jsp.java:53)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:133)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:311)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:301)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:248)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:856)

This is how my Monitor.jsp looks like

<%@ page import="org.apache.commons.dbcp.BasicDataSource" %>
<%@ page import="com.dixons.myapp.db.DataSourceHelper" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Monitor page</title>
</head>
<body>
<%
    BasicDataSource ds = (BasicDataSource) DataSourceHelper.getDbDataSource();
    out.println(ds.getNumActive() + " " + ds.getNumIdle());
%>
</body>
</html>

I know what a ClassCastException is. But I could not understand why Java considers these two classes as different even though they are of same name and are in same package?

My application works just fine with the object Cast to javax.sql.DataSource. But I want to convert it as a org.apache.commons.dbcp.BasicDataSource for this monitor page so that I can keep an Eye on my DB resources.


Solution

  • This is because the same class is loaded by two different class loaders.

    One could be WebappClassLoader loader and another by sun.misc.Launcher$AppClassLoader. More detail can be found here