Researching the use of inheritance in Spring MVC.
Is it a good idea to have a base controller that other controllers can extend ?
The base controller would be to hold functionality common to all controllers.For E-g getting a handle to the logged-in user etc.
If using the base controller is not a good idea are there any other suggestions to implement something like what I have mentioned above.
It is perfectly acceptable to have a base controller that other controllers can extend. When Spring introduced #Controller annotations, they paved the way for you to use whatever class hierarchy you want.
Just be aware that as an object oriented design principle, it's good to favor composition over inheritance. As a rule of thumb (not a hard and fast rule) I would recommend moving your common controller code into a class whose interface can be injected into your controllers via #Inject or #Autowired.
Another suggestion for getting a handle to the logged-in user is a little more work but very nice once you have it. See the discussion here about using a current user annotation on your controller method arguments. This is what I do on my project and it works great!
Related
I am actually a EJB developer and very new in spring framework.
i find a couples of conflict conceptually. Like ..
#RestController use by default scope which is singleton. By single object per loc have to manage heavy trafic.
is it a good design?
Of course, it is a good design because the same instance of the object will be reused instead of keep creating it each time you need it. That is the whole point of that design pattern.
Here is a great example where singleton comes to the rescue.
https://rules.sonarsource.com/java/RSPEC-2119
By default, spring will take care of the creation and destruction of all singleton beans, while the prototype has to be manually handled. Therefore in a lot of cases prototype scope is for custom beans made by developers.
In SpringMVC Controller layer, #Scope("prototype") vs #Scope("singleton")
is it a good design?
Yes, all beans in Spring are singletons (by default).
We have 100+ controllers in several applications and it works perfectly.
If you really need to instantiate controllers more than once, you can, of course, consider other bean scopes (see brief explanation of scopes here https://www.baeldung.com/spring-bean-scopes)
I started learning spring MVC And in controller there is list of 14 classes below:
SimpleFormController
AbstractController
AbstractCommandController
CancellableFormController
AbstractCommandController
MultiActionController
ParameterizableViewController
ServletForwardingController
ServletWrappingController
UrlFilenameViewController
AbstractController
AbstractCommandController
SimpleFormController
CancellableFormController
Do I really need to go through all of them? or #Controller (i.e.MultiActionController) is sufficient?
I think all these classes belongs to very old versions of Spring framework and now a days we don't need to learn them. Need Guidance.
I've gotten by with just #Controller on my Spring Boot projects.
I can't think of a case where you need to worry about which class is auto-wired by the annotation, unless you need to write your own implementation for a specific application flow which uses that specific controller. And, again, I've never had to do this. I only have 1 year of experience with Spring in production, however, so keep that in mind.
I'm reading this official page of Spring documentation and then I read this sentence which I didn't understand :
You cannot add advice to final methods when you use Spring MVC. For
example, you cannot add advice to the
AbstractController.setSynchronizeOnSession() method. Refer to Section
10.6.1, “Understanding AOP proxies” for more information on AOP proxies and why you cannot add advice to final methods.
Can anybody explain to me what they mean by this, and specially by advice?
An advice is a method that should be called before or after a method of another class is invoked.
An example could be a logging advice, that is attached to every method of a service to log out the invocation of every service method.
In order to attach an advice to a method, Spring subclasses the class, the method belongs to and overrides the method with an implementation that calls the advice when the method is invoked. Additionaly the proxy method will also call the overwritten method (the super method) to obtain the original functionality.
A final method cannot be overidden, so Spring cannot create a proxy and you cannat attach an advice.
Its a general limitation, that it is impossible to use a subclass proxy for final methods. It is not a special limitation for aspects.
An advice isn't something specific to Spring MVC, but rather a concept from Aspect Oriented Programming (or AOP for short, see this wikipedia page for a general introduction).
The way Spring Beans work, and the way they allow for AOP, is by taken the class you annotated as a bean, and creating a proxy based on that class, which means on-the-fly / at runtime creating a subclass instance that inherits from your class and which provides custom implementations for each method ('overriding' them). As you know, overriding final methods is inherently impossible (that's what makes them final). That's the reason why the documentation states:
you cannot add advice to final methods
I have been looking at various examples of how to use Spring with REST. Our end target is a Spring HATEOAS/HAL setup
I have seen two distinct methods for rendering REST within Spring
Via #RestController within a Controller
Via #RepositoryRestResource within a Repository
The thing I am struggling to find is why would you use one over the other. When trying to implement HAL which is best?
Our database backend is Neo4j.
Ok, so the short story is that you want to use the #RepositoryRestResource since this creates a HATEOAS service with Spring JPA.
As you can see here adding this annotation and linking it to your Pojo you have a fully functional HATEOAS service without having to implement the repository method or the REST service methods
If you add the #RestController then you have to implement each method that you want to expose on your own and also it does not export this to a HATEOAS format.
There is a third (and fourth) option that you have not outlined, which is to use either #BasePathAwareController or #RepositoryRestController, depending on whether you are performing entity-specific actions or not.
#RepositoryRestResource is used to set options on the public Repository interface - it will automatically create endpoints as appropriate based on the type of Repository that is being extended (i.e. CrudRepository/PagingAndSortingRepository/etc).
#BasePathAwareController and #RepositoryRestController are used when you want to manually create endpoints, but want to use the Spring Data REST configurations that you have set up.
If you use #RestController, you will create a parallel set of endpoints with different configuration options - i.e. a different message converter, different error handlers, etc - but they will happily coexist (and probably cause confusion).
Specific documentation can be found here.
Well, above answers are correct in their context still I am giving you practical example.
In many scenarios as a part of API we need to provide endpoints for searching an entity based on certain criteria. Now using JPA you don't have to even write queries, just make an interface and methods with specific nomenclature of Spring-JPA. To expose such APIs you will make Service layer which would simply call these repository methods and finally Controllers which will expose endpoints by calling Service layer.
What Spring did here, allow you to expose these endpoints from such interfaces (repositories) which are generally GET calls to search entity and in background generates necessary files to create final endpoints. So if you are using #RepositoryRestResource then there is no need to make Service/Controller layer.
On the other hand #RestController is a controller that specifically deals with json data and rest work as a controller. In short #Controller + #ResponseBody = #RestController.
Hope this helps.
See my working example and blog for the same:
http://sv-technical.blogspot.com/2015/11/spring-boot-and-repositoryrestresource.html
https://github.com/svermaji/Spring-boot-with-hibernate-no-controller
#RepositoryRestController override default generated Spring Data REST controllers from exposed repository.
To take advantage of Spring Data REST’s settings, message converters, exception handling, and more, use the #RepositoryRestController annotation instead of a standard Spring MVC #Controller or #RestController
E.g this controllers use spring.data.rest.basePath Spring Boot setting as base path for routing.
See Overriding Spring Data REST Response Handlers.
Be aware of adding #ResponseBody as it is missed in #RepositoryRestController
If you not exposed repository (marked as #RepositoryRestResource(exported = false)), use #BasePathAwareController annotation instead
Also be aware of bags
ControllerLinkBuilder does not take Spring Data REST's base path into account and #RequestMapping shouldn't be used on class/type level
and
Base path doesn't show up in HAL
Workaround to fix link: https://stackoverflow.com/a/51736503/548473
UPDATE: at last I prefer not to use #RepositoryRestController due to lot of workarounds.
Can anyone explain what I need to do to implement my own annotation that would add functionality to my web requests?
For example:
#Controller
public class MyController {
#RequestMapping("/abc")
#RequiresSomeSpecialHandling
public void handleSecureRequest() {
}
}
Here #RequiresSomeSpecialHandling would be my own annotation that causes some special work to be done before or after the given web request /abc.
I know that on a very high level I would need to write a bean post processor, scan classes for my annotations, and inject custom mvc interceptors when needed. But are there any shortcuts to simplify this task? Especially for the two examples above.
Thanks in advance,
This kind of Annotations, (that add additional functionality when invoking a method) looks like annotations that trigger an AOP Advice.
#see Spring Reference Chapter 7. Aspect Oriented Programming with Spring
The idea is to use the Annotation to trigger the AOP Advice.
like:
#Pointcut("#target(com.example.RequiresAuth)")
Depends on what you want to do as a result of #RequiresSomeSpecialHandling. E.g. do you want it to influence request mappings or the invocation of the method (i.e. resolving method arguments, processing the return value)?
The support for annotated classes in Spring 3.1 became much more customizable. You can browse some examples in this repo.
Also keep in mind that a HandlerInterceptor in Spring 3.1 can cast the handler Object to HandlerMethod, which gives you access to the exact method including its annotations. That may be enough for what you need to do.
If caching is one of your goals, take a look at the #Cacheable annotation (and its siblings #CachePut, #CacheEvict and #Caching), available as of Spring 3.1.