Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically enabling remote jmx monitoring

I am attempting to enable my core java application for remote accessibility via JMX. However, two restrictions are making it harder than it should be.

a) I am not at the liberty to change the script which starts the app on the linux box. Therefore, I cannot pass any of the "jmxremote" parameters to the jvm.

b) It is very possible that the remote port ( com.sun.management.jmxremote.port = xxxx ) I specify is not open and I cannot modify the script to try another open port. I must do it automatically.

I tried to get around these restrictions by writing a class with would set all the required jmxremote params as well as find a "free" port.

public class JmxRemoteConnectionHelper{

    @Override
    public void init( ) throws Exception{

        InetAddress address = InetAddress.getLocalHost();
        String ipAddress    = address.getHostAddress();
        String hostname     = address.getHostName();
        String port         = String.valueOf( getFreePort( ) );

        System.setProperty("java.rmi.server.hostname", ipAddress );
        System.setProperty("com.sun.management.jmxremote", "true" );
        System.setProperty("com.sun.management.jmxremote.authenticate", "false" );
        System.setProperty("com.sun.management.jmxremote.ssl", "false" );
        System.setProperty("com.sun.management.jmxremote.port", port  );

    }

    private final int getFreePort( ){

        **//seedPort is passed in the constructor**
        int freePort            = seedPort;
        ServerSocket sSocket    = null;

        for( int i=ZERO; i<PORT_SCAN_COUNTER; i++ ){

            try{

                freePort        = freePort + i;
                sSocket         = new ServerSocket( freePort );

               //FOUND a free port.             
                break;

            }catch( Exception e ){
                //Log

            }finally{

                if( sSocket != null ){
                    try{
                            sSocket.close();
                        sSocket = null;
                    }catch(Exception e ){
                    //Log
                    }

                }
            }

        }

        return freePort;
    }

 }

As shown below, I, then initialize it via spring.

<bean id="JmxRemoteConnection" class="JmxRemoteConnectionHelper" init-method="init" />

<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean" depends-on="JmxRemoteConnection" />   

<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false" >
        <property name="assembler"      ref="assembler"/>
        <property name="namingStrategy" ref="namingStrategy"/>
        <property name="autodetect"     value="true"/>
        <property name="server"         ref="mbeanServer"/>
</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" lazy-init="true">
        <property name="attributeSource" ref="jmxAttributeSource"/>
</bean>

To test, I start the app on my windows machine. It starts up correctly. However, when I bring up JConsole on the same box and try to connect via "remote process" (ip:port), I get a "connection refused" message at the bottom.

My suspicion is that the JMX agent is not seeing any of the remote system properties that I am setting.

I am using JDK 1.6.

like image 896
CaptainHastings Avatar asked Jan 13 '23 21:01

CaptainHastings


2 Answers

Since you are already using Spring I think you should see if using a ConnectorServerFactoryBean can do what you are looking to do. I've never had to start a remote JMX server but it looks like that's what that object can do for you.

like image 162
laz Avatar answered Jan 16 '23 11:01

laz


See the answers to this for enabling jmx within the process:

Is it possible to enable remote jmx monitoring programmatically?

To find a free port simply wrap LocateRegistry.createRegistry() in a loop which retries with a new port number until it succeeds. Of course you'll have to communicate the final port number to whatever needs to connect. Alternatively running jstatd on the host should make it discoverable

like image 36
AutomatedMike Avatar answered Jan 16 '23 10:01

AutomatedMike