Это простой пример Management Bean на Scala.
В scala нет интерфейсов, вместо них — трэйты.
И так, создаём трейт, определяем в нём геттеры, создаём класс наследующий трейт, регистрируем инстанс в MBeanServer, всё. Имена классов выбираются не просто так, имя трейта должно совпадать с именем класса реализации и заканчиваться на «MBean», как в нашем примере:
trait StatusMBean class Status extends StatusMBean
Хоть scala и разрешает нам писать все классы в одном файле, для порядка создадим два файла. class Status
это реализация нашего MBean интерфейса, которая считает количество символов. class MBeanMain
это тестовое приложение, читает строки с консоли и регистрирует каждый символ в бине Status. В трейте (интерфейсе) StatusMBean
объявлен метод возвращающий все символы в виде строки, и список пар символ-количество в виде массива строк. Вообще MBean может отдавать только примитивные типы, и массивы примитивных типов.
package test.mbean import scala.collection.mutable trait StatusMBean { def getAllChars : String def getCharsCount : Array[String] } class Status extends StatusMBean { private val cmap = new mutable.HashMap[Char, Int].withDefaultValue(0) def putChar(ch: Char) = cmap(ch) = cmap(ch) + 1 override def getAllChars : String = cmap.keys.toSeq.sorted.mkString(", ") override def getCharsCount : Array[String] = cmap.toSeq .sortBy(_._1) .map { case (k, v) => s"$k = $v" } .toArray }
package test.mbean import java.lang.management.ManagementFactory import javax.management.ObjectName import test.mbean.Status import scala.io.StdIn object MBeanMain extends App { val mbean = new Status val oname = new ObjectName("test.mbean:type=Status") ManagementFactory.getPlatformMBeanServer.registerMBean(mbean, oname) println("type '\\q' to exit") var line :String = null do { line = StdIn.readLine("> ") line.toCharArray().foreach { c => mbean.putChar(c) } } while (line != "\\q") }
Имя бина ObjectName( ... )
состоит из домена и списка атрибутов. Чтобы не путаться и легко находить свои бины, лучше использовать следующую схему именования: имя.пакета:type=ИмяКласса
. В нашем случае это строка «test.mbean:type=Status», которая в VisualVM будет выглядеть как пакет test.mbean с классом Status внутри, что удобно. Имя можно генерировать автоматически:
val mbean = new Status val c = mbean.getClass ManagementFactory.getPlatformMBeanServer.registerMBean( mbean, new ObjectName(s"${c.getPackage.getName}:type=${c.getSimpleName}") )
Забыл putChar ! Спасибо большое 🙂
trait StatusMBean {
def getAllChars : String
def getCharsCount : Array[String]
def putChar(ch: Char): Unit
}
override def putChar(ch: Char) = {
cmap(ch) = cmap(ch) + 1
}