While testing the upgrade to Spring Boot 1.5.3.RELEASE, I have seen a lot of 'unable to proxy' warnings:
WARN o.s.aop.framework.CglibAopProxy : Unable to proxy interface-implementing method [public final int org.apache.commons.pool2.impl.BaseGenericObjectPool.getMaxTotal()] because it is marked as final: Consider using interface-based JDK proxies instead!
Our project has been using the Apache Commons Pool2 for some time, and we haven't gotten these warnings so far.
Two main questions:
* is there any 'how to' for using interface-based JDK proxies? We're using the KeyedPooledObjectFactory interface for implementing the connection pool, and the class is further used as a regular @Component;
* should we treat it just as a warning? or is it something that must be solved?
Thanks, in advance!
Comment From: snicoll
Thanks for getting in touch, but it feels like this is a question that would be better suited to Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add some more details if you feel this is a genuine bug.
Comment From: jhoeller
Note that this particular warning comes from https://jira.spring.io/browse/SPR-15436 in Spring Framework 4.3.8, revisiting our CGLIB proxy validation log. In fact, we used to have a broader warn-level log entry for final methods on CGLIB proxy which got lowered to info level back in 4.1...
Fundamentally, CGLIB proxies cannot handle final methods. No matter whether an interceptor is to be applied for the particular method, we cannot even dispatch it to the target instance, so the call ends up in the uninitialized proxy instance... either returning invalid state or failing straight away with an NPE.
Now, if you never call such a method on a CGLIB proxy, you're not going to see any negative effect. There is just always a risk that someone might be calling an affected method in a revision of your application, totally surprised why the call wouldn't work. This is arguably less of an issue with delegate methods which do not appear in a service interface of the affected component.
However, in case of an interface-implementing method, the method would show up in an interface-based proxy as well and appears on the signatures of an injected dependency declared as the interface type. This is the specific case that we're warning about now in 4.3.8, in particular for scenarios where the configuration just got switched from interface proxies to target-class proxies.
The warning is safe to ignore if you're not actually calling the getMaxTotal method through the proxy. Just be aware that the affected component is being proxied in the first place: Did you really mean to apply an interceptor to your ObjectPool? In case of a custom pointcut of yours (e.g. for all get* methods), could you possibly narrow it to exclude that particular component?
Comment From: bogdansolga
Thank you very much for your comments, @jhoeller and @snicoll!
@jhoeller - thank you very much for the very thorough description. It shed some light on the CGLib proxying behavior and on the reported issue's context.
Thank you for clarifying that the warning is safe to ignore. I presume the warnings are displayed because we are using an instance of the GenericKeyedObjectPool class as a return value for a @Bean. It is the only link to the BaseGenericObjectPool class, for which several log statements are displayed.
The answers to your questions:
* Did you really mean to apply an interceptor to your ObjectPool? - not by intent. We are using a GenericKeyedObjectPool connection pool, backed by a KeyedPooledObjectFactory. Both are exposed as Spring @Beans and the proxied objects have been working properly. I am not aware of an easier / alternate way to configure the pool, Spring @Beans wise; if there is a better alternative, I'll switch to it.
* In case of a custom pointcut of yours (e.g. for all get* methods), could you possibly narrow it to exclude that particular component? - if by pointcut you are referring to AOP pointcuts -- there is no AOP aspect advising any of the connection pool methods.
Wrapping up - as far as I understand, the warnings are displayed due to the CGLib log threshold change from 4.3.8. On the wiring of the @Beans which are bound in the ApplicationContext and (most likely) causing the logged warnings - I'd like to know a better / cleaner approach.
@snicoll - I do not have a StackOverflow account, that's why I posted the questions here.
Comment From: jhoeller
The plain use of a GenericKeyedObjectPool as an @Bean return type wouldn't trigger such a warning: Some AOP advice is being applied to it at runtime, since such a warning is only issued on actual proxy creation for the given target type.
If it's not based on custom advice of yours, maybe it comes in through an implicit interceptor that some @Enable-initiated functionality brings in? I wonder what it could be though since it can't be annotation-driven in this case... i.e. the Commons Pool classes won't have @Transactional or the like on them. You should be able to find out through activating the debug log.
If you're not calling any of those affected methods through the proxy, you can nevertheless safely ignore the warnings. However, if you're not aware of why your pool beans get proxied in the first place, it's worth researching that part at least: Runtime proxies also incur some performance overhead, so it's worth getting rid of them if they don't add clearly defined value.
Comment From: bogdansolga
Thanks a lot for the hints and cues, @jhoeller !
After doing some debugging and commenting some @Enable- initiated advising (mainly @Async and @Cacheable annotated methods), I have found the annotation which caused the warnings to be displayed - the GenericKeyedObjectPool bean had the @RefreshScope annotation on it, hence causing it to be further advised / proxied.
Would it be safe (and sane) to keep the @RefreshScope annotation on that bean? My intent was to have that bean 'refreshable', in the context of future configuration changes and improvements to it.
Comment From: TTcheng
Bean implements interface's method with final keyword will cause this warning. Usually, this warning can be safely ignored . But if you try to call final method via proxy object or obtain proxy object in the final method context,such as call AopContext.currentProxy() in the final method, a NULL or NPE will be produced.