1

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.

2
  • 2
    Why don't you explain your real situation? Using simple examples like this isn't useful, because they don't really tell whether you're going towards a good solution or not. People tend to say "I need to do it like this" a lot, but if they really need to do it like that, they should be able to explain why. Commented Sep 22, 2017 at 12:31
  • 1
    You can't use a variable in annotation. This is simply not possible. If you will describe your actual problem maybe it will be possible to help you. Commented Sep 22, 2017 at 12:39

2 Answers 2

1

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);
}

}
Sign up to request clarification or add additional context in comments.

1 Comment

This solution only works for gets methods. For works all http methods we need replicate the index method for all HttpMethod using this order. '@RequestMapping(value = "**", method = RequestMethod.POST)'
0

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);
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.