Exposing class attributes to JMX for Mule custom r

2019-07-16 12:17发布

Using Mule Enterprise Standalone 3.1.2 I'm instrumenting attributes of the org.mule.routing.UntilSuccessful via a subclass. My subclass is used as a custom router.

<flow name="Queue Handler" processingStrategy="synchronous">
    <inbound-endpoint ref="Some.Queue">
        <vm:transaction action="ALWAYS_BEGIN"/>
    </inbound-endpoint>

    <custom-router class="com.company.product.mule.UntilSuccessfulSubclass">
        <flow-ref name="SomeFlow" />

        <spring:property name="objectStore" ref="SomeObjectStore" />
        <spring:property name="maxRetries" value="${maxRetries}" />
        <spring:property name="secondsBetweenRetries" value="${secondsBetweenRetries}" />
        <spring:property name="deadLetterQueue" ref="Cancel.Queue" />
        <spring:property name="maxThreads" value="${maxThreads}" />
        <spring:property name="maxBufferSize" value="${maxBufferSize}" />
        <spring:property name="threadTTL" value="${threadTTL}" />
    </custom-router>
</flow>

Currently I'm instrumenting the exposure via @ManagedAttribute on the getters and setters of my subclass of UntilSuccessful.

Looking at the Mule core xsd it doesn't appear that I have the option to pass in a bean instead of a class.

I'd prefer to use Spring's MBeanExporter functionality because this would allow me to avoid changing my class file by adding annotations and, more annoyingly, by having to override superclass methods just so I can instrument the JMX exposure.

2条回答
\"骚年 ilove
2楼-- · 2019-07-16 12:25

Currently Mule prevents using Spring beans directly as custom message processors, routers, ... which IMO is an oversight: since you're an EE user, you may want to open a ticket requesting an improvement for this.

Here is what you currently have to do to configure an UntilSuccessful message processor with Spring. I'm sure you can apply this to your own sub-class.

<spring:beans>
    <spring:bean id="untilSuccessful" class="org.mule.routing.UntilSuccessful">
        <spring:property name="routes">
            <util:list>
                <spring:ref bean="flowToProcess" />
            </util:list>
        </spring:property>
        <spring:property name="objectStore" ref="someObjectStore" />
        <spring:property name="maxRetries" value="5" />
        <spring:property name="secondsBetweenRetries" value="30" />
    </spring:bean>
</spring:beans>

<flow name="test">
    <vm:inbound-endpoint path="test.in"
        exchange-pattern="one-way" />

    <custom-processor class="com.myComp.MessageProcessorDelegate">
        <spring:property name="delegate" ref="untilSuccessful" />
    </custom-processor>
</flow>


package com.myComp;

import org.mule.api.MuleEvent;
import org.mule.api.MuleException;
import org.mule.api.processor.MessageProcessor;
import org.mule.processor.AbstractInterceptingMessageProcessor;

public class MessageProcessorDelegate extends AbstractInterceptingMessageProcessor
{
    private MessageProcessor delegate;

    public MuleEvent process(final MuleEvent event) throws MuleException
    {
        return delegate.process(event);
    }

    public void setDelegate(final MessageProcessor delegate)
    {
        this.delegate = delegate;
    }
}
查看更多
我只想做你的唯一
3楼-- · 2019-07-16 12:40

No word from MuleSoft as to when/whether the enhancement request will go through. However, MuleSoft's support team did provide a workaround:

  • Create interface that defines methods you want to expose in JMX
  • Implement interface in UntilSuccessfulSubclass
  • Include the following method in initialise():

    private void registerMBean()
    {
        final JmxSupportFactory jmxSupportFactory = AutoDiscoveryJmxSupportFactory.getInstance();
        final JmxSupport jmxSupport = jmxSupportFactory.getJmxSupport();
        final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
    
        final String rawName = getName() + "(" + getType() + ")";
        final String name = jmxSupport.escape(rawName);
        final String jmxName = String.format("%s:%s%s", jmxSupport.getDomainName(muleContext, !muleContext.getConfiguration().isContainerMode()), "type=ODM,name=", name);
        try
        {
            final ObjectName on = jmxSupport.getObjectName(jmxName);
            final ClassloaderSwitchingMBeanWrapper mBean = new ClassloaderSwitchingMBeanWrapper(this, UntilSuccessfulMBean.class, muleContext.getExecutionClassLoader());
            logger.debug("Registering custom router with name: " + on);
            mBeanServer.registerMBean(mBean, on);
        }
        catch (final Exception e)
        {
            logger.error(e.getMessage());
        }
    }
    

This approach does not require any change to the original Mule config file (partially referenced in my original post).

One downside to this approach is that my MBean has to appear in the Mule. directory in JMX instead of grouped with all of my other MBeans outside of that context, but it gets the job done. I don't have the points to spend on digging into Mule's JMX packages but it may be possible.

查看更多
登录 后发表回答