5

I'd like to use the shutdown endpoint of my Spring Boot 2.0.1 application from the command line. For that I have only added the spring-boot-starter-actuator to my Gradle file and enabled the shutdown endpoint in the configuration.

I also created a very simple tool that tries to connect via JMX to the running application.

Snippet:

String url = "service:jmx:rmi:///jndi/rmi://127.0.01:<which port?>/jmxrmi";
JMXServiceURL serviceUrl = new JMXServiceURL(url);
JMXConnectorFactory.connect(serviceUrl, null); <-- KAPOW!

JMX is working because I can use jconsole to connect locally. I just have no clue how to do it programmatically.

Any other attempts to explicitly set a port as mentioned here didn't work. Any hints?

Robert Lohr
  • 635
  • 8
  • 21

2 Answers2

1

It's probably easier to enable jolokia rather than using RMI; then you can simply

curl http://localhost:8080/actuator/jolokia/exec/org.springframework.boot:type=Admin,name=SpringApplication/shutdown

EDIT

If you prefer to use RMI, refer to the Spring Framework JMX Documentation.

Server app:

@SpringBootApplication
public class So50392589Application {

    public static void main(String[] args) {
        SpringApplication.run(So50392589Application.class, args);
    }

    @Bean
    public RmiRegistryFactoryBean rmi() {
        RmiRegistryFactoryBean rmi = new RmiRegistryFactoryBean();
        rmi.setPort(1099);
        return rmi;
    }

    @Bean
    public ConnectorServerFactoryBean server() throws Exception {
        ConnectorServerFactoryBean fb = new ConnectorServerFactoryBean();
        fb.setObjectName("connector:name=rmi");
        fb.setServiceUrl("service:jmx:rmi://localhost/jndi/rmi://localhost:1099/myconnector");
        return fb;
    }

}

Client app:

@SpringBootApplication
public class JmxClient {

    public static void main(String[] args) {
        new SpringApplicationBuilder(JmxClient.class)
            .web(WebApplicationType.NONE)
            .run(args);
    }

    @Bean
    public ApplicationRunner runner(MBeanServerConnection jmxConnector) {
        return args -> {
            jmxConnector.invoke(new ObjectName("org.springframework.boot:type=Admin,name=SpringApplication"),
                    "shutdown", new Object[0], new String[0]);
        };
    }

    @Bean
    public MBeanServerConnectionFactoryBean jmxConnector() throws Exception {
        MBeanServerConnectionFactoryBean jmx = new MBeanServerConnectionFactoryBean();
        jmx.setServiceUrl("service:jmx:rmi://localhost/jndi/rmi://localhost:1099/myconnector");
        return jmx;
    }

}
Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • I would have preferred if I didn't have to make this available through HTTP. It should only be a configuration setting to enable `/actuator/shutdown` if I understood everything correctly. However, your example looks complicated enough so that it won't be discovered too easily by someone dabbling around. – Robert Lohr May 18 '18 at 05:33
  • If you prefer to use RMI, see the edit to my answer. – Gary Russell May 18 '18 at 13:37
  • Is it possible to set the port using a property without having to write all this boilerplate code? – Abhijit Sarkar Sep 24 '20 at 00:20
  • How do we set that `8080` port in the `cUrl` example with jolokia if my Spring Boot app is a non web app? @GaryRussell – billydh Feb 23 '21 at 00:34
  • Don’t ask new questions in comments on 3 year old answers. Actuator just needs the web starter. That doesn’t mean you need to add a controller to your app. – Gary Russell Feb 23 '21 at 00:52
-1

There is a much simpler approach if you do not need to connect to the app remotely using the jcmd tool introduced in Java SE 7, and the Attach API introduced in Java SE 6.

I've written a blog post that explains this in detail. It's too big to simply copy-paste here, following is the link to the relevant section.

https://blog.asarkar.com/technical/grpc-kubernetes-spring/#jmx

This is not a duplicate answer because when the question was asked, this answer didn't exist. This answer has already been tailored to this question; let's not get trigger happy mods.

Abhijit Sarkar
  • 21,927
  • 20
  • 110
  • 219