SpringAOP-generated Dynamic subclass is missing annotation - spring

I'm trying to use Spring AOP to inject behavoir into an object. The target object has a single method which is the join point for this new behavior. That method also has a custom annotation that I want to be able to read from other unrelated code. Because my class doesn't implement an interface, Spring is using CGLIB to dynamically subclass the target object. The generated subclass doesn't seem to have the annotation added to the original class.
I tried adding the #Inherited annotation to the custom annotation without luck. It turns out #Inherited only applies to classes. This suggests that Spring would have to explicitly apply my annotation to the overridden method in the subclass.
EDIT: I found a workaround and some more information on the problem. It looks like the CGLib people are aware of the issue. Annotations are treated like implementation in Java (rather than like part of the method signature). Overriding methods must re-declare annotations. CGLib doesn't do this (intentionally by the sound of things).
My workaround was to change my reflection logic. Where I was searching for the annotated method on the class passed to me, I now look at the class and it's super classes. I end up locating the method using the superclass (in the case of a proxy), but when I call the method, regular polymorphisim applies. This makes for some ugly reflection code (even more ugly than normal). It also seems like I shouldn't have to compensate for a SpringAOP implementation detail in my code.
It seems like Spring should provide a cleaner way to handle this. If anyone has other suggestions, they would be appreciated.

Are you sure you have the RetentionPolicy on your annotation set to RUNTIME ?

Related

How to use AOP annotation inside method not in method level

I am using Spring AOP to log the DB execution time, but it is applying to the entire method execution time.
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface TrackExecutionTime {
}
Is there any possibility that we can use this #TrackExecutionTime not in the method level but inside a method just above some statement like below -
#TrackExecutionTime
List<Release> releaseList = releaseRepo.findByProductName(productName.toUpperCase());
that way I can able to get only the DB execution time not only the entire method execution time, as my method contains other business logic too which also including if we use the AOP annotation at the method level.
Your question is not AOP-specific, because annotations are a Java language feature. The answer is: Annotations on arbitrary lines of code are not part of the Java language concept, which for you means you also cannot use them for AOP purposes. This is simply a Java limitation. Neither Spring AOP nor native AspectJ can support a feature which does not exist in Java to begin with.
Friendly suggestion: Please learn more about Java first, then get acquainted with some basic software design and clean code principles. Finally, you shall be able to achieve what you want, albeit in a different way from what you just dreamed up here.
Spring AOP default configuration uses proxies to execute the aspect hence only methods can be annotated.
A bit of a detour on the proxies. A proxy wraps a target method so when you call a method elsewhere Spring makes sure to invoke the method on the proxy and that invocation then contains the aspect code which gets executed before, after, around the call itself (depending on the aspect). There can be several proxies wrapping a single class.
Then an option is to add your aspect annotation to the repository method.
If we need to track the execution time only for subset of calls to the method (which sounds a bit strange a requirement) then we can add a wrapper method - say make a Spring-managed Metrics class with a said time tracking method that accepts a lambda and is annotated with the #TrackExecutionTime. The original call would then be something like
metrics.executeTimed(() -> releaseRepo.findByProductName(productName.toUpperCase()));

Kotlin instance variable is null when accessed by Spring proxied class

I have a service class that is being proxied by Spring, like so:
#Service
#Transactional
open class MyService { ... }
If I remove the open modifier, Spring complains that it needs to proxy the class to apply the #Transactional annotation tweaks.
However, this is causing issues when calling a function on the proxied service, which attempts to access a variable:
#Service
#Transactional
open class MyService {
protected val internalVariable = ...
fun doWork() {
internalVariable.execute() // NullPointerException
}
}
The internalVariable is assigned as part of its declaration, does not have any annotations (like #Autowired, etc.), and works fine when I remove the #Transactional annotation and the requirement for Spring to proxy the class.
Why is this variable null when Spring is proxying/subclassing my service class?
I hit a similar issue and the above comments by Rafal G & Craig Otis helped me-- so I'd like to propose that the following write up be accepted as an answer (or the comments above be changed to an answer and they be accepted).
The solution: open the method/field.
(I hit a similar case where it was a closed method that caused the problem. But whether it is a field/method the solution is the same, and I think the general cause is the same...)
Explanation:
Why this is the solution is more complicated and definitely has to do with Spring AOP, final fields/methods, CGLIB proxies, and how Spring+CGLIB attempts to deal with final methods (or fields).
Spring uses proxies to represent certain objects to handle certain concerns dealt with by Aspect Oriented Programming. This happens with services & controllers (especially when #Transactional or other advice is given that requires AOP solutions).
So a Proxy/Wrapper is needed with these beans, and Spring has 2 choices-- but only CGLIB is available when the parent class is not an interface.
When using CGLIB to proxy classes Spring will create a subclass called
something like myService$EnhancerByCGLIB. This enhanced class will
override some if not all of your business methods to apply
cross-cutting concerns around your actual code.
Here comes the real surprise. This extra subclass does not call super
methods of the base class. Instead it creates second instance of
myService and delegates to it. This means you have two objects now:
your real object and CGLIB enhanced object pointing to (wrapping) it.
From: spring singleton bean fields are not populated
Referenced By: Spring AOP CGLIB proxy's field is null
In Kotlin, classes & methods are final unless explicitly opened.
The magic of how Spring/CGLib when & how chooses to wrap a Bean in an EnhancerByCGLIB with a target delegate (so that it can use finalized methods/fields) I don't know. For my case, however the debugger showed me the 2 different structures. When the parent methods are open, it does not create a delegate (using subclassing instead) and works without NPE. However, when a particular methods is closed then for that closed method Spring/CGLIB uses a wrapped object with delegation to a properly initialized target delegate. For some reason, the actual invocation of the method is done with the context being the wrapper with its uninitialized field values (NULLs), causing NPE. (Had the method on the actual target/delegate been called, there should not have been a problem).
Craig was able to solve the problem by opening the property (not the method)-- which I suspect had a similar effect of allowing Spring/CGLib to either not use a delegate, or to somehow use the delegate correctly.

Spring Weaving: #Configurable objects do not get woven correctly if used as a Parameter inside Methods of Autoproxies

Please consider following situation with spring 4.0.7
For Eclipselink, we use a load-time-weaver. So we wanted to experiment with Springs #Configurable annotation using #EnableSpringConfigured with #EnableLoadTimeWeaving at the same time.
This is fully functional, and Spring-Beans are injected perfectly into POJOs during construction. This functionality is helpful for us, because we want to keep some code regarding validation of these POJOs inside these and not somewhere else in a Bean.
SOme of our Spring Context contains Beans that do not implement any interface, because they are local to some package and used only there. Lets say, FooLogicBean is one of them. If this is to be injected into another Bean, and some Spring-AOP-Aspect (not-aspectj) like some performance measurement aspect is in the execution path, Spring will create a CGLIB autoproxy for the FooLogicBean and inject that. This is fully functional and works perfectly too.
Problems arise, when we want to actually use a POJO that is annotated with #Configurable as a parameter in a method of FooLogicBean (like fooLogicBean.doValidate(myPojo); ), respectively a CGLIB Proxy. In this case, some non-trivial magic stops that POJO from being woven thru aspectj (AnnotationBeanConfigurerAspect from spring-aspects). It is even never woven anywhere in the code regardless of calling the aforementioned doValidate() Method.
If we create that POJO inside FooLogicBean, but dont use it as a method Parameter, it gets woven again due to #Configurable.
Without knowing the Autoproxy creation code, we assume some fancy marking routine from hindering a class from being detected by aspectj, if that class was already used in spring-aop. use in this case means Access.
Did anyone experiment with such obscure constellation and knows a solution for that?
Thanks in advance!
Proxies are created by subclassing, i.e. when you create a proxy of an annotated class Foo:
class Foo {
#Bar
void bar() { }
}
the proxy is created by implementing a class
class Foo$Proxy extends Foo {
#Override
void bar() {
// Proxy logic
}
// Overridden methods of Object
}
This makes the Foo$Proxy class a valid Liskov substitute for Foo. However, normal override semantics apply, i.e. non-inherited annotations such as #Bar are not longer present for the overridden methods. Once another annotation-based API processes your beans, all annotations have disappeared which leads to your outcome. This is true for all kinds of annotations. Those on types, methods and method parameters.
But is it avoidable? It most certainly is by using a proxy generator that was written recently and is built with knowledge of what annotations are, something that is not true for cglib which was first shipped in the early days of the Java virtual machine. However, as long as Spring does not move away from cglib, you will have to live with today's limitations.

Custom annotation like #Value

I need to create a means to add a custom annotation like
#Value("${my.property}")
However, in my case I need to get the value from a database rather then a properties file.
Basically I would like to create a bean on container startup that reads in property name value pairs from a database and can then inject these into fields belonging to other beans.
Approach #1:
One way is to create an Aspect, with a point-cut expression that matches any method having this annotation.
Your aspect will then:
Read the property value in the annotation
Look up the required value an inject it into the class.
AOP Kickstart
Here's a guide to getting started with AOP in Spring
http://www.tutorialspoint.com/spring/aop_with_spring.htm
Joinpoint matching
Here's a reference that describes how to create a join-point that matches on annotations: http://eclipse.org/aspectj/doc/next/adk15notebook/annotations-pointcuts-and-advice.html
Approach #2:
Another way is to use a BeanFactoryPostProcessor - this is essentially how a PropertyPlaceholderConfigurer works.
It will look at your bean definitions, and fetch the underlying class.
It will then check for the annotation in the class, using reflection.
It will update the bean definition to include injecting the property as per the value in the annotation.
. . actually I think approach #2 sounds more like what you want - all of the processing happens on "start-up". . . (In actual fact your modifying the bean recipes even before startup). . whereas if you used AOP, you'd be intercepting method invocations, which might be too late for you?
Namespace Handler
If you wanted you could even create your own Spring namespace handler to turn on your post processor in a terse way. Eg:
<myApp:injectFromDb />
as an alternative to:
<bean class="MyDatabaseLookupProcessorImpl etc, etc. />
Update: Approach #3
As of Spring 3.1 there's also the PropertySourcesPlaceholderConfigurer, that will provide most of the plumbing for you, so you can achieve this with less code.
Alternatively you should be able to configure kind of properties repository bean and then use it in SpEL directly in #Value annotation.
Let's say you'd have bean called propertiesRepository in your context that implements following interface:
interface PropertiesRepository {
String getProperty(String propertyName);
}
then on bean where you want to inject values you can use following expression
#Value("#{propertiesRepository.getProperty('my.property')}")
String myProperty;
You can use #Value annotation by injecting database configuration in application environment itself.
I know this is an old question but I didn't find an exact solution. So documenting it here.
I have already answered the same on different forum.
Please refer to this answer for exact solution to your problem.

#XmlSeeAlso Inheritance

First, I am a newbie in the JAXB and Spring world so if I missed something very obvious I would really appreciate it if someone can point it out instead of not replying. :) I tried searching for a solution here but could not find a good answer.
I have a bunch of subclass DTO's(say A1, A2, A3) which inherit from the same abstract class A. I want the result of my rest query to return a list of the subclass type. I have the following class to represent the result
#XmlRootElement(name="result")
#XmlSeeAlso({A1.class, A2.class, A3.class})
public class AResult<T>
{
...
}
Since AResult is generic I would like the #XmlSeeAlso to also be generic and just write something like
#XmlSeeAlso({(subclasses of A.class})
But I do not think that is possible with JAXB from the research I did on this site and elsewhere.
Since we use the annotation-driven tag in the config, it automatically uses the Jaxb2RootElementHttpMessageConverter class. This message converter creates the JaxbContext using the classes defined in #XmlSeeAlso among others. The createMarshaller and getContext methods are immutable in a superclass.
Because of point 1, I can not write a class where I can check if a class is a subclass of class A and then add it to the JaxbContext. I cannot use a custom Jaxb2RootElementHttpMessageConverter or a custom Marshaller.
How do I get around this? BTW, we are using Spring version 3.1.3
Thanks for your help.
JAXB doesn't scan your classpath for classes that might just happen to be subclasses of AResult (that would be rather slow!) but rather relies on the context knowing about all the classes that it might ever have to create instances of. All the #XmlSeeAlso annotation does is extend the context with the additional classes listed.
However, there are a number of other approaches. For example, you could create a class marked with #XmlRegistry that knows how to make the subclasses that you care about. Or you could experiment with using #XmlJavaTypeAdapter. Alas, I've only ever progressed as far as using the #XmlSeeAlso-based approach in my own code, so I can't comment really from experience.

Resources