8

I am creating prototype beans programatically/dynamically. I want those beans after initiation to be in the jmx console. How I can distinguish between them? I am using anotations in order to add my beans to the jmx and I have

@ManagedResource(objectName="bean:name=MybBean")

I need to inject the objectName dynamically. Any idea how could I do it?

Here's my jmx configuration:

<context:mbean-export server="mbeanServer" />

<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean" />

<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"
        lazy-init="false">

        <property name="beans">
            <map>
                <entry key="Server:name=HttpAdaptor">
                    <bean class="mx4j.tools.adaptor.http.HttpAdaptor">
                        <property name="port" value="8000" />
                        <property name="host" value="0.0.0.0" />
                        <property name="processor">
                            <bean class="mx4j.tools.adaptor.http.XSLTProcessor" />
                        </property>

                    </bean>
                </entry>                
            </map>
        </property>
        <property name="listeners">
            <list>
                <!--

                -->
                <bean class="com.fixgw.jmx.HttpAdaptorMgr">
                    <property name="mbeanServer" ref="mbeanServer" />
                </bean>
            </list>
        </property>
    </bean>

   <bean id="sessionMDB" class="com.fixgw.mdb.SessionMDB"
        scope="prototype" lazy-init="true">
        <constructor-arg ref="0" />
        <constructor-arg ref="0" />
    </bean>
Gray
  • 115,027
  • 24
  • 293
  • 354
rayman
  • 20,786
  • 45
  • 148
  • 246

2 Answers2

16

You can do this by just implementing org.springframework.jmx.export.naming.SelfNaming:

@Component("MyPrototypeScopedBeanName")
@ManagedResource     
public class MyPrototypeScopedBeanName implements SelfNaming
{
    @Override
    public ObjectName getObjectName() throws MalformedObjectNameException {
        return new ObjectName("com.foobar", "name", this.toString());
    }
}
Michael
  • 41,989
  • 11
  • 82
  • 128
theJC
  • 325
  • 2
  • 6
6

You can use a a JMX naming strategy to do this. At work we use an interface:

public interface RuntimeJmxNames {
    /** this is the name= part of the object name */
    public String getJmxName();
    /** this sets the folders as 00=FirstFolder,01=Second */
    public String[] getJmxPath();
}

I've posted the code to implement the RuntimeMetadataNamingStrategy naming strategy.

And then something like the following Spring beans:

<bean id="jmxAttributeSource"
 class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource" />

<bean id="jmxAssembler"
    class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
    <property name="attributeSource" ref="jmxAttributeSource" />
</bean>

<bean id="jmxNamingStrategy" class="com.j256.jmx.RuntimeMetadataNamingStrategy">
    <property name="attributeSource" ref="jmxAttributeSource" />
</bean>

<bean id="mbeanExporter" class="org.springframework.jmx.export.MBeanExporter">
    <property name="autodetect" value="true" />
    <property name="assembler" ref="jmxAssembler" />
    <property name="namingStrategy" ref="jmxNamingStrategy" />
    <property name="ensureUniqueRuntimeObjectNames" value="false" />
    <property name="excludedBeans" ref="excludedJmxBeans" />
</bean>

In your code you do something like:

@ManagedResource(objectName = "foo.com:name=replaced", description = "...")
public class Foo implements RuntimeJmxNames {
    ...
    public String getJmxName() {
        // here's where you can make the name be dynamic
        return toString();
    }
    @Override
    public String[] getJmxPath() {
        return new String[] { "folder" };
    }
}

Here's the Spring documentation on JMX naming although I'm not 100% sure it covers the custom naming stuff.

Also, my SimpleJMX package does a this as well. It uses a JmxSelfNaming interface which allows each instance of an object to define it's own bean-name to make them unique and works well with Spring.

Gray
  • 115,027
  • 24
  • 293
  • 354
  • But the bean name is hardcoded in the class.. I need it to be dynamic I will set it on the creation of the instance – rayman Jul 16 '12 at 14:48
  • So in your `getJmxName()` method, it can do whatever it would like programmatically. It can do it's `toString()` method or spit out whatever makes it unique. I've edited the answer to make this more obvious. – Gray Jul 16 '12 at 14:50
  • com.j256.jmx.RuntimeMetadataNamingStrategy I need to get that lib eh? – rayman Jul 16 '12 at 14:51
  • That lead to other error: No bean named '0' is defined. I have editted the way my mbean looks like in the configuration file – rayman Jul 16 '12 at 14:54
  • Dont forget I am creating this prototype bean dynamically so this is like a 'placeholder' arguments. – rayman Jul 16 '12 at 14:55
  • Not sure I understand the problem there rayman. We use the `MetadataMBeanInfoAssembler` which may be easier than the hard wiring that you are doing. Who is talking about a bean named '0'? – Gray Jul 16 '12 at 15:00
  • I said this is an error I am getting when I am using your technic: aused by: org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [sessionMDB] with key 'sessionMDB'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionMDB' defined in class path resource [applicationContext.xml]: Cannot resolve reference to bean '0' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named '0' is define ... 14 more – rayman Jul 16 '12 at 15:04
  • Oh, I see @rayman. In your XML you have: .... That should be `value=0` not `ref=0`. That was broken before, right? – Gray Jul 16 '12 at 15:51
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/13974/discussion-between-rayman-and-gray) – rayman Jul 17 '12 at 06:47
  • Works awesome. I've implemented your solution using Annotations since I don't like xml config. Here's the implementation: https://pastebin.com/vDp9rvBD – hmojica Feb 10 '18 at 05:35
  • 1
    You might want to look at my SimpleJMX package @hmojica. http://256stuff.com/sources/simplejmx/ – Gray Feb 12 '18 at 22:14