Raúl Garcia
Raúl Garcia

Reputation: 302

Make @RestController at runtime

I'm using Spring Boot in an app that uses REST servers and REST clients. My problem occurs when I let people choose the URL mapping, because then I need to dynamically create a REST Controller with this URL mapping:

@SpringBootApplication
public static void main(String[] args){
  SpringApplication.run(MyClass.class);
  String urlMapping = "/url/url";
  CreateNewRestController c = new CreateNewRestController(urlMapping);
}

@RestController
public class CreateNewRestController{
   String url;
   public CreateNewRestController(String url){
      this.url = url
   }

   @RequestMapping(value = this.url,method = RequestMethod.GET)
   public String getHello(){
       return "Hello";
   }
}

"Why are you using a url variable when you could use a constant string in the RequestMapping?" you may ask. But this is a simple example and I need to create the RequestMapping using a variable argument.

Upvotes: 1

Views: 4553

Answers (2)

Jeremy
Jeremy

Reputation: 3548

I solved this for my use case by using a Map to store 'sub' paths and passing all the requests to a generalized controller.
My use case needed a generic proxy app for multiple back-ends. Not too much different than what as you described a possible solution.

Source code - https://github.com/savantly-net/mesh-gateway

Example -

@RestController
@RequestMapping(MeshGateway.PATH)
public class MeshGateway {

    protected static final String PATH = "/gateway";
    private static final Logger log = LoggerFactory.getLogger(MeshGateway.class);

    private MeshGatewayConfig config;

    public MeshGateway(MeshGatewayConfig config) {
        this.config = config;
    }

    @GetMapping("/{child}/**")
    public ResponseEntity<?> get(@PathVariable String child, ProxyExchange<byte[]> proxy) throws Exception {
        log.debug("doing GET: {}", proxy.path());
        return proxy.uri(getDestinationPath(child, proxy)).get();
    }

    @PostMapping("/{child}/**")
    public ResponseEntity<?> post(@PathVariable String child, ProxyExchange<byte[]> proxy) throws Exception {
        log.debug("doing GET: {}", proxy.path());
        return proxy.uri(getDestinationPath(child, proxy)).post();
    }

    @PutMapping("/{child}/**")
    public ResponseEntity<?> put(@PathVariable String child, ProxyExchange<byte[]> proxy) throws Exception {
        log.debug("doing GET: {}", proxy.path());
        return proxy.uri(getDestinationPath(child, proxy)).put();
    }

    @RequestMapping(path = "/{child}/**", method = RequestMethod.OPTIONS)
    public ResponseEntity<?> options(@PathVariable String child, ProxyExchange<byte[]> proxy) throws Exception {
        log.debug("doing GET: {}", proxy.path());
        return proxy.uri(getDestinationPath(child, proxy)).options();
    }

    @RequestMapping(path = "/{child}/**", method = RequestMethod.PATCH)
    public ResponseEntity<?> patch(@PathVariable String child, ProxyExchange<byte[]> proxy) throws Exception {
        log.debug("doing GET: {}", proxy.path());
        return proxy.uri(getDestinationPath(child, proxy)).patch();
    }

    @RequestMapping(path = "/{child}/**", method = RequestMethod.DELETE)
    public ResponseEntity<?> delete(@PathVariable String child, ProxyExchange<byte[]> proxy) throws Exception {
        log.debug("doing GET: {}", proxy.path());
        return proxy.uri(getDestinationPath(child, proxy)).delete();
    }

    @RequestMapping(path = "/{child}/**", method = RequestMethod.HEAD)
    public ResponseEntity<?> head(@PathVariable String child, ProxyExchange<byte[]> proxy) throws Exception {
        log.debug("doing GET: {}", proxy.path());
        return proxy.uri(getDestinationPath(child, proxy)).head();
    }

    private String getDestinationPath(String child, ProxyExchange<byte[]> proxy) {
        String destination = this.config.getRoutes().get(child);
        String path = proxy.path(String.format("%s/%s", PATH, child));
        log.debug("with prefix removed: {}", path);
        return String.format("%s%s", destination, path);
    }
}

Upvotes: 0

Ra&#250;l Garcia
Ra&#250;l Garcia

Reputation: 302

Github link - here

I found a awnser to my question and maybe a solution to used RequestMapping in real time. I created a RestController that take all the HTTP petitions to it, them the petition ask to a hash map with have the uri mapping like key and a class controller like value.

The generic controller:

@RestController
public class GeneralController {

HashMap<String,PersonalizedController> petitions = new HashMap<String,PersonalizedController>();

 @RequestMapping("**")
 public ResponseEntity<Object> index(HttpServletRequest request,HttpServletResponse response,@RequestBody Object body) {

    // Inicialization zone -  this zone don't must exist
        petitions.put("/dir/esta1", new PersonalizedController("esta1"));
        petitions.put("/dir/esta2", new PersonalizedController("esta2"));
    //-------------------------------------------------

    return handlePetition(request,response);
  }

 private ResponseEntity<Object> handlePetition(HttpServletRequest request, HttpServletResponse response) {
    // TODO Auto-generated method stub
    String petition = request.getRequestURI();
    String method = request.getMethod();

    return petitions.get(petition).makePetition(method,new String());
 }
}

The controller class:

public class PersonalizedController {

private String name;

public PersonalizedController(String name) {
    this.name = name;
}

public ResponseEntity<Object> makePetition(String method,Object body) {
    // TODO Auto-generated method stub
    switch (method) {
    case "GET":
        return doGet(body);
    case "POST":
        return doPost(body);
    case "PUT":
        return doPut(body);
    case "DELETE":
        return doDelete(body);
    default:
        return new ResponseEntity<Object>("",HttpStatus.METHOD_NOT_ALLOWED);
    }
}

public ResponseEntity<Object> doGet(Object body) {
    return new ResponseEntity<Object>("["+name+"] GET",HttpStatus.OK);
}

public ResponseEntity<Object> doPost(Object body) {
    return new ResponseEntity<Object>("["+name+"] POST",HttpStatus.OK);
}

public ResponseEntity<Object> doDelete(Object body) {
    return new ResponseEntity<Object>("["+name+"] DELETE",HttpStatus.OK);
}

public ResponseEntity<Object> doPut(Object body) {
    return new ResponseEntity<Object>("["+name+"] PUT",HttpStatus.OK);
}

}

Upvotes: 1

Related Questions