Reputation: 21866
I have a feign client that looks something like that:
@RequestMapping(method = RequestMethod.POST, value = "/breakdowns/utmMedium", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
List<Breakdown> getUtmMediumBreakdowns(
@RequestBody Record record,
@RequestParam("since") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime since,
@RequestParam("until") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime until,
@RequestParam("timezone") String timezone
);
@RequestMapping(method = RequestMethod.POST, value = "/breakdowns/utmCampaign", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
List<Breakdown> getUtmCampaignBreakdowns(
@RequestBody Record record,
@RequestParam("since") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime since,
@RequestParam("until") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime until,
@RequestParam("timezone") String timezone
);
@RequestMapping(method = RequestMethod.POST, value = "/breakdowns/utmSource", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
List<Breakdown> getUtmSourceBreakdowns(
@RequestBody Record record,
@RequestParam("since") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime since,
@RequestParam("until") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime until,
@RequestParam("timezone") String timezone
);
As you can see, the three methods are exactly the same aside for the difference in the API path that changes according to the parameter utmMedium
, utmCampaign
and utmSource
as in the server side we do treat those differently.
I can't change the server so I can't change the endpoint to accept this parameter as a request param or something. I wonder if there is a way for me to still parameterize this part of the path so I'd have only a single method instead of three.
Upvotes: 0
Views: 24034
Reputation: 159
If you want to add compile time checks to the alternative URIs, a String Enum can be used for the utmType parameter. This assumes you are using Spring Open Feign. Plain Feign would require alternate annotations some starting guidance for that case can be found here.:
//Slight changes should be introduced in the getUtmCampaignBreakdowns method signature utmType parameter.
package test;
import java.time.ZonedDateTime;
import java.util.List;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = "utmThing", url = "${feign.client.config.utmThing.url}")
public interface Test {
@PostMapping(value = "/breakdowns/{utmType}", consumes = MediaType.APPLICATION_JSON_VALUE)
List<Breakdown> getUtmCampaignBreakdowns(
@RequestBody Record record,
@PathVariable("utmType") UtmTypes utmType, //<-Type changed to Enum
@RequestParam("since") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime since,
@RequestParam("until") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime until,
@RequestParam("timezone") String timezone
);
}
//An enum should be declared
package test;
enum UtmTypes {
UTM_MEDIUM("utmMedium"),
UTM_CAMPAIGN("utmCampaign"),
UTM_SOURCE("utmSource");
private final String utmType;
UtmTypes(String utmType) {
this.utmType = utmType;
}
//Do not forget to privide a toString() that would map to the URI parameter
public String toString() {
return utmType;
}
}
//Can be used like so:
package test;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.TimeZone;
import org.springframework.beans.factory.annotation.Autowired;
public class User {
@Autowired
void User(Test test) {
test.getUtmCampaignBreakdowns(new Record(), UtmTypes.UTM_CAMPAIGN, ZonedDateTime.now(),
ZonedDateTime.now().plusDays(1),
Arrays.stream(TimeZone.getAvailableIDs())
.filter(zoneName -> zoneName.contains("Montevideo")).findFirst()
.orElse(TimeZone.getAvailableIDs()[0]));
}
}
//Assuming simple Record and Breakdown implementations
package test;
public class Record {
private String someField;
public void setSomeField(String someField) {
this.someField = someField;
}
public String getSomeField() {
return this.someField;
}
}
package test;
public class Record {
private String someField;
Record() {
this.someField = "defaultValue";
}
public void setSomeField(String someField) {
this.someField = someField;
}
public String getSomeField() {
return this.someField;
}
}
Upvotes: 0
Reputation: 5589
You can define additional parameter with @PathVariable
annotation like the below utmType
.
@RequestMapping(method = RequestMethod.POST, value = "/breakdowns/{utmType}", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
List<Breakdown> getUtmCampaignBreakdowns(
@RequestBody Record record,
@PathVariable("utmType") String utmType,
@RequestParam("since") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime since,
@RequestParam("until") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime until,
@RequestParam("timezone") String timezone
);
One thing that you have to be careful about is that you need to specify the name utmType
like @PathVariable("utmType")
with annotation.
Upvotes: 3