Skip to content

Commit 9534f71

Browse files
1497 : spring contract annotation alias handled (#1579)
* 1497 : spring contract annotation alias handled
1 parent 178040f commit 9534f71

File tree

2 files changed

+71
-21
lines changed

2 files changed

+71
-21
lines changed

spring4/src/main/java/feign/spring/SpringContract.java

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import feign.DeclarativeContract;
1717
import feign.MethodMetadata;
1818
import feign.Request;
19+
import feign.Util;
20+
import java.lang.reflect.Parameter;
1921
import java.util.ArrayList;
2022
import java.util.Collection;
2123
import org.springframework.web.bind.annotation.*;
@@ -41,8 +43,7 @@ public SpringContract() {
4143
registerMethodAnnotation(
4244
RequestMapping.class,
4345
(requestMapping, data) -> {
44-
String[] mappings = requestMapping.value();
45-
appendMappings(data, mappings);
46+
appendMappings(data, mapping(requestMapping.path(), requestMapping.value()));
4647

4748
if (requestMapping.method().length == 1)
4849
data.template().method(Request.HttpMethod.valueOf(requestMapping.method()[0].name()));
@@ -51,7 +52,7 @@ public SpringContract() {
5152
registerMethodAnnotation(
5253
GetMapping.class,
5354
(mapping, data) -> {
54-
appendMappings(data, mapping.value());
55+
appendMappings(data, mapping(mapping.path(), mapping.value()));
5556
data.template().method(Request.HttpMethod.GET);
5657
handleProducesAnnotation(data, mapping.produces());
5758
handleConsumesAnnotation(data, mapping.consumes());
@@ -60,7 +61,7 @@ public SpringContract() {
6061
registerMethodAnnotation(
6162
PostMapping.class,
6263
(mapping, data) -> {
63-
appendMappings(data, mapping.value());
64+
appendMappings(data, mapping(mapping.path(), mapping.value()));
6465
data.template().method(Request.HttpMethod.POST);
6566
handleProducesAnnotation(data, mapping.produces());
6667
handleConsumesAnnotation(data, mapping.consumes());
@@ -69,7 +70,7 @@ public SpringContract() {
6970
registerMethodAnnotation(
7071
PutMapping.class,
7172
(mapping, data) -> {
72-
appendMappings(data, mapping.value());
73+
appendMappings(data, mapping(mapping.path(), mapping.value()));
7374
data.template().method(Request.HttpMethod.PUT);
7475
handleProducesAnnotation(data, mapping.produces());
7576
handleConsumesAnnotation(data, mapping.consumes());
@@ -78,7 +79,7 @@ public SpringContract() {
7879
registerMethodAnnotation(
7980
DeleteMapping.class,
8081
(mapping, data) -> {
81-
appendMappings(data, mapping.value());
82+
appendMappings(data, mapping(mapping.path(), mapping.value()));
8283
data.template().method(Request.HttpMethod.DELETE);
8384
handleProducesAnnotation(data, mapping.produces());
8485
handleConsumesAnnotation(data, mapping.consumes());
@@ -87,7 +88,7 @@ public SpringContract() {
8788
registerMethodAnnotation(
8889
PatchMapping.class,
8990
(mapping, data) -> {
90-
appendMappings(data, mapping.value());
91+
appendMappings(data, mapping(mapping.path(), mapping.value()));
9192
data.template().method(Request.HttpMethod.PATCH);
9293
handleProducesAnnotation(data, mapping.produces());
9394
handleConsumesAnnotation(data, mapping.consumes());
@@ -103,26 +104,54 @@ public SpringContract() {
103104
(ann, data) -> {
104105
data.ignoreMethod();
105106
});
106-
registerParameterAnnotation(
107-
PathVariable.class,
108-
(parameterAnnotation, data, paramIndex) -> {
109-
String name = PathVariable.class.cast(parameterAnnotation).value();
110-
nameParam(data, name, paramIndex);
111-
});
107+
registerParameterAnnotation(PathVariable.class, pathVariableParameterAnnotationProcessor());
112108

113109
registerParameterAnnotation(
114110
RequestBody.class,
115111
(body, data, paramIndex) -> {
116112
handleProducesAnnotation(data, "application/json");
117113
});
118-
registerParameterAnnotation(
119-
RequestParam.class,
120-
(parameterAnnotation, data, paramIndex) -> {
121-
String name = RequestParam.class.cast(parameterAnnotation).value();
122-
Collection<String> query = addTemplatedParam(data.template().queries().get(name), name);
123-
data.template().query(name, query);
124-
nameParam(data, name, paramIndex);
125-
});
114+
registerParameterAnnotation(RequestParam.class, requestParamParameterAnnotationProcessor());
115+
}
116+
117+
private String[] mapping(String[] firstPriority, String[] fallback) {
118+
return firstPriority.length > 0 ? firstPriority : fallback;
119+
}
120+
121+
private String parameterName(String firstPriority, String secondPriority, Parameter parameter) {
122+
if (Util.isNotBlank(firstPriority)) {
123+
return firstPriority;
124+
} else if (Util.isNotBlank(secondPriority)) {
125+
return secondPriority;
126+
} else {
127+
if (parameter.isNamePresent()) {
128+
return parameter.getName();
129+
} else {
130+
return firstPriority;
131+
}
132+
}
133+
}
134+
135+
private DeclarativeContract.ParameterAnnotationProcessor<PathVariable>
136+
pathVariableParameterAnnotationProcessor() {
137+
return (parameterAnnotation, data, paramIndex) -> {
138+
Parameter parameter = data.method().getParameters()[paramIndex];
139+
String name =
140+
parameterName(parameterAnnotation.name(), parameterAnnotation.value(), parameter);
141+
nameParam(data, name, paramIndex);
142+
};
143+
}
144+
145+
private DeclarativeContract.ParameterAnnotationProcessor<RequestParam>
146+
requestParamParameterAnnotationProcessor() {
147+
return (parameterAnnotation, data, paramIndex) -> {
148+
Parameter parameter = data.method().getParameters()[paramIndex];
149+
String name =
150+
parameterName(parameterAnnotation.name(), parameterAnnotation.value(), parameter);
151+
Collection<String> query = addTemplatedParam(data.template().queries().get(name), name);
152+
data.template().query(name, query);
153+
nameParam(data, name, paramIndex);
154+
};
126155
}
127156

128157
private void appendMappings(MethodMetadata data, String[] mappings) {

spring4/src/test/java/feign/spring/SpringContractTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public void setup() throws IOException {
4949
.noContent(HttpMethod.GET, "/health/1")
5050
.noContent(HttpMethod.GET, "/health/1?deep=true")
5151
.noContent(HttpMethod.GET, "/health/1?deep=true&dryRun=true")
52+
.noContent(HttpMethod.GET, "/health/name?deep=true&dryRun=true")
5253
.ok(HttpMethod.GET, "/health/generic", "{}");
5354
resource =
5455
Feign.builder()
@@ -59,6 +60,20 @@ public void setup() throws IOException {
5960
.target(new MockTarget<>(HealthResource.class));
6061
}
6162

63+
@Test
64+
public void noPath() {
65+
resource.getStatus();
66+
67+
mockClient.verifyOne(HttpMethod.GET, "/health");
68+
}
69+
70+
@Test
71+
public void testWithName() {
72+
resource.checkWithName("name", true, true);
73+
74+
mockClient.verifyOne(HttpMethod.GET, "/health/name?deep=true&dryRun=true");
75+
}
76+
6277
@Test
6378
public void requestParam() {
6479
resource.check("1", true);
@@ -128,5 +143,11 @@ public void check(
128143
reason = "This customer is not found in the system")
129144
@ExceptionHandler(MissingResourceException.class)
130145
void missingResourceExceptionHandler();
146+
147+
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
148+
void checkWithName(
149+
@PathVariable(name = "id") String campaignId,
150+
@RequestParam(name = "deep", defaultValue = "false") boolean deepCheck,
151+
@RequestParam(name = "dryRun", defaultValue = "false") boolean dryRun);
131152
}
132153
}

0 commit comments

Comments
 (0)