6

Heloマスター、JNDIデータソースを動的に作成する必要があります。SetupApplicationListenerというリスナーを使用して作成しようとしました。これがの始まりですWEB-LIB/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee">

    <display-name>pri-web</display-name>

    <!-- Listeners -->
    <listener>
        <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
    </listener>
    <listener>
        <listener-class>myapp.SetupApplicationListener</listener-class>
    </listener>

リスナーのコード:

public class SetupApplicationListener implements ServletContextListener {

    public static Log LOG = null;

    public void contextInitialized(ServletContextEvent ctx){
        try {            
            createOracleDataSource();
.....
        }
    }

    private void createOracleDataSource() throws SQLException, NamingException {
        OracleDataSource ds = new OracleDataSource();
        ds.setDriverType(...);
        ds.setServerName(...);
        ds.setPortNumber(...);
        ds.setDatabaseName(...);
        ds.setUser(...);
        ds.setPassword(...);

        new InitialContext().bind("java:comp/env/jdbc/myDS", ds);
    }

.....
}

そして、エラーがあります:

[ERROR] 29/01/2013 09:44:50,517 (SetupApplicationListener.java:86) -> Error
javax.naming.NamingException: Context is read only
    at org.apache.naming.NamingContext.checkWritable(NamingContext.java:903)
    at org.apache.naming.NamingContext.bind(NamingContext.java:831)
    at org.apache.naming.NamingContext.bind(NamingContext.java:171)
    at org.apache.naming.NamingContext.bind(NamingContext.java:187)
    at org.apache.naming.SelectorContext.bind(SelectorContext.java:186)
    at javax.naming.InitialContext.bind(InitialContext.java:359)
    at myapp.SetupApplicationListener.createOracleDataSource(SetupApplicationListener.java:102)

コンテキストの読み取り専用プロパティを「true」に設定できますか?ありがとう!:)

Tomcat 6.0
Oracle 11g
jdk1.5

編集:動的である必要はありません。jndiデータソースを内部で定義する必要があります。共有サーバーであるため、サーバーファイルを変更できません。他のモジュールがそのように使用するため、jndiである必要があります。

4

7 に答える 7

4

データソースを動的に作成する必要がある場合、JNDIルックアップは本当に必要ですか?JNDIは、アプリケーションの外部で接続を確立するように設計されていますが、シナリオでは、正当な要件のためにアプリケーションと緊密に結合されています。JDBC接続を使用しないのはなぜですか?

于 2013-01-29T10:18:35.467 に答える
4

ServletContextListenerを作成する必要があり、そこでInitialContextを書き込み可能にすることができます。これは、実行すべき方法ではありませんが、本当に必要な場合は、これを実行できる1つの方法です。

これはJavaMelodyでも機能します。

protected void makeJNDIContextWritable(ServletContextEvent sce) {
    try {
        Class<?> contextAccessControllerClass = sce.getClass().getClassLoader().loadClass("org.apache.naming.ContextAccessController");
        Field readOnlyContextsField = contextAccessControllerClass.getDeclaredField("readOnlyContexts");
        readOnlyContextsField.setAccessible(true);
        Hashtable readOnlyContexts = (Hashtable) readOnlyContextsField.get(null);
        String context = null;
        for (Object key : readOnlyContexts.keySet()) {
            String keyString = key + "";
            if (keyString.endsWith(sce.getServletContext().getContextPath())) {
                context = keyString;
            }
        }
        readOnlyContexts.remove(context);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}
于 2016-03-22T10:59:50.283 に答える
2

私は通常、アプリケーションサーバー(tomcat、weblogicなど)でJNDIを定義していたので、これまでこの問題は発生していません。Kevinが言ったように、これはまさにJNDIが設計された目的です。データソース構成をソースコードから分離し、ルックアップとインジェクトを介してJNDIリソースを取得します。

質問に戻りますが、Tomcatには、実行時にJNDIを変更するためのすべての厳密なルールがあると思います。つまり、コンテキストからjndiを再バインドまたは削除することはできません。tomcatの仕様を確認すると、おそらくjndiルックアップについて何かがわかりますが、再バインドは行われません。

于 2013-01-29T10:27:25.280 に答える
2

EE 6プラットフォーム仕様(JSR 316)のセクションEE.5.3.4から:

コンテナは、アプリケーションコンポーネントインスタンスがネーミングコンテキストへの読み取りアクセスのみを持つようにする必要があります。コンテナは、環境のネーミングコンテキストとそのサブコンテキストを変更するjavax.naming.Contextインターフェースのすべてのメソッドからjavax.naming.OperationNotSupportedExceptionをスローする必要があります。

このセクションの「それらの命名コンテキスト」はを参照していることに注意してくださいjava:comp

于 2013-01-29T16:23:25.047 に答える
0

environmentContextオブジェクトを閉じていることがわかったときに、この問題を解決しました。次に例を示します。

Context context=new InitialContext();
Context environmentContext=(Context) context.lookup("java:comp/env");

そして私のコードは:

environmentContext.close();

environmentContextからclose関数を削除した後、問題が販売されました。

于 2015-11-21T19:30:26.457 に答える
0

私もこの問題を抱えていましたが、トミーに慣れていないので、簡単な解決策があることを知りませんでした。Webアプリをwebappsフォルダーにデプロイすると、アプリは正常に機能しましたが、サービスフォルダーにデプロイすると、同じアボートが発生しました。問題は、フォルダー名がwar名(.warを除く)と一致しなかったことです。それを修正すると、アプリは正常に動作しました。ウォー名、フォルダー名、サービス名が同じであることを確認してください。この問題により、コンテキストの読み取り専用やJavaEEJNDIエントリのマージエラーなどのいくつかの異なるエラーが発生します。

于 2017-12-08T20:35:35.303 に答える
0

useNaming="false"context.xmlに設定することで、この問題を解決しました。

ドキュメントから

useNaming:true(デフォルト)に設定すると、Catalinaは、Java2 Enterprise Edition(J2EE)プラットフォームの規則と互換性のあるこのWebアプリケーションのJNDIInitialContextを有効にします。

于 2018-07-25T12:05:41.797 に答える