jonatzin
jonatzin

Reputation: 972

java.io.NotSerializableException raised when JMX raises notifications

Hello recently I started working on a JMX bean implementation.

I then publish the below bean, run JConsole, connect to the bean, register for notification. However when the notification is sent i get the following error:

Apr 13, 2012 5:31:26 PM ClientNotifForwarder NotifFetcher.fetchOneNotif WARNING: Failed to deserialize a notification: java.io.NotSerializableException: com.*.jmx.TaskMergeMBean

Any help will be most welcome, I've spent the better part of a day trying to figure this one out.

Thanks, Jonathan

public class TaskMBean extends NotificationBroadcasterSupport implements DynamicMBean {

  private final TaskStateChangedEventListener taskChangedListener;

  public TaskMBean (DriverIf driver) {
    taskChangedListener= new TaskStateChangedEventListener (this);
    driver.registerMergeTaskStateChangedListener(mergeTaskChangedListener);
  }
  @Override
  public MBeanNotificationInfo[] getNotificationInfo() {
    String[] types = new String[] { AttributeChangeNotification.ATTRIBUTE_CHANGE };
    String name = AttributeChangeNotification.class.getName();
    String description = "An attribute of this MBean has changed";
    MBeanNotificationInfo info = new MBeanNotificationInfo(types, name,description);
    return new MBeanNotificationInfo[] { info };
  }

  @Override
  public Object getAttribute(String attribute) throws AttributeNotFoundException,          MBeanException,
      ReflectionException {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public void setAttribute(Attribute attribute) throws AttributeNotFoundException,
      InvalidAttributeValueException, MBeanException, ReflectionException {
    // TODO Auto-generated method stub

  }

  @Override
  public AttributeList getAttributes(String[] attributes) {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public AttributeList setAttributes(AttributeList attributes) {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Object invoke(String actionName, Object[] params, String[] signature)
      throws MBeanException, ReflectionException {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public MBeanInfo getMBeanInfo() {
    MBeanNotificationInfo haltInfo =
        new MBeanNotificationInfo(
            new String[] { "NOTIFICATION_TYPE_MERGE_STATE_CHANGE" },
            Notification.class.getName(), "server halt on fatal error");
    MBeanNotificationInfo[] notifications = new MBeanNotificationInfo[] { haltInfo };
    return new OpenMBeanInfoSupport(XhiveMergeMBean.class.getName(), "", null, null, null,
        notifications);
  }
}

public class TaskStateChangedEventListener implements Serializable {

  static final String NOTIFICATION_TYPE_MERGE_STATE_CHANGE = "com.xhive.lucene.merge";
  private final NotificationBroadcasterSupport broadcaster;
  private int notificationSequence = 1;

  public TaskStateChangedEventListener (NotificationBroadcasterSupport broadcaster) {
    this.broadcaster = broadcaster;
  }

  @Override
  public void notify(Object source) {
    Notification n =
        new AttributeChangeNotification(this, notificationSequence++,    System.currentTimeMillis(), "", "", "int", 1, 2);
    broadcaster.sendNotification(n);
  }
}

Upvotes: 0

Views: 1565

Answers (1)

Nicholas
Nicholas

Reputation: 16056

What Peter said. But also.....

Notifications usually (but not always) have to be serialized, so using this as the notification source tends to put a dent in that. (pun intended)

So you need to make completely sure that the the instance of this is serializable (and preferably usefully so) or better yet, send a simpler representation of what this is, like the ObjectName of the MBean. The intent is for the receiver (or the filter) to be able to determine the source of the notification, so I find that consistent use of informative ObjectNames really helps.

And lastly, JConsole tends to be a bit thin on business classes (by default I mean) so if you're relying on JConsole a lot and you want to be able to view all your notifications cleanly, you need to make sure you only use core JDK types in your payload.

(Or use OpenTypes (same thing) or enable remote class loading (not worth the hassle)).

//Nicholas

Upvotes: 2

Related Questions