8

MXBeanインターフェースを作成することにより、JMXを使用してアプリケーションサーバーでリモート管理するためのメソッドと、それを実装するためのクラスを公開しました。このインターフェースには、サーバーに属性を設定するための操作と、属性の現在の値を取得するための操作が含まれています。たとえば、次の方法を取ります。

public interface WordManagerMXBean {
     public void addWord(String word);
     public WordsObject getWords();
     public void removeWord(String word);
}

WordsObjectは、サーバーの状態に関するデータを取得するために使用される、カスタムのシリアル化可能なクラスです。次に、上記のインターフェイスを実装するWordManagerクラスもあります。次に、リソースを管理するためのJMXエージェントを作成します。

MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName wordManagerName = new ObjectName("com.example:type=WordManager");
mbs.registerMBean(wordManager, wordManagerName);

これらのメソッドを呼び出すクライアントを作成しましたが、これは期待どおりに機能します。ただし、クライアントに返送できるユーザー定義の例外を追加して、この現在の構成を拡張したいと思います。だから私は私のインターフェースを次のようなものに変更したいと思います:

public interface WordManagerMXBean {
     public void addWord(String word) throws WordAlreadyExistsException;
     public WordsObject getWords();
     public void removeWord(String word);
}

私のWordAlreadyExistsExceptionは次のようになります。

public class WordAlreadyExistsException extends Exception implements Serializable {

private static final long serialVersionUID = -9095552123119275304L;

public WordAlreadyExistsException() {
    super();
    }
}

クライアントでaddWord()メソッドを呼び出すときに、単語がすでに存在する場合はWordAlreadyExistsExceptionを返したいと思います。ただし、これを行うと、次のようなエラーが発生します。

java.rmi.UnmarshalException: Error unmarshaling return; nested exception is: 
java.lang.ClassNotFoundException: com.example.WordAlreadyExistsException

WordAlreadyExistsException、WordsObject、およびWordManagerMXBeanインターフェースはすべて、クライアントとサーバーの両方で使用できる単一のjarファイルに含まれています。getWords()メソッドを呼び出すと、クライアントはWordsObjectを問題なく処理できます。ただし、上記のようなユーザー定義の例外がスローされた場合、クライアントは上記のエラーを出します。クライアントでこの例外を正しく処理するようにJMXを設定することは可能ですか?

いくつか検索した後、例外をラップするために使用されるMBeanExceptionクラスがあることに気付きました。このラッピングがエージェントによって自動的に実行されるのか、それとも自分でラッピングを実行するのかはわかりません。両方を試しましたが、どちらの場合もクライアントで同じエラーが発生します。

チェックされた例外とチェックされていない例外の両方でこれを試しましたが、同じエラーが発生します。

これに対する1つの解決策は、すべての標準Java例外が機能するため、一般的なエラー内でエラー文字列を返すことです。しかし、クライアントによる処理の実際の例外を取り戻したいと思います。

JMXでユーザー定義の例外を処理することは可能ですか?もしそうなら、どのようにアイデアはありますか?

編集:フルスタックトレースを含む

java.lang.reflect.UndeclaredThrowableException
at $Proxy4.addWord(Unknown Source)
at com.example.TestClient.addWord(TestClient.java:76)
at com.example.TestClient.execute(TestClient.java:56)
at java.lang.Thread.run(Thread.java:722
Caused by: java.rmi.UnmarshalException: Error unmarshaling return; nested exception is: 
java.lang.ClassNotFoundException: com.example.WordAlreadyExistsException
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:245)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:160)
at com.sun.jmx.remote.internal.PRef.invoke(Unknown Source)
at javax.management.remote.rmi.RMIConnectionImpl_Stub.invoke(Unknown Source)
at javax.management.remote.rmi.RMIConnector$RemoteMBeanServerConnection.invoke(RMIConnector.java:1017)
at  javax.management.MBeanServerInvocationHandler.invoke(MBeanServerInvocationHandler.java:305)
... 6 more
Caused by: java.lang.ClassNotFoundException: com.example.WordAlreadyExistsException
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:453)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:184)
at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:637)
at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:264)
at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:216)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1593)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:243)
... 11 more
4

5 に答える 5

4

問題を再現しようとしましたが、問題なく動作します;-(。以下の例外出力を参照してください。これは実際にはクライアント側のクラス読み込みの問題であると思います。投稿することは可能ですか?クライアントjarのバージョン(およびおそらくソースも)を削除しましたか?

Exception in thread "main" javax.management.MBeanException: WordAlreadyExistsException
at com.sun.jmx.mbeanserver.MBeanIntrospector.unwrapInvocationTargetException(MBeanIntrospector.java:283)
at com.sun.jmx.mbeanserver.MBeanIntrospector.invokeM(MBeanIntrospector.java:210)
.....
Caused by: WordAlreadyExistsException
at WordManager.addWord(WordManager.java:7)
.....
于 2012-12-04T22:45:44.633 に答える
1

発生している可能性があるのは、カスタム例外がシリアル化されてからアプリケーションサーバー内で逆シリアル化されますが、「クラスローダー名前空間」というより適切な単語がないためです。

カスタム例外クラスを含むjar(c)を、AppServerが使用しているJMXjarと一緒に配置してみてください。古い場所から古いjarファイルを削除してください(WEB-INF/libのどこかにあると想定しています。

于 2012-12-04T21:33:54.330 に答える
1

推奨されていませんが、カスタム例外をスローすることは間違いなく可能です。JMXのベストプラクティスから:

MBeanによってスローされる例外は、JavaSEプラットフォームのjava。*およびjavax。*パッケージで定義されている標準セットから取得することをお勧めします。MBeanが非標準の例外をスローした場合、その例外クラスを持たないクライアントには、代わりにClassNotFoundExceptionなどの別の例外が表示される可能性があります。

WordAlreadyExistsExceptionしたがって、私はあなたのクライアントが単にクラスをロードしなかったお金をいくらか入れます。かなり単純なことを確認できます。この例外をスローするメソッドをクライアントに記述し、それを呼び出して、何が起こるかを確認します。すべてが正常に行われた場合(OK =カスタム例外がスローされた、いいえClassNotFoundException)、クライアントとサーバーにが含まれる同じバージョンのjarがあることを確認しますWordAlreadyExistsException。わずかな不一致(たとえば、パッケージ名)でも、問題の原因となる可能性があります。

于 2012-12-04T22:23:47.220 に答える
0

例外はから拡張する必要があります

    javax.management.JMException

また

    javax.management.JMRuntimeException

RuntimeExceptionの場合。

于 2012-12-04T07:24:21.550 に答える
0

RuntimeMBeanExceptionを拡張する代わりに、RuntimeExceptionをRuntimeMBeanExceptionのコンストラクター引数として渡して、その例外をスローするだけです。jarファイルがCLASSPATHに存在することを確認してください。

jarファイルがクラスパスに存在する場合、RuntimeMBeanExceptionの拡張も機能する可能性がありますが、私はそれをテストしませんでした

于 2012-12-04T13:41:42.807 に答える