JMX MBean Scala example

Это простой пример 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}")
)

JMX MBean Scala example: 1 комментарий

  1. Забыл 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
    }

Оставьте комментарий