【问题标题】:how to return object value while using spring boot jmx使用spring boot jmx时如何返回对象值
【发布时间】:2018-05-23 08:35:38
【问题描述】:

当数据库发生更改时,我正在使用 spring boot jmx 远程执行该方法。每件事都运行良好,当我使用原始数据类型作为返回值时,我可以在 windows 中使用 jmc.exe 监控我的应用程序。现在我需要返回对象(不是原始数据类型,而是一个类)值作为我的方法的返回值。实际上,这个对象与我的班级在同一个包中。但是当我使用 jmx 远程运行该方法时,我得到了

java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
java.lang.ClassNotFoundException: com.ff.KeyValue (no security manager: RMI class loader disabled).

我的代码如下

@Service
@ManagedResource(description = "JMX managed resource for updating map when database is updated",
        objectName = "chargeCode:name=ChargeCodeService")
public class ChargeCodeService {

    private static final Logger logger = LoggerFactory.getLogger(ChargeCodeService.class);

    private final ChargeCodeRepository chargeCodeRepository;
    private Map<String, KeyValue<String,String>> chargeCodeMap = new HashMap<>();

    @Autowired
    public ChargeCodeService(ChargeCodeRepository chargeCodeRepository) {
        this.chargeCodeRepository = chargeCodeRepository;
    }

    @PostConstruct
    @ManagedOperation
    public Map<String, KeyValue<String,String>> chargeCodMapInitial() {
        logger.info("ready to read chargeCode data from database. this operation will do when an update occure in database");
        List<ChargeCode> chargeCodes = chargeCodeRepository.findAll();
        for (ChargeCode chargeCode : chargeCodes) {
            chargeCodeMap.put(chargeCode.getIacChargeCode(),new KeyValue<>( chargeCode.getBankChargeCode(),chargeCode.getTopupProvider()));
        }
        return chargeCodeMap;
    }

    @ManagedAttribute
    public Map<String, KeyValue<String, String>> getChargeCodeMap() {
        return chargeCodeMap;
    }
}

KeyValue 类如下:

public class KeyValue<K, V> implements Map.Entry<K, V>, Serializable {

    private static final long serialVersionUID = -2610138893852455839L;

    private K key;
    private V value;

    public KeyValue() {
    }

    public KeyValue(K key, V value)
    {
        this.key = key;
        this.value = value;
    }

  getter,setter;
}

【问题讨论】:

  • JVM(发出 JMX 命令的那个)不知道你的类。只有服务器知道您的课程,因此您会收到错误消息。
  • 谢谢,但是我如何通过编程让 JVM 知道我的课程。这两个类都在同一个应用程序和同一个包中

标签: spring-boot jconsole spring-jmx jmc


【解决方案1】:

您必须返回 CompositeData 或 TabularDataSupport 作为您的返回类型。以下代码演示了两者,并且应该对您有用。如果您有任何问题,请告诉我。

package com.example.demo;

import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedOperationParameter;
import org.springframework.jmx.export.annotation.ManagedOperationParameters;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Component;

import javax.management.openmbean.*;

@Component
@ManagedResource(objectName="com.example.demo.jmx:name=ServerManager",
        description="Server manager.")
public class SampleOperation {
    private static final String[] itemNames = new String[] { "name", "age" };
    private static final String[] itemDescription = new String[] { "Your name", "Your age" };
    private static final OpenType<?>[] itemTypes = new OpenType[] {
            SimpleType.STRING,
            SimpleType.INTEGER
    };

    public static final String IAC_CHARGE_CODE = "IacChargeCode";
    public static final String BANK_CHARGE_CODE = "BankChargeCode";
    public static final String TOP_UP_PROVIDER = "TopUpProvider";
    public static final String[] rowItemNames = new String[] { IAC_CHARGE_CODE, BANK_CHARGE_CODE, TOP_UP_PROVIDER };
    public static final String[] rowItemDescriptions = new String[] {
            "Iac charge code",
            "Bank charge code",
            "Top up provider"
    };

    @ManagedOperation(description="Get the complex object.")
    @ManagedOperationParameters({
            @ManagedOperationParameter(name="name", description= "Your name."),
            @ManagedOperationParameter(name="age", description= "Your age.")})
    public CompositeData simpleData(String name, int age) throws Exception {
        CompositeType compositeType = new CompositeType(
                "NameAndAge",
                "name and age",
                itemNames, itemDescription, itemTypes);

        CompositeData data = new CompositeDataSupport(compositeType, itemNames, new Object[] {
                name, age
        });
        return data;
    }

    @ManagedOperation(description="Retrieve recodes from DB.")
    public TabularDataSupport tabular() throws OpenDataException {
        OpenType<?>[] rowItemTypes = new OpenType[]{
                SimpleType.STRING, SimpleType.STRING, SimpleType.STRING
        };

        CompositeType compositeRowType = new CompositeType(
                "chargeRow",
                "some row",
                rowItemNames,
                rowItemDescriptions,
                rowItemTypes);
        TabularType tabularType = new TabularType(
                "charge table",
                "Sample table of charge",
                compositeRowType,
                rowItemNames);
        TabularDataSupport rows = new TabularDataSupport(tabularType);

        rows.putAll(new CompositeData[]{
                new CompositeDataSupport(compositeRowType, rowItemNames, new Object[]{
                        "charge code #1", "bank charge code #1", "Top up #1"
                }),
                new CompositeDataSupport(compositeRowType, rowItemNames, new Object[]{
                        "charge code #2", "bank charge code #2", "Top up #2"
                }),
                new CompositeDataSupport(compositeRowType, rowItemNames, new Object[]{
                        "charge code #3", "bank charge code #3", "Top up #3"
                }),
        });
        return rows;
    }
}

【讨论】:

  • 非常感谢。这正是我想要的。你为我节省了很多时间。
猜你喜欢
  • 2017-06-02
  • 1970-01-01
  • 2022-01-01
  • 1970-01-01
  • 2018-10-17
  • 2016-05-16
  • 2020-04-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多