Rewriting Java Controller Class with Grails REST - java

I have implemented a REST application with Spring at Java. An example of GET and DELETE requests are as follows:
#RequestMapping(method = RequestMethod.GET)
public
#ResponseBody
List<Configuration> getAllConfigurationsInJSON() {
return new ArrayList<Configuration>(configurationMap.values());
}
#RequestMapping(value = "{systemId}", method = RequestMethod.DELETE)
public void deleteConfiguration(HttpServletResponse response, #PathVariable long systemId) throws IOException {
if (configurationMap.containsKey(systemId)) {
configurationMap.remove(systemId);
response.setStatus(HttpServletResponse.SC_OK);
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
I am searching about Grails and want to rewrite my controller with Grails. I read some articles and it shows that there is no need to write that annotations at Grails. I will just define my clousers and it will render my response to JSON object as like my Spring applicaiton. How can I implement them with closures? (I use IntelliJ IDEA 10.3)

There is nothing in this code that can make use of closures.
In grails it may look the same, or you can put the url mappings in UrlMappings.groovy

Related

How to test with Postman a controller's method that has one or more objects parameters (and not simple params) in Spring?

I am a newbie in Spring development. I need to create a simple application, a controller that has a method that takes as parameter an object of a custom designed entity class into the project. The prototype looks like this:
#RestController
public class JobsController {
#PostMapping("/search")
public ResponseEntity<?> search() {
log.info("JobsController -> search method");
//JobSearchEntity jobSearchEntity = modelMapper.map(jobSearch, JobSearchEntity.class);
List<JobEntity> jobs = jobService.searchJobs();
//log.info(String.format("Job found: %s ", jobSearch));
return ResponseEntity.ok(jobs);
}
}
Can someone who is more advanced into this staff with Postman testing tell me how to do that , how to test a controller method which takes parameters?
You can use postman to submit parameters in JSON format after adding # requestbody annotation on the method, or submit parameters directly in form without annotation
You can use this example. Is very simple exemple.
#RestController
#RequestMapping("/root")
public class RootController {
private final RootService service;
public RootController(final RootService service) {
this.service = service;
}
#PostMapping("/exemple")
public void createRoot(#RequestBody final RootDto dto) {
service.createRoot(dto);
}
}
Then you can send request to POST host/root/exemple with your JSON.
More exampls you can find here: https://www.baeldung.com/spring-request-response-body
It seems you are missing an honest search on google about the subject.
You can make use of #RequestBody annotation to accept method arguments.
Check these page for examples --
#RequestBody and #ResponseBody annotations in Spring
https://stackabuse.com/get-http-post-body-in-spring/
https://www.twilio.com/blog/create-rest-apis-java-spring-boot
These set of playlist on youtube are very good starter course for SpringBoot -
https://www.youtube.com/c/JavaBrainsChannel/playlists
Postman Tutorial--
https://www.youtube.com/watch?v=VywxIQ2ZXw4
To get data from api is preferred to use GET method :
#RestController
public class JobsController {
#GetMapping("/search")
public ResponseEntity<?> search(#RequestParam("id") String id,#RequestParam("desc") String desc) {
log.info("JobsController -> search method");
//JobSearchEntity jobSearchEntity = modelMapper.map(jobSearch, JobSearchEntity.class);
List<JobEntity> jobs = jobService.searchJobs();
//log.info(String.format("Job found: %s ", jobSearch));
return ResponseEntity.ok(jobs);
}
}
you call this api with post man this way :
#PostMapping used usually to save new data (example : create job )
Take look on rest resource naming guide

Build a rest wrapper which accepts any kind of request

I want to build a rest wrapper in a spring boot application which accepts any kind of request (API call). Lets assume I have two API calls /employee/123 (GET method) /dept/123 (PUT method). Now When I hit these two requests from postman client, my wrapper should accepts these two types of requests.
I have tried this with Filter and Interceptor. But those didn't work for me. Can any one please explain how to do this.
Not quite clear what's your problem. Is this what you're looking for?
#RestController
public class SampleController {
#GetMapping(path = "/employee/{id}")
public String getEmployee(#PathVariable int id) {
....
}
#PutMapping(path = "/dept/{id}")
public String putDept(#PathVariable int id) {
....
}
}
Or you want an API proxy? So, perhaps, it makes sense to look at Zuul or any similar project?
if you want to accepts any kind of request like POST,GET,DELETE or PUT the dont mention the method of RequestMethod in #RequestMapping and if you want to do different operation depends on Request method then use HttpServletRequest for getting ReuestMethod
eg.
#RequestMapping({ "/employee/{id}", "/dept/{id}" })
public #ResponseBody String demo(HttpServletRequest request, #PathVariable("id") Integer id) {
if (request.getMethod().equalsIgnoreCase("POST")) {
return "POST MEhod";
} else if (request.getMethod().equalsIgnoreCase("GET")) {
return "GET Method";
} else if (request.getMethod().equalsIgnoreCase("PUT")) {
return "PUT Method";
} else {
return "DELETE Method";
}
}

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?

Use ModelAndView in a Rest API app

I'm writing a web app which only consists of Rest API endpoints. There is no jsp, nor any UI written in Java provided by the app. (I'm planning to write the front end in React in future)
Does it make sense to use ModelAndView in my controllers ? I want to do a redirect to another URL ? I see sample codes similar to the following code:
#Controller
#RequestMapping("/")
public class RedirectController {
#GetMapping("/redirectWithRedirectPrefix")
public ModelAndView redirectWithUsingRedirectPrefix(ModelMap model) {
model.addAttribute("attribute", "redirectWithRedirectPrefix");
return new ModelAndView("redirect:/redirectedUrl", model);
}
}
If your controller is always going to redirect, you can just return a String e.g.
return "redirect:/redirectedUrl";
Otherwise, you can return a response entity:
final HttpHeaders headers = new HttpHeaders();
headers.add("Location", "/redirectedUrl");
return new ResponseEntity<Foo>(headers, HttpStatus.FOUND);
I don't think it makes sense to return a ModelAndView if there is no view.

Spring MVC: IP restriction for a single controller method

I need to hide a specific API for requests coming form IP different to a specific one.
For instance this should work if I try to use it and my IP is 192.168.1.1, but not if my IP is 192.168.1.2.
#RequestMapping(value = "/test/{id}", method = RequestMethod.GET)
#ResponseBody
#IpRestricted
public void download(#PathVariable("id") String id) {
...
}
I read I can make it creating a specific annotation, the one I called "#IpRestricted" in this example, but than how can I proceed? There are better solution to this?
I then realized I can make it without using spring security.
I made an annotation like this:
#Retention(RetentionPolicy.RUNTIME)
public #interface IpRestricted {
}
Than I check the request IP address inside a HandlerInterceptor preHandle method:
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod method = (HandlerMethod)handler;
if (method.getMethodAnnotation(IpRestricted.class)!=null) {
if (!request.getRemoteAddr().equals("192.168.1.1")) {
throw new UnauthorizedException("Ip not authorized");
}
}
}
[....]
}
And for the download method:
#RequestMapping(value = "/test/{id}", method = RequestMethod.GET)
#ResponseBody
#IpRestricted
public void download(#PathVariable("id") String id) {
...
}
That's it!
I think the best Spring solution available for this case is the hasIpAddress() method from Spring Security. There are many different ways to configure permissions to your services via Spring Security, and the IP-based solution is also implemented.
Here is a good example of how to set it up.

Categories