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.
Related
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've been looking for an answer for a while, but no luck so far, thus I'm coming here for some words of wisdom.
I've created an aspect using #Aspect annotation, because I need to #Autowire some singleton dependencies I've decided to annotate this aspect class with #Component and let the Spring to do the magic. It works, however ...
I'm fairly familiar with AOP concept, what's weaving and different flavors of it (cglib vs aspectj) but it's not fully intuitive to me how it works under the hood.
#Component means a given class will be a singleton within a given context, #Aspect means that the content of an aspect class will be somehow weaved into the target class during runtime/compilation - and this target class is not a singleton but prototype for instance. So what I'm ending up with at the end?
Spring AOP does not do compile-time-weaving and does not modify the code of the advised target. Instead it works with proxies that are weaved around the joinpoints. That is why Spring AOP aspects and be used as (singleton) components, have their fields autowired, etc., like any other Spring Proxy.
It is also the reason why Spring AOP aspects only work for public method executions, not field accesses and the like.
The documentation is quite well written and goes into as much (or as little) detail as one might like:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html
The book AspectJ in Action's section 2.5 is on the internal working of the weaving step, it is only 2 page but gets the point across well.
Luckily the section is available here.
This is for posterity.
I am new to AOP and I am trying to understand the difference between Method Interceptor and MethodAdvice(i.e. MethodBeforeAdvice or MethodAfterAdvice). To me looks like both are doing the same thing i.e. are called on method invocation. When should we use MethodInterceptor vs MethodAdvice.
Take a look at the definition of the org.aopalliance.interceptInterceptor interface (implemented by MethodInterceptor):
public interface Interceptor extends Advice {
}
It's easy to see that a MethodInterceptor actually IS an Advice.
The only difference between an Advice being defined in an #Aspect class and such an Interceptor is that Interceptor implementations can be added to and removed from Spring AOP Proxies at runtime (casting them to 'Advised'), whereas the Advice you're talking about is a more static construct. But their still essential to Spring AOP since their presence tells Spring which beans to wrap in a proxy object during application context startup.
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.
As in the title above, I am confused about pros cons between injecting applicationContext by directly #Autowired annnotation or implementing ApplicationContextAware interface in a singleton spring bean.
Which one do you prefer in which cases and why? Thanks.
Actually, both are bad. Both of them tie your application to the Spring framework, thus inverting the whole inversion-of-control concept. In an ideal world, your application should not be aware of being managed by an ApplicationContext at all.
Once you have chosen to violate this principle, it doesn't really matter how you do it. ApplicationContextAware is the legacy version that has been around at least since Version 2.0. #Autowired is a newer mechanism but they work in pretty much the same way. I'd probably go with ApplicationContextAware, because it semantically makes clear what it is about.
As #Sean Patrick Floyd says, the need of ApplicationContext is often due to a bad design. But sometimes you have no other option. In those cases I prefer the use of #Autowired because is the way I inject all other properties. So, if I use #Autowired for injecting MyRepository, why can't I use it for ApplicationContext or any other Spring bean?
I use Spring interfaces only for those things I can't do with annotations, for example BeanNameAware.
If you need to get a prototype in a singleton then you can use method injection. Basically, you create an abstract method that returns the object you need and spring will return the prototype everytime you call that method. You define the "lookup-method" in your spring config. Here are some links:
http://docs.spring.io/spring/docs/1.2.9/reference/beans.html#beans-factory-method-injection
http://java.dzone.com/articles/method-injection-spring
Since you are not extending any of the spring classes your application is always separated from the framework. Most of the cases you will not wanted to inject the ApplicationContext as it, but will need to inject the beans defined in the ApplicationContext.
The best case is always to stick to the bare minimum, until and unless you have any specific requirement and this is very simple with spring.
So either,
Annotate your beans and scan them in application context, then use #Autowire to wire them up.
Use application context to wire your bean expediencies(old xml style configs). You can use #Autowire with this approach also.
When you want to control the bean life cycle, you can read the API and customize it, but most of the time these general settings will do the job.
Here are some examples.
Spring Auto-Wiring Beans with #Autowired annotation
Spring Auto-Wiring Beans XML Style
Spring IoC container API Docs
There is no need to use ApplicationContext at all.
ObjectFactory
If you need to use prototype scoped beans in a singleton bean, inject an org.springframework.beans.factory.ObjectFactory.
For example using constructor injection:
#Service
class MyClass {
private ObjectFactory<MyDependency> myDependencyFactory;
public MyClass(ObjectFactory<MyDependency> prototypeFactory) {
myDependencyFactory = prototypeFactory;
}
}
Why
Now what's the benefit over using ApplicationContext ?
You can substitute this dependency (e.g. in a test) by simply passing a lambda (since ObjectFactory is a #FunctionalInterface) that returns a stubbed version of it.
While it is possible to stub the ApplicationContext, it is not clear in that case which beans will be looked up and need to be stubbed.