Рассмотрим процесс создания JMX-бина на примере.
-
Интерфейс JMX-бина:
package com.sample.sales.core; import org.springframework.jmx.export.annotation.*; @ManagedResource(description = "Performs operations on Orders") public interface OrdersMBean { @ManagedOperation(description = "Recalculates an order amount") @ManagedOperationParameters({@ManagedOperationParameter(name = "orderId", description = "")}) String calculateTotals(String orderId); }
Интерфейс и его методы могут содержать аннотации для задания описания JMX-бина и его операций. Это описание будет отображаться во всех инструментах, работающих с данным JMX-интерфейсом, тем самым помогая администратору системы.
Так как инструменты JMX поддерживают ограниченный набор типов данных, параметры и результат метода желательно задавать типа
String
, и при необходимости выполнять конвертацию внутри метода. -
Класс JMX-бина:
package com.sample.sales.core; import com.haulmont.cuba.core.*; import com.haulmont.cuba.core.app.*; import com.sample.sales.entity.Order; import org.apache.commons.lang.exception.ExceptionUtils; import javax.annotation.ManagedBean; import javax.inject.Inject; import java.util.UUID; @ManagedBean("sales_OrdersMBean") public class Orders implements OrdersMBean { @Inject protected OrderWorker orderWorker; @Inject protected Persistence persistence; @Authenticated @Override public String calculateTotals(final String orderId) { try { persistence.createTransaction().execute(new Transaction.Runnable() { @Override public void run(EntityManager em) { Order entity = em.find(Order.class, UUID.fromString(orderId)); orderWorker.calculateTotals(entity); } }); return "Done"; } catch (Throwable e) { return ExceptionUtils.getStackTrace(e); } } }
Аннотация
@ManagedBean
определяет, что данный класс является управляемым бином с именемsales_OrdersMBean
. Имя указано напрямую в аннотации, а не в константе, так как доступ к JMX-бину из кода Java не требуется.Рассмотрим реализацию метода
calculateTotals()
.-
Метод имеет аннотацию
@Authenticated
, т.е. при входе в метод и при отсутствии в потоке выполнения пользовательской сессии выполняется системная аутентификация. -
Тело метода обернуто в блок
try/catch
, так что метод в случае успешного выполнения возвращает строку "Done", а в случае ошибки - stacktrace исключения в виде строки.Следует иметь в виду, что в данном случае все исключения обрабатываются, а значит, не попадают в
MBeanInterceptor
и не выводятся в журнал автоматически. Поэтому при необходимости логгировать исключения здесь нужно добавить вызов логгера в секцииcatch
. -
Логика метода заключается в том, что он стартует транзакцию, загружает экземпляр сущности
Order
по идентификатору, и передает управление бинуOrderWorker
для обработки.
-
-
Регистрация JMX-бина в
spring.xml
:<bean id="sales_MBeanExporter" lazy-init="false" class="com.haulmont.cuba.core.sys.jmx.MBeanExporter"> <property name="beans"> <map> <entry key="${cuba.webContextName}.sales:type=Orders" value-ref="sales_OrdersMBean"/> </map> </property> </bean>
Все JMX-бины проекта объявляются в одном экземпляре MBeanExporter
в элементах map/entry
свойства beans
. Ключом элемента здесь является JMX ObjectName, значением - имя бина, заданное
в аннотации @ManagedBean
. ObjectName начинается с имени веб-приложения, так как в одном экземпляре Tomcat (т.е. в одной JVM) может быть развернуто несколько веб-приложений, экспортирующих одинаковые JMX-интерфейсы.