I am designing a REST controller layer with the concept of different versioning which might happen in the future.
I am thinking of having separate classes with version number as follows.
#RequestMapping("/v1/api")
#RestController
class V1RestController {
}
#RequestMapping("/v2/api")
#RestController
class V2RestController {
}
Or V2RestController might extend V1RestController depending on the requirements. This is just a draft idea. But my question is if there is any Spring MVC api which can catch the URL and look up the version '/v1/api or /v2/api' and delegate the request to the right controller.
Based on my research, the best way is to make it backward-compatible, but i am sure that the reality is different and there would be some cases to have different implementations.
I know that there are other ways to design the rest controller layer for different versioning, but for now, i would like to take this approach.
Any help would be appreciated.
But my question is if there is any Spring MVC api which can catch the URL and look up the version '/v1/api or /v2/api' and delegate the request to the right controller.
DispatcherServlet intercepts the request (what to intercept it looks in "web.xml" ), and then DispatcherServlet looks at the request URL and looks for the controller whose "value" parameter (the "#RequestMapping" annotation) matches the request URL, if a match is found: control is transferred in the corresponding controller. Something like this.
Related
Are there conventions for naming methods in the Restful spring boot conrtoller layer ?
I am in dilemma choosing the two name - getSomeData vs fetchSomeData.
Is it OK to use HTTP Verbs (get,post,put) inside controller method names?
I think the most important thing is to be consistent in all your Controllers and to be explicit about what the method is supposed to be doing. It is completely ok to use HTTP verbs in the method names, especially in regards to GET. But when you have POSTs for example, that is usually a creation of a resource, so a method called createWhateverResource instead of postWhateverResource. The important thing is to be clear and let the name of the method be self-explanatory.
I checked a bit on the net. My conclusions:
There are no official naming rules
Official Spring Boot documentation uses short names: all(), one(), etc.
Names for the URLs are most important, method names are secondary
You never call these methods directly in code, they are only called by Spring framework.
A related note - for methods returning HTML (using Thymeleaf templates) I would probably call the methods by the page that they return: home(), orderDetails(), etc. Again for the same reason - we never call the methods directly. At the same time, it is very clear that #Controller and #RestController classes contain only methods returning HTTP responses to specific endpoints. Therefore, the verbs are probably not necessary.
I'm wondering is it possible to have path variable in server.servlet-path with DispatcherServlet? I know of course it possible in controller, but I'd like to have it in one place instead of updating 70 endpoints.
Like:
server.servlet-path=/{client-name}/api/v4
And for example that client-name will be available in request attributes, headers, etc.
Or I need to implement my own dispatcher which will do that logic?
Since REST based controller methods only return objects ( not views ) to the client based on the request, how can I show view to my user ? Or maybe better question what is a good way to combine spring-mvc web app with REST, so my user always get the answer, not in just ( for example ) JSON format, but also with the view ?
So far as I understood, REST based controller would be perfectly fitting to the mobile app ( for example twitter ), where views are handled inside the app and the only thing server has to worry about is to pass the right object to the right request. But what about the web app ?
I might be wrong in several things ( correct me if I am ), since I am trying to understand REST and I am still learning.
To simplify things - you basically have two options:
1) Build Spring MVC application.
2) Build REST backend application.
In case of first option - within your application you will have both backend and frontend (MVC part).
In case of second option you build only backend application and expose it through REST API. In most cases, you will need to build another application - REST client for your application. This is more flexible application because it gives you opportunity to access your backend application from various clients - for example, you can have Android, IOS applications, you can have web application implemented using Angular etc...
Please note, that thins are not so simple, you can within one application have both REST backend and REST client etc... This is just very very simplified in order that you get some general picture. Hope this clarified a little things.
There is some additional clarification related to REST and views worth learning. From your question, I can see that you mean "view" in a sense of UI(user interface) and typical MVC usage. But "view" can mean different things in a different contexts.
So:
JSON can be considered as a view for data
JSON is a representation of the resource, just like HTML is
JSON doesn't have style (unless you are not using a browser
extension, which most the users are not using)
The browser is recognizing HTML as a markup language and applying a
style to it
Both are media types
Both JSON and HTML are data formats
Both can be transferred over the wire
This method returns a view
#RequestMapping("/home")
String home(Model model) {
return "home"; // resources\templates\home.html
}
This method Returns String
#RequestMapping(value = "/home")
#ResponseBody
public String home() {
return "Success";
}
If you annotate a method with #ResponseBody, Spring will use a json mapper to generate the response. Instead of annotating every method with #ResponseBody you can annotate your class with #RestController.
If you want to return a view, you need to annotate the class with #Controller instead of #RestController and configure a viewresolver. Bij default spring will use thymeleaf as a viewresolver if you have spring-web as a dependency on the classpath. The return type of the method is a String that references the template to be rendered. The templates are stored in src/main/resources/templates.
You can find a guide on the spring website: https://spring.io/guides/gs/serving-web-content/
First of all my application is build with spring boot and security.
So I have several rest controllers (resources). One controller provides multiple methods to get/post different kind of data. But I have cases where some methods should be public and others needs authentication.
For example:
GET /api/object/method1 <-- Needs authentication
GET /api/object/method2 <-- Public
POST /api/object/method3 <-- Needs authentication
POST /api/object/method4 <-- Public
What is best practice to secure this resource? I can't secure url with antMatcher with following pattern /api/object/**. Because then the public methods would be secured as well. Also I can't secure by request type (GET, POST).
One option I thought about was using only method level security (eg #Secured etc). This would mean that I need to annotate a lot of methods.
Another thought that comes to mind is dividing resource to 2 parts.
For example creating
ObjectResource.java
ObjectResourcePublic.java
One controller base URL would be /api/public/ and second simply /api/
Then I could use antMatcher for these URLS.
Is my only option to secure every path separtely or every method separetly?
What other options do I have to do this kind of partial securing one resource?
You may use below methods apart from above mentioned methods.
1. Write Interceptor/filter
2. Use Aspect and define advise
I want to use Spring MVC 3.0 to build interfaces for AJAX transactions. I want the results to be returned as JSON, but I don't necessarily want the web pages to be built with JSP. I only want requests to the controllers to be intercepted/routed through the DispatcherServlet and the rest of the project to continue to function like a regular Java webapp without Spring integration.
My thought was to define the servlet-mapping url pattern in web.xml as being something like "/controller/*", then have the class level #RequestMapping in my controller to be something like #RequestMapping("/controller/colors"), and finally at the method level, have #RequestMapping(value = "/controller/colors/{name}", method = RequestMethod.GET).
Only problem is, I'm not sure if I need to keep adding "/controller" in all of the RequestMappings and no matter what combo I try, I keep getting 404 requested resource not available errors.
The ultimate goal here is for me to be able to type in a web browser "http://localhost:8080/myproject/controller/colors/red" and get back the RGB value as a JSON string.
You are not correct about needing to add the entire path everywhere, the paths are cumulative-
If you have a servlet mapping of /controller/* for the Spring's DispatcherServlet, then any call to /controller/* will be handled now by the DispatcherServlet, you just have to take care of rest of the path info in your #RequestMapping, so your controller can be
#Controller
#RequestMapping("/colors")
public class MyController{
#RequestMapping("/{name}
public String myMappedMethod(#PathVariable("name") String name, ..){
}
}
So now, this method will be handled by the call to /controller/colors/blue etc.
I don't necessarily want the web pages to be built with JSP
Spring MVC offers many view template integration options, from passthrough to raw html to rich templating engines like Velocity and Freemarker. Perhaps one of those options will fit what you're looking for.