I want Spring to create 2 instances of FooController. Requests to /foo should be handled by one of the instances and requests to /bar should be handled by the other instance. I want something like the below, but of course @RequestMapping
doesn’t work that way and also Spring gives me the ambiguous mapping error on FooController as well.
@RestController
public class FooController {
String name;
public FooController(String name) { this.name = name; }
}
@Configuration
public class FooControllerConfig {
@Bean
@RequestMapping("/foo")
public FooController getFooFooController(){
return new FooController("foo");
}
@Bean
@RequestMapping("/bar")
public FooController getBarFooController(){
return new FooController("bar");
}
}
Advertisement
Answer
Don’t try this at home. This code was performed by a bored, trained professional…
You can have multiple instances of the same controller class, each of which handles a different URL through the same or a different method in the controller. The only thing is, I don’t know how to do it with just annotations. The way I just did it was to dynamically register each request mapping at initialization time. The FooController becomes a prototype bean (defined with annotations) so you can have Spring instantiate it multiple times, once for each mapping
FooController.java
@Controller
@Scope("prototype")
public class FooController {
private String name;
public FooController() {}
public FooController(String name) {
this.name = name;
}
public ResponseEntity<String> handleRequests() throws Exception {
return new ResponseEntity<>("Yo: " + name + " " + this.hashCode(), HttpStatus.OK);
}
EndpointService.java
@Service
public class EndpointService {
@Autowired
private BeanFactory beanFactory;
@Autowired
private RequestMappingHandlerMapping requestMappingHandlerMapping;
public void addFooController(String urlPath, String name) throws NoSuchMethodException {
RequestMappingInfo requestMappingInfo = RequestMappingInfo
.paths(urlPath)
.methods(RequestMethod.GET)
.produces(MediaType.APPLICATION_JSON_VALUE)
.build();
requestMappingHandlerMapping.registerMapping(requestMappingInfo,
beanFactory.getBean(FooController.class, name),
FooController.class.getDeclaredMethod("handleRequests"));
}
@EventListener
public void handleContextRefreshEvent(ContextRefreshedEvent ctxStartEvt) {
try {
addFooController("/blah1", "blahblah1");
addFooController("/blah2", "blahblah2");
addFooController("/blah3", "blahblah3");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
Results:
http://localhost:8080/blah1 returns: Yo: blahblah1 1391627345
http://localhost:8080/blah3 returns: Yo: blahblah3 2078995154