Reputation: 75
Our application submits jobs to another service on either a monthly or quarterly basis. We have an API that allows us to trigger one of the following scenarios:
Currently we have 3 different API endpoints for the 3 scenarios, but would like to update the API to use a structure similar to the following:
/submit?type=single&id=123
/submit?type=all&frequency=monthly
/submit?type=all&frequency=quarterly
My question is how can we achieve this kind of mapping inside a Controller class so that each of the 3 API's has its own method, uniquely identified by the key-values provided to it.
Currently we have 3 methods similar to the following, which allows us to share the API path between the 3 methods, but differentiate them based on the params
value. Is there a similar approach we could use that allows us to filter based on both the query param key and value?
@PostMapping(value = "/submit", params = "monthly")
@ResponseStatus(HttpStatus.ACCEPTED)
public void submitAllMonthlyJobs() {
// Code
}
One approach is to use a single method that handles all 3 scenarios, and inside that method we fork to one of the 3 options based on the query params. But I'm hopeful there's a cleaner approach where Spring handles this for us.
Thanks for your help.
Upvotes: 1
Views: 2333
Reputation: 10531
Each request mapping like @RequestMapping
, @GetMapping
, @PostMapping
etc. can be filtered not only by path
, but also by params
. Your endpoint with the three mappings could look like this:
@RestController
public class JobEndpoint {
@PostMapping(path = "submit", params = "type=single")
public void submitSingleJob(@RequestParam("id") long id) {
System.out.println("submitting single job " + id);
}
@PostMapping(path = "submit", params = {"type=all", "frequency=monthly"})
public void submitMonthlyJobs() {
System.out.println("submitting monthly jobs");
}
@PostMapping(path = "submit", params = {"type=all", "frequency=quarterly"})
public void submitQuarterlyJobs() {
System.out.println("submitting quarterly jobs");
}
}
And just to be sure that it works:
@WebMvcTest
@ExtendWith(OutputCaptureExtension.class)
class JobEndpointTest {
@Autowired
private MockMvc mvc;
@Test
void submitSingleJob(CapturedOutput output) throws Exception {
mvc.perform(post("/submit?type=single&id=123")).andExpect(status().isOk());
assertThat(output).contains("submitting single job 123");
}
@Test
void submitMonthlyJobs(CapturedOutput output) throws Exception {
mvc.perform(post("/submit?type=all&frequency=monthly")).andExpect(status().isOk());
assertThat(output).contains("submitting monthly jobs");
}
@Test
void submitQuarterlyJobs(CapturedOutput output) throws Exception {
mvc.perform(post("/submit?type=all&frequency=quarterly")).andExpect(status().isOk());
assertThat(output).contains("submitting quarterly jobs");
}
}
Upvotes: 4