is there a spring property to set transaction mode to aspectJ - spring-boot

I need transactions for private methods and self referenced method (in a spring boot 2.7.5 application). for this documentation suggest "mode=aspectj"
Consider the use of AspectJ (see below) if you need to annotate non-public methods.
My problem all documentation about it seems to rely on xml files.
Is there a property to set this mode?
Are there other things besides needed to get #Transactional working on private methods?

Related

Is an explicit CacheManager bean definition mandatory when using Spring Boot + Spring Cache?

From documentation Spring Boot uses ConcurrentMapCacheManager as CacheManager implementation by default if we don't define own CacheManager bean definition. But I keep getting 'No qualifying bean of type 'org.springframework.cache.CacheManager' available' error eventhough spring-boot-starter-cache and #EnableCaching is there.
Any help would be greatly appreciated.
Best regards,
SetNug
Short answer... NO.
I suspect you are having problems while (integration) testing? If so, then you probably need to declare the appropriate "test slice annotation", that is #AutoConfigureCache; see Javadoc.
To demonstrate, I created a simple example with a test class contained in this module of my SO repository. You must declare the #AutoConfigureCache annotation in configuration (see here) even if your test is a #SpringBootTest.
As Spring Boot's documentation describes, all of Spring Boot's auto-configuration (which is quite extensive) can be a bit much for testing. As such, none of Spring Boot's auto-configuration is enabled by default. Therefore, you must explicitly enable what you want, or, alternatively, you can declare that you want Spring Boot's entire auto-configuration enabled, by replacing the #AutoConfigureCache annotation declaration with Spring Boot's #EnableAutoConfiguration annotation instead.
You are correct that Spring Boot will auto-configure a "Simple" caching provider (i.e. the ConcurrentMapCacheManager, or in other words, a Spring CacheManager implementation backed by a java.util.concurent.ConcurrentHashMap; see here) when no other cache provider implementation (e.g Redis) is present or explicitly declared.
However, Spring Boot auto-configuration is only in effect when your Spring Boot application is an "application", which I have shown here.
Of course, it is also true that if your #SpringBootApplication annotated class is found (in the classpath component-scan) by your test as described, then it will also enable caching without any explicit annotations, such as, no need to explicitly declare the #AutoConfigureCache test slice annotation, even.
NOTE: In my example, I deliberately did not package the source according to the suggested structure. So, if I were to replace the #AutoConfigureCache annotation declaration in my test configuration with #Import(SpringBootDefaultCachingApplication.class) and comment out this assertion from the application class, then the test would also pass. Using the #Import annotation in this way works similarly as if the test class and application class were in the same package, or the application class were in a parent package relative to the test class.
1 last tip... you can always enable Spring Boot debugging (see Baeldung's blog) to see what auto-configuration is applied while running your application, or even while running tests.

Enabling compile-time AspecJ for Spring Method Security

Spring AOP runs everything through proxies which sadly can't be everywhere. For this reason Spring Security's annotations #PreAuthorize, #PostAuthorize, #PreFilter and #PostFilter (also #Secured) will not be taken into consideration when calls are not going through said proxies. Proxies are created only for singletons (#Beans) so We are greatly limited when We want to secure methods on specific objects (such as JPA #Entities) that are not beans. Proxies also won't be called within calling objects (bean calling its methods in context of self - this).
I know that Spring has suppot not only for Spring AOP but also real AOP - AspectJ. Not only that, but it SHOULD support AspectJ out of box. Testament to this is:
#EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, securedEnabled = true, prePostEnabled = true)
When enabled, Spring will require (crash on startup otherwise) aspectj dependency, which is provided within:
'org.springframework.security:spring-security-aspects'
After adding this dependency we will have AspectJ libraries in classpath and will get:
org.springframework.security.access.intercept.aspectj.aspect
with:
public aspect AnnotationSecurityAspect implements InitializingBean
But here it all ends. There is no documentation that I could find that would state how to further enable aspectj weaving. Setting #EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ) certainly DOES something as we lose standard Spring AOP - security annotations stop working anywhere (on Beans) and at the same time they are not weaved with AspectJ.
Does anyone have some knowledge on Spring's support for this out of box (compile-time weaving) and what further configuration is needed? Maybe I need to weave it myself? Do I need some specific libraries for building?
Version: Spring 5.2.1.RELEASE (all packages).
#DimaSan comment helped me find few threads/issues I missed while doing my search and while many of them are too years-outdated I managed to setup my app.
Turns out I was actually very close and by making few updates and changing dependencies/plugins on gradle I have a working environment.
Gradle: 5.6.4
with:
plugins {
id "io.freefair.aspectj.post-compile-weaving" version "4.1.6"
}
dependencies {
aspect 'org.springframework.security:spring-security-aspects'
runtime 'org.springframework.security:spring-security-aspects'
}
Spring setup at 5.2.1.RELEASE with
spring-boot-starter-
web
data-jpa
security
With above setup this is actually only thing needed:
#EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, securedEnabled = true, prePostEnabled = true)
Finally if You are not using Gradle (e.g. want to use STS/Eclipse Run Configuration), you will add:
-javaagent:C:\Users\USER\.gradle\caches\modules-2\files-2.1\org.aspectj\aspectjweaver\1.9.4\<cache-string>\aspectjweaver-1.9.4.jar
.gradle and 1.9.4 being case for my current setup/version.
Note that this is yet untested (but working with JPA/Hibernate) with e.g. Transaction management and I will comment on it once I start using complex transactions where weaving would create issues.

Spring AOP logging

I have a j2ee web application running on Spring framework. I want to implement logging using log4j and Spring's AOP. I am able to log the public methods using custom annotation. I am not able to log private methods using custom annotation. can any one please give reference how to implement custom annotation for private methods.
Spring AOP
Spring AOP doesn't support interception of private methods.
11. Supported Pointcut Designators
Due to the proxy-based nature of Spring’s AOP framework, calls within the target object are by definition not intercepted. For JDK proxies, only public interface method calls on the proxy can be intercepted. With CGLIB, public and protected method calls on the proxy will be intercepted, and even package-visible methods if necessary. However, common interactions through proxies should always be designed through public signatures.
Note that pointcut definitions are generally matched against any intercepted method. If a pointcut is strictly meant to be public-only, even in a CGLIB proxy scenario with potential non-public interactions through proxies, it needs to be defined accordingly.
If your interception needs include method calls or even constructors within the target class, consider the use of Spring-driven native AspectJ weaving instead of Spring’s proxy-based AOP framework. This constitutes a different mode of AOP usage with different characteristics, so be sure to make yourself familiar with weaving first before making a decision.
AspectJ Source Weaving
You can intercept private methods by taking advantage of AspectJ source weaving. Here is a complete working example.

Using Spring AOP uses underneath aspectj?

Hy,
Reading a lot about Spring AOP vs AspectJ, I still have some doubts:
1.)When using Spring AOP with classes annotated with #Aspect and using "aop:aspectj-autoproxy" tag , it can be said that we are using just the annotations of aspectj or besides that it is being used AspectJ too for the weaving?
2) Its said that AspectJ has better performance because the weaving is in compilation time, it means that the target class files are physically changed inserting the aspects in them? is it not a bit aggressive?
3)It said that Spring uses proxys for AOP, so, I undertand that when you get a bean from Spring, Spring builds a proxy in memory that has already inserted the aspects in it, right?
So why is it said that when a method from your proxy bean calls other method in the proxy, the last method will not have aspects?
Thanks
1) using aspectj-autoproxy means that #Aspectannotations are recognized, but Spring proxies are still being created, see this quote from the documentation:
Do not be misled by the name of the element:
using it will result in the creation of Spring AOP proxies. The
#AspectJ style of aspect declaration is just being used here, but the
AspectJ runtime is not involved.
2) AspectJ supports load time weaving, byte code weaving and compile time weaving. There should no difference in performance, it's just a different point in time to weave the aspect in (compilation, third party jars available, class load time), see this answer for further details.
It is actually more transparent once it's set up to have the aspects weaved at these moments, with runtime proxies there are problems when a bean calls itself using this.someMethod, the aspects don't get applied because the proxies get bypassed (#Transactional/#Secured does not work, etc.).
3) Have a look at this picture from the documentation:
With runtime proxies (non AspectJ), Spring leaves the bean class untouched. What it does is it creates a proxy that either implements the same interface as the bean (JDK proxy), or if the bean implements no interface then it dynamically creates a proxy class with CGLIB (subclass of bean).
But in both cases a proxy is created that delegates the calls to the actual bean instance. So when the bean call this.methodB() from methodA, the proxy is bypassed because the call is made directly on the bean and not on the proxy.
Spring AOP can be configured with AspectJ-sytle, ie annotations are parsed to build configuration but AspectJ compiler is not used for weaving. Only a subset of AspectJ annotations and poincut definitions can be used with Spring AOP.
Maybe, but I don't know any class that has complained. However, is possible that some classes don't allow re-weaving when modified by other bytecode tools.
Inner calls are not proxied because they call on this.method() (with this = the target bean begin proxied) and not on proxy.method() so the proxy has no chances to intercept the call. However, Spring AOP proxies usually notices when a target method return this and return itself instead, so calls like builder.withColor(Color.RED).withHat(Hat.Cowboy) will work. Note that in Spring AOP there are always two classes involved: the proxy and the target.

Spring application has Cglib2AopProxy warnings

Upon starting my application, I get numerous warnings along the lines of o.s.aop.framework.Cglib2AopProxy 'Unable to proxy method [public final void org.springframework.jdbc.core.support.JdbcDaoSupport.setDataSource(javax.sql.DataSource)] because it is final: All calls to this method via a proxy will be routed directly to the proxy.' for about a dozen or so functions.
Now I perfectly understand that proxy-based aspects cannot be applied to final methods. However, I did not (on purpose, at least) try to weave any aspects into JdbcDaoSupport. I suspect it comes from <tx:annotation-driven />. Is there anything I can do to silence these warnings or, better yet, exclude those classes from the aspect weaving?
This is most likely caused by the #Transactional annotation, Spring wraps your DAO in a proxy to add the transactional behavior.
I would recommend to make your DAO implement an Interface (create and use an interface for your DAO), this will allow Spring to use a JDK dynamic proxy instead of having to use CGLib.
Using CGLIB has a limitation that methods marked as final in target class can’t be advised as final methods can’t be overridden (CGLIB creates a subclass of target class at runtime) but this limitation disappears in case of using JDK dynamic proxies.
Reference
Maybe you have extended JdbcDaoSupport and added #Transactional annotations.
You can set the Cglib2AopProxy logger to log level ERROR to avoid the warn messages. For example if using log4j and log4j.properties:
log.logger.org.springframework.aop.framework.Cglib2AopProxy = ERROR
You should use interfaces for dependency injection, the most reasons for this are described here and here.
You can read documentation about proxying mechanic for details why you see this warning.
And please vote for feature request of inspection for IntelliJ that may helps us to avoid this warnings. BTW It also contains a good explanation.
Spring Boot now uses CGLIB proxying by default, including for the AOP support. If you need interface-based proxy, you’ll need to set the spring.aop.proxy-target-class to false.
spring.aop.proxy-target-class=false

Resources