我一直在使用编程远程JMX客户端,连接到WebSphere Application Server的MBean服务器。到目前为止,我可以使用适当的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。
因此;如果不阻止我接收进一步的通知,我该怎么办才能处理这种情况?
答案 0 :(得分:3)
我可以想出4种解决这个问题的方法,按复杂度递增顺序(我认为):
将类库添加到客户端类路径
陈述显而易见,但试图全面。
修改通知
考虑修改服务器生成的通知,将 com.mycompany.MyWeirdClass 实例交换为格式化字符串。如果对象很复杂,请考虑使用XML或JSON。如果您可以修改通知发件人来封送实例,那可能是最简单的。如果没有,你可以修改 com.mycompany.MyWeirdClass 类(应该是Serializable,对吗?)并添加一个返回实例的String表示的writeReplace方法
远程ClassLoader
在WebSphere应用程序中实现一个HTTP服务器,该服务器返回包含 com.mycompany.MyWeirdClass 类及其所有依赖项的JAR。 (从技术上讲,HTTP服务器可以在任何地方,只要它提供正确的类。)让我们假设JAR可以在 http://classloader.mycompany.com/Weird.jar 获得即可。现在使用添加的系统属性启动您的客户端,如下所示:
java ..... -D-Djava.rmi.server.codebase=http://classloader.mycompany.com/Weird.jar ...
有一个HTTP服务器实现的示例,用于提供动态类加载here。
将类实现为JMX OpenType
最常见的方法是将课程设为MXBean,或者您可以实施CompositeData或扩展CompositeDataSupport。如果您不介意使用 com.sun 类,则java运行时(1.6+)包含DefaultMXBeanMappingFactory,它将为您创建复合数据实例,因此这个有用的实用程序可用于与上述解决方案之一的音乐会。例如,您可以像这样实现 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);
}
}