On Java Controller how to get the value of annotation #RequestMapping("/getThisValueFromOtherClass")? - java

On Java MVC Controller how to get the value of annotation #RequestMapping("/getThisValueFromOtherClass")? I know we can extract this by using java reflections but is there any other way? Thank you.
#RequestMapping("/getThisString")
public class MyController{}

If the purpose is just to avoid changing the url at every place, I will suggest define a string constant in some class and instead of using hard coded string in request mapping use that constant every where.
In future if u want tp\o change the url, simple update the constant value at one place
final String constUrl = "/myurl";
#RequestMapping(value=constUrl)
you can make the constant static, if defining in another class

The value of the annotation can be read programmatically:
#RequestMapping("/endpoints")
public ResponseEntity<String> getPath() {
String path = getClass().getAnnotation(RequestMapping.class).value()[0];
return new ResponseEntity<String>(path, HttpStatus.OK);
}

To obtain the path, you should pass the Request i.e. HttpServletRequest as a parameter to your handler method.
#RequestMapping(value={"/getThisString"}, method=RequestMethod.GET)
public String handlerMethod (Model model, HttpServletRequest request) throws Exception {
String getThatString = request.getServletPath();
....
}
Reference:
HttpServletRequest

In your case if an URI pattern “/getThisString” is requested, it will map to this MyController, and handle the request with method where #RequestMapping(method = RequestMethod.GET) is declared.
You can refer this tutorial #RequestMapping example
Hope it helps.

Related

Spring restful API, is there a method being used like router to get other method's end points or URL?

#RequestMapping("/accounts")
public class controller {
#GetMapping("/get/{id}")
public final ResponseEntity<?> getHandler(){
}
#PostMapping(value = "/create")
public final ResponseEntity<?> createHandler(){
/*
trying to use some spring library methods to get the url string of
'/accounts/get/{id}' instead of manually hard coding it
*/
}
}
This is the mock code, now I am in createHandler, after finishing creating something, then I want to return a header including an URL string, but I don't want to manually concat this URL string ('/accounts/get/{id}') which is the end point of method getHandler(), so I am wondering if there is a method to use to achieve that? I know request.getRequestURI(), but that is only for the URI in the current context.
More explanation: if there is some library or framework with the implementation of route:
Routes.Accounts.get(1234)
which return the URL for the accounts get
/api/accounts/1234
The idea is, that you don't need to specify get or create (verbs are a big no-no in REST).
Imagine this:
#RequestMapping("/accounts")
public class controller {
#GetMapping("/{id}")
public final ResponseEntity<?> getHandler(#PathVariable("id") String id) {
//just to illustrate
return complicatedHandlerCalculation(id).asResponse();
}
#PostMapping
public final ResponseEntity<?> createHandler() {
//return a 204 Response, containing the URI from getHandler, with {id} resolved to the id from your database (or wherever).
}
}
This would be accessible like HTTP-GET: /api/accounts/1 and HTTP-POST: /api/accounts, the latter would return an URI for /api/accounts/2 (what can be gotten with HTTP-GET or updated/modified with HTTP-PUT)
To resolve this URI, you could use reflection and evaluate the annotations on the corresponding class/methods like Jersey does.
A Spring equivalent could be:
// Controller requestMapping
String controllerMapping = this.getClass().getAnnotation(RequestMapping.class).value()[0];
and
//Method requestMapping
String methodMapping = new Object(){}.getClass().getEnclosingMethod().getAnnotation(GetMapping.class).value()[0];
taken from How do i get the requestmapping value in the controller?

Is there a way to access a PathVariable in a controller level #PreAuthorize annotation?

is there a way to access the httpRequest within a controller level #PreAuthorize annotation to obtain a PathVariable and use it for the expression inside the #PreAuthorize annotation?
I want to be able to do the following, where #somePathVariable would result in the actual value passed for the PathVariable:
#RequestMapping(value = "/{somePathVariable}/something")
#PreAuthorize("#someBean.test(#somePathVariable)")
public class SomeController { ... }
It also would be sufficient if i could access the HttpServletRequest and get the PathVariable manually.
Please note that this expression is at the controller level before answering. I'd appreciate any help!
So as #pvpkiran already commented. It's probably not possible to get the param the way i want. However his workaround with using a bean to access the PathVariables manually seems to work just fine.
#Component
#RequiredArgsConstructor
public class RequestHelper {
private final HttpServletRequest httpServletRequest;
/* https://stackoverflow.com/questions/12249721/spring-mvc-3-how-to-get-path-variable-in-an-interceptor/23468496#23468496 */
public Object getPathVariableByName(String name) {
final Map pathVariables = (Map) httpServletRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
return pathVariables.get(name);
}
}
and
#RequestMapping(value = "/{somePathVariable}/something")
#PreAuthorize("#someBean.test(#requestHelper.getPathVariableByName('somePathVariable'))")
public class SomeController { ... }
did the job. It's not perfect but it works. The other (prob. better) option is to use #PreAuthorize on method level.
Thanks for your help!

How to properly manage PathVariables with spring

I'm hoping this isn't too simple of a question. I'm new to the java web services world and cant seem to get access to my PathVariables in my controller. I'm using STS and it's not complaining that my syntax is wrong.
So more important than the correct answer, I'd really like to know why this isn't working.
Here's some example code that I cant get to work:
#RestController
public class TestController {
#RequestMapping("/example")
public String doAThing(
#PathVariable String test
) throws MessagingException {
return "Your variable is " + test;
}
}
If I run a curl against it like so:
curl http://localhost:8080/example?test=foo
I receive the following response:
{"timestamp":1452414817725,"status":500,"error":"Internal Server
Error","exception":"org.springframework.web.bind.MissingPathVariableException","message":"Missing
URI template variable 'test' for method parameter of type
String","path":"/example"}
I know that I have everything else wired up correctly, other controllers work.
I feel like I must be missing some fundamental principal here.
Thanks in advance.
Spring support different ways how to map stuff from the url to method parameters: request parameters and path variables
Request Parameters are taken from url-query parameters (and request body, for example in http-POST requests). The annotation to mark the java method parameter that should take its value from a request parameter is #RequestParam
Path Variables (somtimes called path templates) are parts of the url-path. The annotation to mark the java method parameter that should take its value from a request parameter is #PathVariable
Have a look at this answer of mine, for an example an links to the Spring Reference.
So what your problem is: you want to read a Request Parameter (from the url-query part), but used the annotation for the Path Variables. So you have to use #RequestParam instead of #PathVariable:
#RestController
public class TestController {
#RequestMapping("/example")
public String doAThing(#RequestParam("test") String test) throws MessagingException {
return "Your variable is " + test;
}
}
If you are using path variable, then it has to be part of the URI. As you have not mentioned in the URI but used in the method arguments, spring tries to find out and assign this value from the path URI. But this path variable is not there in the path URI , therefore throwing MissingPathVariableException.
This should work.
#RestController
public class TestController {
#RequestMapping("/example/{test}")
public String doAThing(
#PathVariable String test
) throws MessagingException {
return "Your variable is " + test;
}
}
And your curl request would be like
curl http://localhost:8080/example/foo
//here the foo can be replace with other string values
The reason why it's not working is that there are two ways to pass parameters to a REST API implementation using RestController. One is the PathVariable, the other is RequestParam. Both of them need names to be specified in the RequestMapping annotation.
Check out this excellent resource that explains RequestMapping in detail
Try this for your solution.
#RequestMapping("/example/{test}", method= RequestMethod.GET)
public String doAThing(
#PathVariable("test") String test
) throws MessagingException {
return "Your variable is " + test;
}
The solution for me was:
#RestController
#RequestMapping("/products")
#EnableTransactionManagement
public class ProductController {
#RequestMapping(method = RequestMethod.POST)
public Product save(#RequestBody Product product) {
Product result = productService.save(product);
return result;
}
}

How to map REST parameters to complex object?

I want to create a REST service with spring that takes a bunch of parameters. I'd like these parameters to be mapped automatically into a complex transfer object, like:
#RequestMapping(method = RequestMethod.GET)
#ResponseBody
public String content(#RequestParam RestDTO restDTO) {
Sysout(restDTO); //always null
}
public class RestDTO {
private boolean param;
//getter+setter
}
But: when I execute a query like localhost:8080/myapp?param=true the restDTO param remains null.
What am I missing?
Try with localhost:8080/myapp?param=true.
Probably a case where another pair of eyes sees the obvious :)
EDIT
Remove #RequestParam from method signature, works for me.
It turned out I have to omit the #RequestParam for complex objects:
#RequestMapping(method = RequestMethod.GET)
#ResponseBody
public String content(RestDTO restDTO) {
Sysout(restDTO);
}
So, I see few problems (if it's not mistyping of course):
localhost:8080/myapp&param=true "&" isn't correct, you have to use "?" to split params from URL like localhost:8080/myapp?param=true.
I don't see mapping value in #RequestMapping(method = RequestMethod.GET) (But if you caught the request you've made correct configuration).

Pass javascript value to controller in spring mvc

I am new with Spring mvc. I need to pass an javascript variable to controller. How to achieve this??
Form tag solution is not appropriate in case of my application.
I need to pass this start variable of JS to my controller.In some cases this variable can be null or not available as per requirements.
Please suggest asap!!!
My JS code is:
function clickPaginate(start){
var X = '<%=url%>';
window.location.href=X+'/library/${publisher}';
}
and controller is:
#RequestMapping(value = "/library/{publisher}", method = RequestMethod.GET)
public String getPublisherDetails(#PathVariable("publisher") String publisher, ModelMap model) throws FeedsException {
}
There is an annotation #RequestParam that you'll have to use in the method. In your case
window.location.href=X+'/library/${publisher}?foo=bar';
foo is the request parameter with value bar that you are passing to your method.
Your method should be like
public String getPublisherDetails(#RequestParam("foo") String foo, #PathVariable("publisher") String publisher, ModelMap model)
Check out this mvc doc

Categories