1

私は、WebSphere Application ServerのMBeanサーバーに接続して、プログラムによるリモートJMXクライアントで遊んでいます。これまでのところ、適切なJMXServiceURLを使用して接続し、Beanからの通知をサブスクライブできます。

しかし、Beanがローカルクラスパスにないクラスを含む通知を送信すると、素晴らしいスタックトレースで爆発します。

SEVERE: Failed to fetch notification, stopping thread. Error is: java.rmi.RemoteException: CORBA NO_IMPLEMENT 1330646337 No; nested exception is: 
    org.omg.CORBA.NO_IMPLEMENT: The sender's class RMI:com.mycompany.MyWeirdClass:143EC4C84209B825:EAD08F0965BC6044 is not present on the local classpath, and the class is not marked as truncatable, so it cannot be unmarshaled.  vmcid: OMG  minor code: 1  completed: No
java.rmi.RemoteException: CORBA NO_IMPLEMENT
... more frames ...

これは最終的に次の原因で発生します。

Caused by: java.lang.ClassNotFoundException: com.mycompany.MyWeirdClass
    at com.ibm.rmi.util.RepositoryId.loadClass(RepositoryId.java:675)
    at com.ibm.rmi.util.RepositoryId.checkClassCache(RepositoryId.java:644)
    ...

IBMのコードの奥深くで爆発しているように見えますが、私ができることはどこにもありません。問題のある通知がNotificationListenerに届くことはありません。

それで; それ以上の通知を受け取れないようにすることなく、このシナリオを処理するにはどうすればよいですか?

4

1 に答える 1

3

複雑さの昇順で、これに対処する4つの方法を考えることができます(私は思います):

クラスライブラリをクライアントクラスパスに追加します

明白なことを述べますが、包括的であろうとしています。

通知を変更する

サーバーで生成された通知を変更して、com.mycompany.MyWeirdClassインスタンスをフォーマットされた文字列にスワップアウトすることを検討してください。オブジェクトが複雑な場合は、XMLまたはJSONの使用を検討してください。通知の送信者を変更してインスタンスをマーシャリングできる場合は、おそらくそれが最も簡単です。そうでない場合は、com.mycompany.MyWeirdClassクラス(Serializableである必要があります)を変更し、インスタンスの文字列表現を返すwriteReplaceメソッドを追加できます。

リモートClassLoader

com.mycompany.MyWeirdClassクラスとそのすべての依存関係を含むJARを返すHTTPサーバーをWebSphereアプリに実装します。(技術的には、HTTPサーバーは、正しいクラスを提供する限り、どこにあってもかまいません。)JARがhttp://classloader.mycompany.com/Weird.jarで利用可能であると仮定しましょう。次に、次のような追加のシステムプロパティを使用してクライアントを起動します。

java .....  -D-Djava.rmi.server.codebase=http://classloader.mycompany.com/Weird.jar ...

ここに動的クラスローディングを提供するHTTPサーバー実装の例があります。

クラスをJMXOpenTypeとして実装します

これを行う最も一般的な方法は、クラスをMXBeanにするか、 CompositeDataを実装するかCompositeDataSupportを拡張することです。com.sunクラスを使用してもかまわない場合は 、Javaランタイム(1.6以降)にDefaultMXBeanMappingFactory が含まれており、複合データインスタンスが作成されるため、この便利なユーティリティを上記のソリューションの1つと組み合わせて使用​​できます。たとえば、次のようにwriteReplaceトラックを実装します。

import com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory;
import com.sun.jmx.mbeanserver.MXBeanMapping;
final MXBeanMapping mapping = 
   DefaultMXBeanMappingFactory.DEFAULT.mappingForType(
      com.mycompany.MyWeirdClass.class, 
      DefaultMXBeanMappingFactory.DEFAULT
   );
private Object writeReplace() throws ObjectStreamException {
   try {
      return mapping.toOpenValue(this);
   } catch (Exception ex) {
      throw new RuntimeException(ex);
   }
}
于 2013-01-16T14:51:02.377 に答える