| import javax.management.remote.JMXServiceURL |
| import javax.management.remote.JMXConnectorFactory |
| import javax.management.ObjectName |
| import org.grails.io.support.* |
| import groovy.jmx.GroovyMBean |
| |
| description("Stops the running Grails application") { |
| usage "grails stop-app" |
| synonyms 'stop' |
| flag name:'port', description:"Specifies the port which the Grails application is running on (defaults to 8080 or 8443 for HTTPS)" |
| flag name:'host', description:"Specifies the host the Grails application is bound to" |
| } |
| System.setProperty("run-app.running", "false") |
| def getJMXLocalConnectorAddresses = {-> |
| final applicationMainClassName = MainClassFinder.findMainClass() |
| |
| if(applicationMainClassName) { |
| try { |
| final String CONNECTOR_ADDRESS = "com.sun.management.jmxremote.localConnectorAddress" |
| def VirtualMachine = getClass().classLoader.loadClass('com.sun.tools.attach.VirtualMachine') |
| return VirtualMachine.list() |
| .findAll { |
| it.displayName() == applicationMainClassName |
| } |
| .collect { desc -> |
| def vm = VirtualMachine.attach(desc.id()) |
| try { |
| def connectorAddress = vm.agentProperties.getProperty(CONNECTOR_ADDRESS) |
| if (connectorAddress == null) { |
| // Trying to load agent |
| def agent = [vm.systemProperties.getProperty("java.home"), "lib", "management-agent.jar"].join(File.separator) |
| vm.loadAgent(agent) |
| |
| connectorAddress = vm.agentProperties.getProperty(CONNECTOR_ADDRESS) |
| } |
| if (connectorAddress) { |
| return connectorAddress |
| } |
| } finally { |
| vm.detach() |
| } |
| }.findAll { it } |
| |
| } |
| catch(Throwable e) { |
| // fallback to REST request if JMX not available |
| } |
| } |
| } |
| |
| |
| def addresses = getJMXLocalConnectorAddresses() |
| if(addresses) { |
| JMXServiceURL url = new JMXServiceURL(addresses[0]) |
| def connector = JMXConnectorFactory.connect(url) |
| |
| try { |
| def server = connector.MBeanServerConnection |
| |
| def objectName = server.queryNames(null,null).find { it.canonicalName.contains('name=shutdownEndpoint,type=Endpoint') } |
| def mbean = new GroovyMBean(server, objectName) |
| console.addStatus "Shutting down application..." |
| mbean.shutdown() |
| console.addStatus "Application shutdown." |
| return true |
| } |
| catch(e) { |
| console.addStatus "Application not found via JMX, attempting remote shutdown." |
| } |
| finally { |
| connector.close() |
| } |
| } |
| |
| |
| Integer port = flag('port')?.toInteger() ?: config.getProperty('server.port', Integer) ?: 8080 |
| String host = flag('host') ?: config.getProperty('server.address', String) ?: "localhost" |
| String contextPath = config.getProperty('server.context-path') ?: config.getProperty('server.contextPath') ?: "" |
| String managementPath = config.getProperty('management.endpoints.web.base-path') ?: config.getProperty('management.endpoints.web.basePath') ?: "/actuator" |
| console.updateStatus "Shutting down application..." |
| def url = new URL("http://$host:${port}${contextPath}${managementPath}/shutdown") |
| try { |
| def connection = url.openConnection() |
| connection.setRequestMethod("POST") |
| connection.doOutput = true |
| connection.connect() |
| console.updateStatus connection.content.text |
| while(isServerAvailable(host, port)) { |
| sleep 100 |
| } |
| console.updateStatus "Application shutdown." |
| return true |
| |
| } |
| catch (e) { |
| console.error "Application not running.", e |
| return false |
| } |
| |
| |
| |