3

Tomcat 6にデプロイするカスタムMBeanを作成しました。そのタスクの1つは、データベース値を照会することです。これを行うには、JNDIを使用してデータベースリソースをロードします。リソースはTomcatのserver.xmlで定義されています。

問題は、インスタンスを作成すると、が見つからないためにがjavax.naming.InitialContextスローされることです。このクラスは、共通のクラスローダーにあり、ロードされます。MBeanコードを含むjarは、共有クラスローダーによってロードされます。ClassNotFoundExceptionorg.apache.naming.java.javaURLContextFactorycatalina.jar

これを回避する方法について何かアイデアはありますか?

注:私のMBeanは、で定義したContextListenerによってロードされtomcat/conf/web.xmlます。web.xmlまた、違いがないWebアプリで定義しました。共有クラスローダーによってロードされるクラスに依存しているため、共通クラスローダーによってロードされるようにjarを実際に移動することはできません。

前もって感謝します、

意思

4

1 に答える 1

6

奇妙なクラスローディングまたはセキュリティ/許可の問題に見えます。以下は回避策です。

主なアイデア: MBean を登録する前に、リスナーで get it を使用せずにServletContextListenerを呼び出し、MBean オブジェクトのコンストラクターに渡すことができるためです。私は単純な Web アプリケーションを使用しましたが、変更はしていません。new InitialContext()ClassNotFoundExceptiontomcat/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>

ServletContextListenerMBean を登録する:

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 インターフェース:

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 To には aが必要であると書かれてmbeans-descriptor.xmlいますが、それがなくてもうまく機能します。で HelloMBean に接続できましたjconsolesayHello()次の出力を介して呼び出しjconsoleます。

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

ソース:

于 2011-10-02T23:12:04.947 に答える