Skip to content

Instantly share code, notes, and snippets.

@brdloush
Last active June 22, 2021 10:00
Show Gist options
  • Save brdloush/30efd7cdbf794ae3746454117180488d to your computer and use it in GitHub Desktop.
Save brdloush/30efd7cdbf794ae3746454117180488d to your computer and use it in GitHub Desktop.
Standalone CLI utility that triggers a quartz job via QuartzScheduler JMX Bean. Requires clojure + JDK (openjdk 8,11,15 were succesfully tested).
#!/bin/sh
#_(
DEPS='
{:deps {org.clojure/java.jmx {:mvn/version,"1.0.0"}}}
'
exec clojure $OPTS -Sdeps "$DEPS" -M "$0" "$@"
)
(ns jmx.core
(:require [clojure.java.jmx :as jmx]
[clojure.string :as str])
(:import [javax.management.remote JMXServiceURL]))
(defn quartz-scheduler-mbean-name []
(->> (jmx/mbean-names "*:*")
(map str)
(filter #(str/includes? % "type=QuartzScheduler"))
first))
(defmacro with-local-pid-connection
[pid & body]
`(let [vm# (com.sun.tools.attach.VirtualMachine/attach (str ~pid))
url# (.startLocalManagementAgent vm#)]
(with-open [connector# (javax.management.remote.JMXConnectorFactory/connect
(JMXServiceURL. url#)
{})]
(binding [jmx/*connection* (.getMBeanServerConnection connector#)]
~@body))))
(defn add-system-classpath
"Add an url path to the system class loader"
[url-string]
(let [field (aget (.getDeclaredFields java.net.URLClassLoader) 0)]
(.setAccessible field true)
(let [ucp (.get field (ClassLoader/getSystemClassLoader))]
(.addURL ucp (java.net.URL. url-string)))))
(try (Class/forName "com.sun.tools.attach.VirtualMachine")
(catch ClassNotFoundException e
(add-system-classpath (format "file:///%s/../lib/tools.jar" (System/getProperty "java.home")))
(Class/forName "com.sun.tools.attach.VirtualMachine")))
(let [[pid job-name] *command-line-args*]
(if (and pid job-name)
(with-local-pid-connection pid
(let [scheduler-mbean (quartz-scheduler-mbean-name)]
(println (format "Triggering job %s on mbean %s" job-name scheduler-mbean))
(jmx/invoke scheduler-mbean
:triggerJob
job-name
"DEFAULT"
(java.util.HashMap.))
(println "Execution finished.")))
(println "Usage: triggerJob.clj <pid> <quartz-job-name>")))
Copy link

ghost commented Jun 22, 2021

👍

@brdloush
Copy link
Author

Its usage might be furthermore simplified with naive helper function (think ~/.zshrc) such as:

function run-quartz-job {
  JPS_APP_NAME=$1  # provide the java app name as seen in `jps` output
  JOB_NAME=$2 
  PID=$(jps | grep $JPS_APP_NAME | cut -d ' ' -f 1); triggerJob.clj $PID $JOB_NAME
}

Then the usage looks like:

~ run-quartz-job OurSpringbootApplication ourQuartzJob
Triggering job ourQuartzJob on mbean quartz:type=QuartzScheduler,name=ourapp,instance=brdloush-nb1624292395132
Execution finished.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment