Refine 'Allow operations to produce different output'
Refine the new `Producible` support so that it can also be used with `@ReadOperation`, `@WriteOperation` and `@DeleteOperation` annotations. This update allows the same enum to be used both as an argument and as an indicator of the media-types that an operation may produce. Closes gh-25738
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.OperationType;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -48,12 +49,35 @@ class DiscoveredOperationMethodTests {
|
||||
AnnotationAttributes annotationAttributes = new AnnotationAttributes();
|
||||
String[] produces = new String[] { "application/json" };
|
||||
annotationAttributes.put("produces", produces);
|
||||
annotationAttributes.put("producesFrom", Producible.class);
|
||||
DiscoveredOperationMethod discovered = new DiscoveredOperationMethod(method, OperationType.READ,
|
||||
annotationAttributes);
|
||||
assertThat(discovered.getProducesMediaTypes()).containsExactly("application/json");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getProducesMediaTypesWhenProducesFromShouldReturnMediaTypes() {
|
||||
Method method = ReflectionUtils.findMethod(getClass(), "example");
|
||||
AnnotationAttributes annotationAttributes = new AnnotationAttributes();
|
||||
annotationAttributes.put("produces", new String[0]);
|
||||
annotationAttributes.put("producesFrom", ExampleProducible.class);
|
||||
DiscoveredOperationMethod discovered = new DiscoveredOperationMethod(method, OperationType.READ,
|
||||
annotationAttributes);
|
||||
assertThat(discovered.getProducesMediaTypes()).containsExactly("one/*", "two/*", "three/*");
|
||||
}
|
||||
|
||||
void example() {
|
||||
}
|
||||
|
||||
enum ExampleProducible implements Producible<ExampleProducible> {
|
||||
|
||||
ONE, TWO, THREE;
|
||||
|
||||
@Override
|
||||
public MimeType getProducedMimeType() {
|
||||
return new MimeType(toString().toLowerCase());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,6 +34,7 @@ import org.springframework.boot.actuate.endpoint.invoke.OperationInvokerAdvisor;
|
||||
import org.springframework.boot.actuate.endpoint.invoke.OperationParameters;
|
||||
import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
|
||||
import org.springframework.boot.actuate.endpoint.invoke.reflect.OperationMethod;
|
||||
import org.springframework.util.MimeType;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -121,6 +122,14 @@ class DiscoveredOperationsFactoryTests {
|
||||
assertThat(advisor.getParameters()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void createOperationShouldApplyProducesFrom() {
|
||||
TestOperation operation = getFirst(
|
||||
this.factory.createOperations(EndpointId.of("test"), new ExampleWithProducesFrom()));
|
||||
DiscoveredOperationMethod method = (DiscoveredOperationMethod) operation.getOperationMethod();
|
||||
assertThat(method.getProducesMediaTypes()).containsExactly("one/*", "two/*", "three/*");
|
||||
}
|
||||
|
||||
private <T> T getFirst(Iterable<T> iterable) {
|
||||
return iterable.iterator().next();
|
||||
}
|
||||
@@ -175,6 +184,15 @@ class DiscoveredOperationsFactoryTests {
|
||||
|
||||
}
|
||||
|
||||
static class ExampleWithProducesFrom {
|
||||
|
||||
@ReadOperation(producesFrom = ExampleProducible.class)
|
||||
String read() {
|
||||
return "read";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TestDiscoveredOperationsFactory extends DiscoveredOperationsFactory<TestOperation> {
|
||||
|
||||
TestDiscoveredOperationsFactory(ParameterValueMapper parameterValueMapper,
|
||||
@@ -229,4 +247,15 @@ class DiscoveredOperationsFactoryTests {
|
||||
|
||||
}
|
||||
|
||||
enum ExampleProducible implements Producible<ExampleProducible> {
|
||||
|
||||
ONE, TWO, THREE;
|
||||
|
||||
@Override
|
||||
public MimeType getProducedMimeType() {
|
||||
return new MimeType(toString().toLowerCase());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,24 +39,28 @@ class ApiVersionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
void fromHttpHeadersWhenEmptyReturnsLatest() {
|
||||
ApiVersion version = ApiVersion.fromHttpHeaders(Collections.emptyMap());
|
||||
assertThat(version).isEqualTo(ApiVersion.V3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
void fromHttpHeadersWhenHasSingleV2HeaderReturnsV2() {
|
||||
ApiVersion version = ApiVersion.fromHttpHeaders(acceptHeader(ActuatorMediaType.V2_JSON));
|
||||
assertThat(version).isEqualTo(ApiVersion.V2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
void fromHttpHeadersWhenHasSingleV3HeaderReturnsV3() {
|
||||
ApiVersion version = ApiVersion.fromHttpHeaders(acceptHeader(ActuatorMediaType.V3_JSON));
|
||||
assertThat(version).isEqualTo(ApiVersion.V3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
void fromHttpHeadersWhenHasV2AndV3HeaderReturnsV3() {
|
||||
ApiVersion version = ApiVersion
|
||||
.fromHttpHeaders(acceptHeader(ActuatorMediaType.V2_JSON, ActuatorMediaType.V3_JSON));
|
||||
@@ -64,6 +68,7 @@ class ApiVersionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
void fromHttpHeadersWhenHasV2AndV3AsOneHeaderReturnsV3() {
|
||||
ApiVersion version = ApiVersion
|
||||
.fromHttpHeaders(acceptHeader(ActuatorMediaType.V2_JSON + "," + ActuatorMediaType.V3_JSON));
|
||||
@@ -71,18 +76,21 @@ class ApiVersionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
void fromHttpHeadersWhenHasSingleHeaderWithoutJsonReturnsHeader() {
|
||||
ApiVersion version = ApiVersion.fromHttpHeaders(acceptHeader("application/vnd.spring-boot.actuator.v2"));
|
||||
assertThat(version).isEqualTo(ApiVersion.V2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
void fromHttpHeadersWhenHasUnknownVersionReturnsLatest() {
|
||||
ApiVersion version = ApiVersion.fromHttpHeaders(acceptHeader("application/vnd.spring-boot.actuator.v200"));
|
||||
assertThat(version).isEqualTo(ApiVersion.V3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
void fromHttpHeadersWhenAcceptsEverythingReturnsLatest() {
|
||||
ApiVersion version = ApiVersion.fromHttpHeaders(acceptHeader("*/*"));
|
||||
assertThat(version).isEqualTo(ApiVersion.V3);
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.boot.actuate.endpoint.invoker.cache;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -203,9 +202,9 @@ class CachingOperationInvokerTests {
|
||||
Object expectedV2 = new Object();
|
||||
Object expectedV3 = new Object();
|
||||
InvocationContext contextV2 = new InvocationContext(mock(SecurityContext.class), Collections.emptyMap(),
|
||||
Arrays.asList(new ApiVersionArgumentResolver(ApiVersion.V2)));
|
||||
new ApiVersionArgumentResolver(ApiVersion.V2));
|
||||
InvocationContext contextV3 = new InvocationContext(mock(SecurityContext.class), Collections.emptyMap(),
|
||||
Arrays.asList(new ApiVersionArgumentResolver(ApiVersion.V3)));
|
||||
new ApiVersionArgumentResolver(ApiVersion.V3));
|
||||
given(target.invoke(contextV2)).willReturn(expectedV2);
|
||||
given(target.invoke(contextV3)).willReturn(expectedV3);
|
||||
CachingOperationInvoker invoker = new CachingOperationInvoker(target, CACHE_TTL);
|
||||
|
||||
Reference in New Issue
Block a user