Announcement Announcement Module
Collapse
No announcement yet.
JMX-Integration: NotificationPublisher never set when using jmx-int channel adapters Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JMX-Integration: NotificationPublisher never set when using jmx-int channel adapters

    Hello everyone,

    I am experimenting with spring's JMX support- and have had good luck, except when I try working with the spring jmx-integration channel adapters (these fancy things: http://static.springsource.org/sprin...tmlsingle/#jmx).

    My problem is with the notification-publishing-channel-adapter, specifically that the NotificationPublisher is never set by the container. I have never encountered this problem when working with standard spring beans, only when trying to use these channel adapters.

    Here is an excerpt from my working configuration:

    management-applicationContext.xml
    Code:
    <context:mbean-server /> 
    	
    <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
         <property name="assembler" ref="assembler"/>
         <property name="namingStrategy" ref="namingStrategy"/>
         <property name="autodetect" value="true"/>
         <property name="notificationListenerMappings">
              <map>
                   <entry key="*">
                        <bean class="com.poc.jmx.domain.NotificationBroadcastListener" />
                   </entry>
              </map>
         </property>
    </bean>
    
    <bean id="jmxAttributeSource" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
    
    <bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
         <property name="attributeSource" ref="jmxAttributeSource"/>
    </bean> 
    
    <bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
         <property name="attributeSource" ref="jmxAttributeSource"/>
    </bean> 
    
    <!-- Annotated with @ManagedResource(objectName = "IntManagement:name=messageBroadcaster") -->
    <bean id="notificationBroadcaster" class="com.poc.jmx.domain.NotificationBroadcaster" />
    In my tests, notificationBroadcaster is deployed successfully to the MBean server- which I can connect to with JConsole and activate managed operations.

    Those operations broadcast notifications- so the NotificationPublisher is being set in this case. The notifications are even successfully picked up by the NotificationBroadcastListener.


    Now, here is my current configuration:

    management-applicationContext.xml
    Code:
         .
         . <!-- Added just below what is posted above -->
         .
    
    <int:channel id="testInputChannel" />
    	
    <int:channel id="testOutputChannel">
         <int:queue />
    </int:channel> 
     
    <int-jmx:notification-listening-channel-adapter id="listeningAdapter"
         channel="testOutputChannel"
         object-name="IntManagement:name=messageBroadcaster"/> 
    
    <int-jmx:notification-publishing-channel-adapter id="publishingAdapter"
         channel="testInputChannel"
         object-name="IntManagement:name=messageBroadcaster"
         default-notification-type="jmx.integration.notification" />
    The error
    Code:
    Caused by: java.lang.IllegalStateException: NotificationPublisher must not be null.
    	at org.springframework.util.Assert.state(Assert.java:384)
    	at org.springframework.integration.jmx.NotificationPublishingMessageHandler$PublisherDelegate.publish(NotificationPublishingMessageHandler.java:133)
    	at org.springframework.integration.jmx.NotificationPublishingMessageHandler$PublisherDelegate.access$100(NotificationPublishingMessageHandler.java:124)
    	at org.springframework.integration.jmx.NotificationPublishingMessageHandler.handleMessageInternal(NotificationPublishingMessageHandler.java:116)
    	at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:73)
    	... 30 more

    As you can see, I have not changed anything besides adding the channel adapters and specifying the object to listen for/publish notifications. I am currently using Spring Integration 2.2.1-RELEASE, and Spring Framework 3.2.1-RELEASE.

    I've tried just about every version of configuring the MBean exporter and I'm out of ideas. Any help or suggestions would be greatly appreciated.

    Thanks a million.
    Last edited by waitwhat; Feb 13th, 2013, 12:06 PM.

  • #2
    That's strange. We usually use an IntegrationMBeanExporter, but I just tested with the monitoring SI sample https://github.com/garyrussell/sprin...ate/monitoring (I replaced the IntegrationMBeanExporter and AnnotationMBeanExporter with a simple MBeanExporter like you have) and all works fine for me.

    The IllegalStateException implies the adapter's initialization code (called from afterPropertiesSet) didn't find the exporter (because the PublisherDelegate gets a reference to a NotificationPublisher when the initialization code registers it with the exporter. Do you see this log message...

    Code:
    11:04:27.134 INFO  [main][org.springframework.integration.jmx.NotificationPublishingMessageHandler] Registered JMX notification publisher as MBean with ObjectName: ...
    ??

    Here's the initialization code; the call to registerMBeanResource calls back into the delegate to provide the publisher...

    Code:
    public final void onInit() throws Exception {
    	Assert.isTrue(this.getBeanFactory() instanceof ListableBeanFactory, "A ListableBeanFactory is required.");
    	Map<String, MBeanExporter> exporters = BeanFactoryUtils.beansOfTypeIncludingAncestors(
    			(ListableBeanFactory) this.getBeanFactory(), MBeanExporter.class);
    	Assert.isTrue(exporters.size() > 0, "No MBeanExporter is available in the current context.");
    	MBeanExporter exporter = null;
    	for (MBeanExporter exp : exporters.values()) {
    		exporter = exp;
    		if (exporter instanceof IntegrationMBeanExporter) {
    			break;
    		}
    	}
    	if (this.notificationMapper == null) {
    		this.notificationMapper = new DefaultNotificationMapper(this.objectName, this.defaultNotificationType);
    	}
    	exporter.registerManagedResource(this.delegate, this.objectName);
    	if (this.logger.isInfoEnabled()) {
    		this.logger.info("Registered JMX notification publisher as MBean with ObjectName: " + this.objectName);
    	}
    }
    If there's no IntegrationMBeanExporter, we register with the last one (which is what I see in my tests).
    Last edited by Gary Russell; Feb 13th, 2013, 01:07 PM.

    Comment


    • #3
      Hey Gary, thanks a lot for your reply. And based on one of your suggestions I was able to get to the bottom of the issue, so thanks again.

      That log message you posted was not coming up, so I tried to include the IntegrationMBeanExporter in my management-applicationContext.xml.

      However after adding it and attempting to run my test, I got a methodNotFound exception on IntegrationMBeanExporter's constructor, caused by some version conflicts in the pom.

      After cleaning up a few of the dependencies, my tests run fine. I was also able to remove the IntegrationMBeanExporter and replace it with the simple MBeanExporter and it worked fine.

      Thanks again for your help, without your suggestion I'm not sure how long it would have taken me to figure it out.

      Code:
      javax.management.Notification[source=IntegrationManagement:name=channelMessageBroadcaster][type=jmx.integration.notification][message=hahaha oh wow]
      PASSED: sendMessageTest

      Comment

      Working...
      X