4

javax.mail.Sessions インスタンスを作成する、Tomcat 6.0 が提供する標準のリソース ファクトリを使用したいと考えています。JNDI リソースの HOW-TO チュートリアル で説明されているとおりです。

私の META-INF/context.xml は次のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<Context reloadable="true">
    <Resource name="mail/Session" 
          auth="Container" 
          type="javax.mail.Session" 
          mail.smtp.host="smtp.gmail.com"
          mail.smtp.port="587"
          mail.smtp.auth="true"
          mail.smtp.user="someone@gmail.com"
          mail.smtp.password="secretpassword" 
          mail.smtp.starttls.enable="true"/>    
</Context>

WEB-INF/web.xml の </webapps> の直前に、次の resource-ref があります。Web.xml が検証します。McDowell の方法を使用して検証しました。

<resource-ref>
    <description>Resource reference to a factory for javax.mail.Session instances that may be used for sending electronic mail messages, preconfigured
    to connect to the appropiate SMTP server.
    </description>
    <res-ref-name>mail/Session</res-ref-name>
    <res-type>javax.mail.Session</res-type>
    <res-auth>Container</res-auth>
    </resource-ref>

次のコード スニペットを使用して、javax.mail.Session オブジェクトにアクセスします。

Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
Session session = (Session)envCtx.lookup("mail/Session");
System.out.println("HERE smtp.user: " + session.getProperty("mail.smtp.user"));

サンプルアプリでテストしたところ、うまくいきました。残念ながら、同じコードを Struts アプリケーションに移動すると、上記の print ステートメントで NULL が返されます。mailer というシングルトン クラス (WEB-INF/classes フォルダーで定義されています) でコンテキスト ルックアップを行いますが、Struts アクション クラスでコンテキスト ルックアップを行うと同じ問題が発生します。

問題を見つけるために何が違うのかを考えてきました。私の struts アプリケーションの web.xml は、単純なアプリケーションの web.xml よりも複雑です。これには、セキュリティ制約、フィルター、および Struts サーブレット構成があります。サーブレット定義の直前に resource-ref を配置します。resource-ref が無視されているようです。

別の問題があります。javax.mail.Session に必要な mailapi.jar が myapp/WEB-INF/lib フォルダーにある場合、次のようになります。

java.lang.NoClassDefFoundError: javax/mail/Authenticator

$CATALINA_HOME/lib に入れると見つかります。

何か案は?ストラットと休止状態を使用します。多分それはそれと関係があります。

デバッグ

デバッグ属性をコンテキストに入れてデバッグしようとしました

<Context reloadable="true" debug="99" ...  

しかし、私は面白いものを見ません。

01-feb-2009 17:39:09 org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextInitialized()
01-feb-2009 17:39:09 org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextInitialized()
01-feb-2009 17:39:09 org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextInitialized()
01-feb-2009 17:39:09 org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextInitialized()
01-feb-2009 17:39:09 org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextInitialized()
01-feb-2009 17:39:09 org.apache.catalina.core.ApplicationContext log

私は試した:

Session session = (Session) initCtx.lookup("java:comp/env/mail/Session");

それ以外の:

Context envCtx = (Context) initCtx.lookup("java:comp/env");
Session session = (Session)envCtx.lookup("mail/Session");

しかし、まだ NULL Session オブジェクトを取得しています。

部分解

Resource 要素を $CATALINA_HOME/conf/context.xml ファイル内に配置すると、機能します。

4

4 に答える 4

6

JNDIルックアップコードの癖

JNDIリソースが見つからないという問題が複数あります。Websphereでは(私は知っています、あなたはそれを使用しませんが、知っておくのは良いことです...)あなたは問題を抱えることになります

コンテキストenvCtx=(コンテキスト)initCtx.lookup( "java:comp / env");
セッションsession=(Session)envCtx.lookup( "mail / Session");

(Websphereで)機能するのは

セッションsession=(Session)initCtx.lookup( "java:comp / env / mail / Session");

あなたが別の回答で書いたことから、これはあなたの問題ではないことを理解しています-後で異なる状況で同じ問題に遭遇する人々のためにここに残しておきます。

自己生成スレッドからのJNDIリソースのルックアップ

また、JNDIリソースへのアクセスは、リソースを検索するスレッドに依存する場合があります。私が覚えている限り、スレッド化はサーブレットAPI(またはJava EEまたは関連領域。自発的かつ明示的に定義されていない場合もあります)では十分に定義されていません。したがって、サーバーがスレッドでJNDIリソースを提供することは必須ではありません。あなたは自分自身を生み出しました(Websphereはこれで私を噛みました、私はこの点でTomcat6をテストしていません、以前のバージョンはすべてのスレッドにJNDIリソースを提供するために使用されました)

シングルトンからJNDIリソースを検索していると書いています。リソースを検索する時点で、スタックトレースを調べます(IDEで、例外をスローするか、いじりますThread.currentThread().getStacktrace()):スタックトレースにTomcatコネクタがあるか、またはスレッドのrun()メソッドの1つです。スタックトレースのルートこれは、Actionクラスからルックアップを行う場合、Jacksの質問の背後にある質問に答えます。(ジャックの答えを参照)

スレッドと呼び出し環境パート2

新しいStrutsアクションを作成し、そこからJNDIルックアップコードを呼び出します。これがStrutsの近くに配置され、httpリクエストの処理内にある場合に機能するかどうかを確認します。ここで機能する場合は、上記の手順に進みます。

web.xmlの有効性

また、web.xmlのスキーマ定義を調べて、resource-refが正しく配置されていることを確認することもできます。サーブレット仕様2.4はjcp.orgで入手可能であり、tomcatが2.5を実装している場合でも、チェックするには十分なはずです。

結局のところ、tomcat6はweb.xmlを検証するので、おそらくすでに正しい位置にあると思います。(IDEエディターが間違っていると文句を言うので、web.xmlを作成する必要があるかどうか思い出せません)

Tomcatデバッグオプション

多くのcontext.xmlエントリは、属性'debug'を尊重します。1桁の低い値で十分だと思いますが、「Context」などの要素に「debug="99"」を追加する習慣を採用しています。これにより、役立つログエントリが生成されるかどうかを確認することをお勧めします。

クラスパスではないことを確認してください

環境を根本的に変えたように見えるので、必要なライブラリがすべて搭載されていることを確認してください。メールAPIはいくつかのjarファイルで構成されています。新しいコピーをダウンロードし、すべてのライブラリを$ CATALINA_HOME/libに解凍します。そこにあるすべてのライブラリで機能すると、未使用のものを取り除くことができます。

クラスパスの質問について

$ CATALINA_HOME / libに配置されたときにクラスが見つかる理由は、接続がサーバーによって行われるためです(アプリケーションを起動するためにサーバーによって読み取られるcontext.xmlで定義したことを忘れないでください)。 jarは、アプリケーションだけでなく、サーバーのクラスパス上にある必要があります(詳細については、tomcatクラスローダーHOWTOを参照してください)。

編集:

あなたの部分的な解決策について

$ CATALINA_HOME / conf / context.xmlには、グローバルな「デフォルト」コンテキスト要素が含まれています。これは、アプリケーション固有の構成が必要な場所ではありません。

tomcatの標準の位置は、webapps META-INF / context.xmlか、$ CATALINA_HOME / conf / Catalina / localhost /のxmlファイル(任意の名前で、.xmlで終わる)にあります。後者のソリューションは、META-INF / context.xmlに関して実際に優先されます。これは、この方法では、構成がアプリケーションから独立しており、新しいアプリケーションがデプロイされたときに上書きされないためです。

このコンテキストには通常、docBaseやpathなどの追加の属性が含まれています。

<Context docBase="/location/where/you/deployed/your/application" path="/app">
  ...
</Context>

このようにして、アプリケーションはで利用できますhttp://servername:8080/app。$ CATALINA_HOME / webappsディレクトリにデプロイする場合、docBase値はwebappに相対的である可能性があります。ただし、競合状態には注意してください。Tomcatはアプリケーションを$ CATALINA_HOME / webappsに自動デプロイし、コンテキストファイルを作成する場合があります。また、新しいWebアプリケーションをデプロイするためにWebアプリケーションを削除すると、Tomcatがxml構成ファイルを削除する可能性があります。

そのため、問題が何であれ、コンテキスト定義/アプリケーションが$ CATALINA_HOME / conf / Catalina / localhost/app.xmlに配置されたときに機能するかどうかを試してください。それは非常に単純なことであり、実際の問題を確認するために最後の情報だけが欠落しているような気がします。

于 2009-02-01T16:08:04.260 に答える
1

そして、あなたは何をお勧めしますか?

JNDI で定義しますが、Web アプリケーション/WAR の外部で定義します。Tomcat では、これを ${CATALINA_BASE}/conf/context.xml ファイルに入れることで実行できます。これにより、外部リソース (メール、データベースなど) の構成を Web アプリケーションの外部で定義できるようになり、たとえば、データベースの構成を変更したり、別のデータベースを使用して別の環境に移動したりするときに、WAR を再パッケージ化する必要がなくなります。

メーラーと呼ばれるシングルトンクラスでコンテキストルックアップを行います。

このメーラー クラスは WEB-INF/classes にありますか、それとも WEB-INF/lib 内の JAR ですか? または、クラスパスの他の場所で定義されていますか? 後者の場合は、アプリケーションに移動することを検討してください。


編集: 最新の調査結果に基づいて、Web アプリの META-INF/context.xml が有効になっていないようです。Tomcat には、これにつながるシナリオがいくつかあります。詳しいことはわかりませんが、以下のような情報が得られました。

あたり - http://tomcat.apache.org/tomcat-5.5-doc/config/host.html

Host要素で「deployXML」属性がfalseに設定されている場合(私はserver.xmlを信じています)。

deployXML - アプリケーション内に埋め込まれた context.xml ファイル (/META-INF/context.xml にあります) の解析を無効にする場合は、false に設定します。セキュリティを意識した環境では、アプリケーションがコンテナーの構成と対話するのを防ぐために、これを false に設定する必要があります。管理者は、外部コンテキスト構成ファイルを提供し、それを $CATALINA_HOME/conf/[enginename]/[hostname]/ に配置する責任があります。フラグの値のデフォルトは true です。

あたり - http://tomcat.apache.org/tomcat-5.5-doc/config/context.html

$CATALINA_HOME/conf/[enginename]/[hostname]/[context-path].xml ファイルが定義されている場合。

他にもあると思いますが、これらは私がすぐに見つけることができたものです。

于 2009-02-03T05:40:01.063 に答える
1

META-INF/web.xml ではなく META-INF/context.xml でコンテキストを定義する必要があると思います (ただし、これは元の投稿のタイプミスである可能性があります)。

コードを Struts アプリケーションに移行したとおっしゃいましたが、具体的に教えていただけますか? 今、Action クラスでコンテキスト ルックアップを行っているということですか?

また、すでにご存じかもしれませんが、Web アプリでコンテキスト (JNDI エントリなど) を定義する META-INF/context.xml は開発者の環境では受け入れられますが、共有環境のあらゆる形式で使用することは強くお勧めしません。本番環境ではありません。

于 2009-02-01T17:21:12.413 に答える