Spring Boot Actuator 2.x @WriteOperation с объектом в качестве параметра

Чего я пытаюсь достичь: я хочу создать конечную точку, доступную из Интернета и JMX, с действием, которое принимает объект в качестве параметра.

вот простой пример:


пом.xml

....

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.jolokia</groupId>
        <artifactId>jolokia-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Класс объекта:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dog {

    protected String name;
    protected int age;
}

Класс конечной точки

@Component
@Endpoint(id = "dogs")
@Slf4j
public class EndpointDogsExperiment {

    protected List<Dog> dogs = new ArrayList<>();

    public EndpointDogsExperiment() {
        dogs.add(new Dog("dog0", 5));
        dogs.add(new Dog("dog1", 7));
        log.debug("dogs created {}", dogs.toString());
    }

    @WriteOperation
    public List<Dog> addDog(Dog dog) {
        log.debug("adding a dog \n{}", dog );
        dogs.add(dog);
        return dogs;
    }
}

проблема:

как мне "вызвать" эту операцию

когда я пытаюсь использовать HTTP POST с /actuator/dogs и body {"dog":{"name":"aaaa", "age":33}}

клиент получает

Ответ: статус: 400 Дата: Сб, 31 марта 2018 г. 14:59:41 Соединение по Гринвичу: закрыть кодирование передачи: фрагментированный тип контента: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8

{"отметка времени":"2018-03-31T14:59:41.778+0000","статус":400,"ошибка":"Неверный запрос","сообщение":"Нет доступных сообщений","путь":"/ привод/собачки"}


и журнал сервера говорят


2018-03-31 17:59:41.766 WARN 12828 --- [nio-8081-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver: не удалось прочитать HTTP-сообщение: org.springframework.http.converter.HttpMessageNotReadableException: ошибка синтаксического анализа JSON: невозможно десериализовать экземпляр java.lang.String из токена START_OBJECT; вложенным исключением является com.fasterxml.jackson.databind.exc.MismatchedInputException: невозможно десериализовать экземпляр java.lang.String из токена START_OBJECT в [Источник: (PushbackInputStream); строка: 1, столбец: 8] (через цепочку ссылок: java.util.LinkedHashMap["собака"])


Я попытался создать @WriteOperation с параметром String, а затем с телом HTTP POST.

{"paramName":"StringParamValue"}

работает нормально

почему это?

Спасибо!


person Boris Daich    schedule 31.03.2018    source источник


Ответы (1)


Операции конечной точки не поддерживают сложные входные данные, такие как ваш тип Dog. Однако вы можете использовать отдельные параметры name и age и создать Dog в реализации операции:

@WriteOperation
public List<Dog> addDog(String name, int age) {
    Dog dog = new Dog(name, age);
    log.debug("adding a dog \n{}", dog );
    dogs.add(dog);
    return dogs;
}

Вы можете узнать больше в Справочная документация по Spring Boot.

person Andy Wilkinson    schedule 31.03.2018
comment
как передать несколько параметров? добавить @RequestParam ? - person Boris Daich; 01.04.2018
comment
@BorisDaich использует @Selector для привязки переменной из пути, вы можете получить N из них. Затем остальные параметры могут быть заполнены из параметров запроса. Но, к сожалению, вы не можете определить перегруженный @WriteOperation - person Martin Mucha; 26.02.2021
comment
Если еще актуально, поделитесь ссылкой на документацию, где именно об этом написано? - person dubnic; 05.03.2021
comment
@dubnic Я добавил ссылку на соответствующий раздел справочной документации. - person Andy Wilkinson; 05.03.2021