java - Tomcat 中的自定义 MBean - 创建 InitialContext 时找不到 javaURLContextFactory

标签 java tomcat classloader jmx classnotfound

我编写了一个部署在 Tomcat 6 中的自定义 MBean。它的任务之一是查询数据库值。我通过使用 JNDI 加载数据库资源来执行此操作 - 该资源在 Tomcat 的 server.xml 中定义。

问题是,当我创建 javax.naming.InitialContext 的实例时,它抛出一个 ClassNotFoundException,因为它找不到 org.apache.naming .java.javaURLContextFactory。 此类位于 catalina.jar 中,由通用类加载器加载。包含我的 MBean 代码的 jar 由共享类加载器加载。

关于如何解决这个问题有什么想法吗?

注意:我的 MBean 由我在 tomcat/conf/web.xml 中定义的 ContextListener 加载。我还在 webapp web.xml 中定义了它,这没有区别。我真的不能移动我的 jar 以便由公共(public)类加载器加载,因为它依赖于共享类加载器加载的类。

提前致谢

最佳答案

这看起来是一个奇怪的类加载或安全/权限问题。以下是解决方法。

主要思想:由于 ServletContextListener 可以在没有 ClassNotFoundException 的情况下调用 new InitialContext() 在监听器中获取它并将其传递给在注册 MBean 之前创建 MBean 对象的构造函数。我使用了一个简单的 Web 应用程序并且我没有修改 tomcat/conf/web.xml

tomcat/conf/context.xml中的资源配置:

<Context>
...
    <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
        maxActive="100" maxIdle="30" maxWait="10000"
        username="root" password="..." driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://localhost:3306/javatest?autoReconnect=true"/>
...
<Context>

web.xml资源配置:

<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>

注册 MBean 的 ServletContextListener:

import java.lang.management.ManagementFactory;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class ContextListener implements ServletContextListener {

    private ObjectName objectName;

    public void contextInitialized(final ServletContextEvent sce) {
        System.out.println("---> bean context listener started");

        final MBeanServer mbeanServer = 
            ManagementFactory.getPlatformMBeanServer();
        try {
            final InitialContext initialContext = new InitialContext();
            final Context envContext = 
                (Context) initialContext.lookup("java:/comp/env");

            objectName = new ObjectName("com.example:type=Hello");
            final Hello helloMbean = new Hello(envContext);
            mbeanServer.registerMBean(helloMbean, objectName);
            System.out.println("---> registerMBean ok");
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }

    public void contextDestroyed(final ServletContextEvent sce) {
        System.out.println("---> bean context listener destroyed");
        final MBeanServer mbeanServer = 
            ManagementFactory.getPlatformMBeanServer();
        try {
            mbeanServer.unregisterMBean(objectName);
            System.out.println("---> unregisterMBean ok");
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }
}

MBean 接口(interface):

public interface HelloMBean {
    void sayHello();
}

MBean 实现:

import java.sql.Connection;

import javax.naming.Context;
import javax.sql.DataSource;

public class Hello implements HelloMBean {

    private final Context envContext;

    public Hello(final Context envContext) {
        this.envContext = envContext;
        System.out.println("new hello " + envContext);
    }

    @Override
    public void sayHello() {
        System.out.println("sayHello()");

        try {
            final DataSource ds = 
                (DataSource) envContext.lookup("jdbc/TestDB");
            final Connection conn = ds.getConnection();
            System.out.println("   conn: " + conn);
            // more JDBC code
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }
}

MBean Descriptor How Tombeans-descriptor.xml 是必需的,但没有它也能正常工作。我可以使用 jconsole 连接到 HelloMBean。通过 jconsole 调用 sayHello() 打印以下内容:

conn: jdbc:mysql://localhost:3306/javatest?autoReconnect=true, \
UserName=root@localhost, MySQL-AB JDBC Driver

来源:

关于java - Tomcat 中的自定义 MBean - 创建 InitialContext 时找不到 javaURLContextFactory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7571160/

相关文章:

groovy - 在 Websphere 上的 Groovy 中加载外部 jar

java - 类似于Knapsack Java代码的动态规划算法

java - 在 Jenkins 中找不到 Spark-version-info.properties

src的Java其他目录

tomcat - 安全站点上的 RichFaces

自定义类加载器的 JSP 编译错误

java - Java 解释器是否将字节码文件转换为可执行文件?

java - Tomcat 7 TagLib 和用户问题

java - ServletContextListener 是否调用每次机器重启时调用的方法

java - 异常初始化器