- PR -

メール送信時に java.lang.NoClassDefFoundError

1
投稿者投稿内容
兵庫在住
会議室デビュー日: 2007/04/16
投稿数: 3
投稿日時: 2007-04-16 19:03
2年ほどプログラマとして WEB開発 (JSP・Servlet) に携わっております。
よろしくお願い致します。


mail.jar の version を1.1.3から1.3.3へ入れ替え、メールが正しく送信できるか確認をしておりました。

JSP 画面の操作 (ボタン押下) によるメール送信は確認できるのですが、ant exec でメール送信しようとすると java.lang.NoClassDefFoundError が出てしまいます。
--------------------------------
<LOG>
[java] Exception in thread "P=445566:O=0:CT" java.lang.NoClassDefFoundError: com/sun/mail/util/MailDateFormat
[java] at common.MailUtils.sendMail(MailUtils.java(Compiled Code))
[java] at common.MailUtils.sendBatchMail(MailUtils.java(Compiled Code))
[java] at main.Test1.updateBase(Test1.java(Compiled Code))
[java] at main.Test1.checkBothData(Test1.java(Compiled Code))
[java] at main.Test1.main(Test1.java(Compiled Code))
--------------------------------

私なりに調べたところ、
mail.jar(1.1.3) の MailDateFormat.classはcom/sun/mail/util/ にありますが、
mail.jar(1.3.3) の MailDateFormat.classはcom/sun/mail/util/ ではなく
別の場所にあることが分かりました。

shell ファイルを作成し、実行してみたところ、正しくメール送信できます。
-----------------------------------------------------
<shell 内容>
# /bin/sh
/usr/WebSphere/AppServer/java/bin/java -classpath 〜 クラス名
-----------------------------------------------------

なぜ JSP 画面からの操作・shell 実行では正しくメール送信でき、
ant exec では NoClassDefFoundError が出てしまうのでしょうか・・。
mail.jar(1.1.3) 使用時には、いずれも正しくメール送信できておりました。


ご存知の方いらっしゃいましたら、ご教示ください。


*環境*
WebSphere4.0
J2RE-1.3.1

WebSphere/AppServer/java/jre/lib/extにmail.jar、activation.jar ともにあり、
ant exec 時もパスが通っているのを確認しています。


[ メッセージ編集済み 編集者: 兵庫在住 編集日時 2007-04-16 19:10 ]

[ メッセージ編集済み 編集者: 兵庫在住 編集日時 2007-04-16 19:13 ]
Java僧
ぬし
会議室デビュー日: 2003/11/06
投稿数: 261
投稿日時: 2007-04-17 08:45
肝心な build.xml が無いので、「ant exec 時もパスが通っている」のは信じるとして。

jre/lib/ext にある jar ファイルは明示的にクラスパスに含めなくてもよいはずですが、
「/usr/WebSphere/AppServer/java/bin/java -classpath 〜」で省略した「〜」の部分(ここが重要です)は何を指定していますか?
また、環境変数 CLASSPATH はどうなっていますか?(これはたぶん重要ではない)

common.MailUtils.sendMail の該当部分のソースコードも載せたほうがよいかも。
兵庫在住
会議室デビュー日: 2007/04/16
投稿数: 3
投稿日時: 2007-04-17 10:02
Java僧さん、ありがとうございます。

>肝心な build.xml が無いので、「ant exec 時もパスが通っている」のは信じるとして。

build.xml ではこのように定義しております。
------------------------------
<build.xml>
   〜
   <property file="build.properties"/>
   <property environment="env"/>

     <path id="classpath">
     <pathelement path="${java.classpath}" />
     <pathelement path="${javac.destdir}" />
       <fileset dir="test1.war/WEB-INF/lib">
         <include name="*.jar"/>
       </fileset>
       <fileset dir="${env.WAS_HOME}/lib">
         <include name="*.jar"/>
       </fileset>
       <fileset dir="${env.WAS_HOME}/java/jre/lib/ext">
         <include name="*.jar"/>
       </fileset>
     </path>
     〜
     <target name="exec" depends="compile.all">
       <java classname="${EXEC}" fork="yes">
         <arg line="${EXEC_ARGS}" />
         <classpath refid="classpath"/>
       </java>
     </target>
-----------------------------

>jre/lib/ext にある jar ファイルは明示的にクラスパスに含めなくてもよいはずですが、
>「/usr/WebSphere/AppServer/java/bin/java -classpath 〜」で省略した「〜」の部分
>(ここが重要です)は何を指定していますか?

log4j-1.2.4.jar
postgresql.jar
websphere.jar
j2ee.jar

を指定しております。
jre/lib/ext にある jar ファイルは指定しておりません。
(ここでは mail.jar、activation.jar はクラスパスに含めておりません。)

>また、環境変数 CLASSPATH はどうなっていますか?(これはたぶん重要ではない)

WAS_HOME=/usr/WebSphere/AppServer
ANT_HOME=/usr/local/jakarta-ant-1.4
JAVA_HOME=/usr/java130

を設定しております。

>common.MailUtils.sendMail の該当部分のソースコードも載せたほうがよいかも。

このメソッドでエラーが出ているのは分かるのですが、どの箇所が問題なのかは
分かっておりません・・。メソッドのソースコードを載せます。
-----------------------------
     /**
      * メールの送信を行う。
      */
     public static boolean sendMail(
          String aFrom
          , String aTo
          , String aSubject
          , String aMessage
     ) {
        try {
            MimeMessage msg = new MimeMessage(session);
            msg.setFrom(new InternetAddress(aFrom));
            msg.setRecipient(Message.RecipientType.TO
                      , new InternetAddress(aTo));
            msg.setHeader("Content-Type", "text/plain");
            msg.setHeader("Errors-To", Constant.getErrorAddress());
            if (Constant.getFrom().equals(aFrom)) {
              InternetAddress[] address = {new InternetAddress(Constant.getReplyAddress())};
              msg.setReplyTo(address);
            } else {
              InternetAddress[] address = {new InternetAddress(aFrom)};
              msg.setReplyTo(address);
            }
            msg.setSubject(convertString(aSubject), "iso-2022-jp");
            msg.setText(convertString(aMessage), "iso-2022-jp");
            msg.setSentDate(new Date());
            Transport.send(msg);
         } catch (Exception e) {
           logger.fatal("sendMail Error." + ExceptionUtil.getStackTrace(e));
           return false;
         }
         return true;
     }
------------------------------------

よろしくお願い致します。
zilloll
常連さん
会議室デビュー日: 2006/02/01
投稿数: 24
投稿日時: 2007-04-19 13:49
こんにちは
ANTの設定は理解していないので、設定が正しいかはわかりませんが、
プログラムを実行した際に、実行時バージョンのmail.jarにない
com.sun.mail.util.MailDateFormatでエラーに
なるということは、実行classファイルにこのクラスを使用するコードが
含まれてしまっているということだと思いますが、メール送信処理のソースを
mail.jar(1.3.1)でビルドしなおしてもエラーになるでしょうか。

なんとなく、MailDateFormatが指定の場所に存在していないのに、
JSP側で使用できているというほうがおかしいように思います。
想像ですが、mail.jar(1.1.3)にもクラスパスが通っていて
そちらが先に見つかっているために優先されて1.1.3が使用されている
ということは無いでしょうか。
兵庫在住
会議室デビュー日: 2007/04/16
投稿数: 3
投稿日時: 2007-04-19 15:38
zilloll さん、ありがとうございます。

先ほど、原因が分かりました!

結論からいいますと、j2ee.jar に JavaMail の主要なクラスが入っており、それを activation.jar、mail.jar より先に
読み込んでいたのが原因でした。
----------------------------
順をおって説明致します。

【状況】mail.jar の version を 1.1.3 から 1.3.3 へ入れ替え、メールが正しく送信できるか確認
  @ JSP画面の操作(ボタン押下) − 確認済
  A ant exec で実行 − java.lang.NoClassDefFoundError: com/sun/mail/util/MailDateFormat
  B shell 実行 − 確認済

  ※java.lang.NoClassDefFoundError は、sendMail メソッドで MimeMessage のコンストラクタ作成時
  > MimeMessage msg = new MimeMessage(session);
  で発生しておりました。

環境(システムプロパティ)
  @ JSP画面の操作(ボタン押下)時
   sun.boot.class.path= (省略)   
   java.ext.dirs=/usr/WebSphere/AppServer/java/jre/lib/ext (activation.jar、mail.jar)
   
   java.class.path=/usr/WebSphere/AppServer/properties
                /usr/WebSphere/AppServer/lib/bootstrap.jar
                  (以下、省略)
   
   ws.ext.dirs=/usr/WebSphere/AppServer/java/lib
             /usr/WebSphere/AppServer/classes
             /usr/WebSphere/AppServer/lib (j2ee.jar)
             /usr/WebSphere/AppServer/lib/ext
   
  A ant exec で実行時
   sun.boot.class.path= (省略)   
   java.ext.dirs=/usr/java130/jre/lib/ext(activation.jarなし、mail.jar なし)
   
   java.class.path=/usr/WebSphere/AppServer/lib/j2ee.jar
                /usr/WebSphere/AppServer/java/jre/lib/ext/activation.jar
                /usr/WebSphere/AppServer/java/jre/lib/ext/mail.jar
                 (以下、省略)
   
  B shell 実行時
   sun.boot.class.path= (省略)
   
   java.ext.dirs=/usr/WebSphere/AppServer/java/jre/lib/ext (activation.jar、mail.jar)
   
   java.class.path=/usr/WebSphere/AppServer/installedApps/ 〜 /WEB-INF/classes
                 /usr/WebSphere/AppServer/installedApps/ 〜 /WEB-INF/lib/log4j-1.2.4.jar
                 /usr/WebSphere/AppServer/installedApps/ 〜 /WEB-INF/lib/postgresql.jar
                 /usr/WebSphere/AppServer/lib/websphere.jar
                 /usr/WebSphere/AppServer/lib/j2ee.jar

webSphere V4.0で、クラスファイルは、
   ブート・クラスパス (sun.boot.class.path)
          ↓
   JVM エクステンション (java.ext.dirs)
          ↓
   アプリケーション・クラスパス (java.class.path)
   
   の順でロードされるようです。
   
   
activation.jar、mail.jar は、/usr/WebSphere/AppServer/java/jre/lib/ext/ 下にありますので、
  @ JSP画面の操作(ボタン押下)時、B shell 実行時では、JVM エクステンション (java.ext.dirs)として
  ロードされます。
  A ant exec で実行時では、アプリケーション・クラスパス (java.class.path)としてロードされます。
  
  しかし、載せている build.xml から分かりますように、Aでは activation.jar、mail.jar がロードされる前に、
  /usr/WebSphere/AppServer/lib/ の j2ee.jar がロードされています。
  よって j2ee.jar にある javax/mail/internet/MimeMessage.class がロードされ、
  これが com/sun/mail/util/MailDateFormat.class を呼んでいるようなのです。
  
  activation.jar、mail.jar を j2ee.jar より先にロードさせるようにしたところ、
   "java.lang.NoClassDefFoundError: com/sun/mail/util/MailDateFormat" は解消しました。

  参考: WebSphere V4.0 のクラスローディング
  http://www63.tok2.com/home2/jd4/WAS40ClassLoaders.html

----------------------------

Java 僧さん、zilloll さん、ありがとうございます。

お騒がせ致しました。
今後ともよろしくお願い致します。
1

スキルアップ/キャリアアップ(JOB@IT)