#Transactional with static method - spring

Why cant we use #Transactional for static methods to manage the transactions in my spring Project ?
#Transactional works well for non static method but not for static methods any specific reason ?

In order to understand why something like what you are proposing does not work you have to first understand at a high level how Spring handles beans that use #Transactional.
When you annotate a method or the class as #Transactional and make it a Spring Bean, Spring effectively creates a proxy for that class (using JDK Dynamic proxies or CGLIB proxies). That means that whenever your class is used (from Spring managed code that is), it's not your code that gets called immediately, but the proxy which first does whatever is needed, and then your code is called (in the case of caching support your code would perhaps not even be called at all).
A key thing to remember here is that the invoking code (the call site if you will) does not change at all, and the invocation of to the required target method (the proxy method) is performed by the JVM using the same bytecode (invokevirtual or invokeinterface).
With that in mind, the reason that static is not supported becomes clear.
You can't create a proxy for static method! Of course Java Dynamic Proxies cannot do this, and neither can CGLIB.
Supporting such a feature would require changing the bytecode of the invoking code, since calling a static method is implemented via invokestatic in bytecode, which hard-codes the target method.
This part of the Spring documentation explains Spring AOP in details

If you're using AspectJ, here's a simple, albeit ugly, workaround:
public static void doWhatever(final String param) {
new Runnable() {
#Transactional
public void run() {
// do whatever in transaction...
}
}.run();
}

This is feasible using:
#EnableTransactionManagement(mode = ASPECTJ) (or its XML equivalent)
all the configuration required to make AspectJ work
registering a custom aspect to handle #Transactional over static methods like this one I just stumbled upon (did not test it)
NB: in this post I asked about how to make package-private methods #Transactional.

Related

Spring AOP pointcut execution not working

I'm working on a Spring Boot project that uses Spring Cloud (io.awspring.cloud:spring-cloud-aws-dependencies:2.4.2) to produce and consume AWS SQS messages. I have several message producers and several message consumers, and all is working fine from that perspective.
I now have a cross cutting concern where I need to set a header on all messages being produced/sent; and to read that header on all messages being consumed (correlationId), and AOP seems like a good fit.
My aspect for handling (receiving) a message works fine:
#Before("execution(* org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(..))")
fun beforeHandleMessage(joinPoint: JoinPoint) {
The class and method that it is targeting is:
package org.springframework.messaging.handler.invocation;
...
public abstract class AbstractMethodMessageHandler<T>
implements MessageHandler, ApplicationContextAware, InitializingBean {
...
#Override
public void handleMessage(Message<?> message) throws MessagingException {
As mentioned, this works great.
However, I can't get my pointcut for sending a message working. This is my aspect:
#Before("execution(* org.springframework.messaging.support.AbstractMessageChannel.send(..))")
// #Before("execution(* io.awspring.cloud.messaging.core.QueueMessageChannel.send(..))")
fun beforeSendMessage(joinPoint: JoinPoint) {
And the class and method that I'm trying to target is this:
package org.springframework.messaging.support;
...
public abstract class AbstractMessageChannel implements MessageChannel, InterceptableChannel, BeanNameAware {
...
#Override
public final boolean send(Message<?> message) {
But it doesn't seem to work. I've also tried writing the pointcut to target the concrete implementation class (as commented out above), but that also does nothing.
I can't see what the difference is between my working pointcut for beforeHandleMessage and beforeSendMethod, other than the pointcut for beforeSendMethod is targeting a final method. Is that relevant?
Any pointers to get this working would be very much appreciated;
Thanks
Spring AOP uses dynamic proxies, i.e. it works by subclassing (CGLIB proxy) or by implementing interfaces (JDK proxies). In your case, you are targeting a class method rather than an interface method. The class method is final, which explains why it cannot work that way, because you cannot override a final method in a CGLIB proxy. What you should do instead is to
target the interface method MessageChannel.send(Message) and
make sure to use JDK proxies, i.e. not the "proxy target class" (CGLIB) mode. In Spring core, JDK proxy mode is the default, in Spring Boot CGLIB mode. So in Boot, you need to manually reconfigure the framework to permit for JDK proxies, which is only possible there via config file, not via annotations (they come too late in the bootstrapping process for Boot).
More specifically, you need this in src/main/resources/application.properties for Spring Boot:
# This works, now we can create JDK interface proxies. The seemingly equivalent alternative
# #EnableAspectJAutoProxy(proxyTargetClass = false)
# where 'false' is even the default, does *not* work in Spring Boot.
spring.aop.proxy-target-class=false
I found the answer from this other SO answer: Spring AOP ignores some methods of Hessian Service
I know that Spring AOP won't intercept local method calls. I.e. the proxy which is applied doesn't intercept the calls if the same object calls its own method, even if it matches the pointcut expression.
The problem was that the send method I was targeting was called by a number of other methods in the class.
Looking at the call stack I found a different method that was the first method called in the class. Changing the pointcut to target that method has worked.

What are the drawbacks of CGLIB proxy over dynamic proxy in Spring AOP?

As I understand it, Spring AOP generally involves:
dynamic proxy for interfaces
CGLIB proxy for those without (except for final methods and classes)
Why not just use CGLIB proxy all the time? I would expect the following gains:
Since its done during compilation, there should be performance gains over dynamic proxying
doesn't have the limiting factor of requiring interfaces
it can be to bypass the proxy if you return impl classes in some service factory
at the cost of configurability without compilation.
I'm not sure I understood the gains of CGLIB as you've presented them in the question.
Both dynamic proxy and CGLIB are created in runtime, it's not relevant to compile-time at all.
Basically, the major drawback of CGLIB is performance.
There are two aspects of performance that can be more or less important depending on the domain:
The Cost of creation of a proxy object
The cost of the Method call on a proxy.
Now, In both cases, the dynamic proxy mechanism is way more lightweight than a CGLIB proxy. That's why spring up to version 5 (mentioned in the question tag) has attempted to create Dynamic proxy if there was an interface and only if it wasn't possible it wrapped the real object with CGLIB.
This has changed in Spring 5 in favor of using CGLIB in any case but there is still a flag that can bring back the old behavior.
Interesting that CGLIB has a kind of advantage that you haven't mentioned that turned to be important to Spring (well, maybe that was the reason of the behavior change in Spring 5, I can't say for sure):
Many companies don't bother to create interfaces for the services and work directly by the implementation, or even if they do - they do not use injection by interface:
public interface MyService {
void foo();
}
#Component
public class MyServiceImpl implements MyService {
public void foo() {... whatever...}
}
#Component
public class AnotherService {
#Autowired // note, this is not an injection by inteface
private MyServiceImpl service;
public void bar() {
// do something
service.foo();
// do something else
}
}
Now, if you'll use a dynamic proxy (which in general could be used if the application code was using the injection by interface) - you'll generate something that implements the interface MyService but can't be injected into AnotherService because the generated proxy doesn't extend MyServiceImpl class. In this case, the CGLIB is the only viable solution.

Clean database with Flyway after each test class

we are in situation where we cannot simple rollback data after test, so we decide to use Flyway java API like this:
#Autowired
protected Flyway flyway;
#AfterEach
public void restoreDatabase() {
flyway.clean();
flyway.migrate();
}
Is possible execute clean and migrate after each test class instead of test method? I need call this in #AfterAll annotated static method, but this type of methods have to be static so I cannot use autowired component Flyway. Can you advice me any workaround? Thank you.
The following solution may help you.
Besides the #Rollback annotation there is also the possibility to mark a class (or method) as "dirty" with the annotation org.springframework.test.annotation.DirtiesContext. This will provide the test cases a fresh context. From the Java Docs:
Test annotation which indicates that the ApplicationContext associated with a test is dirty and should therefore be closed and removed from the context cache.
Use this annotation if a test has modified the context — for example, by modifying the state of a singleton bean, modifying the state of an embedded database, etc. Subsequent tests that request the same context will be supplied a new context.
#DirtiesContext may be used as a class-level and method-level annotation within the same class or class hierarchy. In such scenarios, the ApplicationContext will be marked as dirty before or after any such annotated method as well as before or after the current test class, depending on the configured methodMode and classMode.
Let me show you an example:
#RunWith(SpringRunner.class)
#SpringBootTest
#DirtiesContext(classMode = ClassMode.BEFORE_CLASS)
public class SomeTestClass {
#Autowired
private ExampleController controller;
#Test
public void testSomething() {
//Do some testing here
}
Now in this case, with an embedded DB (like H2), a fresh DB will be started containing no changes from previous transactions.
Please note that this will most probably slow down your test cases because creating a new context can be time consuming.
Edit:
If you watch the log output you'll see that Spring creates a new application context with everything included. So, when using an embedded DB for the test cases, Spring will drop the current DB and creates a new one and runs all specified migrations to it. It's like restarting the server which also creates a new embedded DB.
A new DB doesn't contain any commits from previous actions. That's why it works. It's actually not hacky imo but a proper set up for integration tests as integration tests mess up the DB and need the same clean setup. However, there are most probably other solutions as well because creating new contexts for every test class may slow down the execution time. So, I would recommend to annotate only classes (or methods) which really needs it. On the other hand, unit tests are in most cases not very time critical and with newer Spring versions lazy loading will speed up startup time.

Spring MVC #Configuration class constructor

As part of the Spring MVC initialization, I need to run an action (just calling a method on a 3rd party library) once as a setup operation. I'm working in Spring MVC environment where I don't really have control over the web.xml or anything, so I can't add a servlet context listener or anything. I tried making an implementation of a WebApplicationInitializer but it never seems to get called (no idea why though, or how to try and debug that any further).
If I annotate a class with #Configuration it does get created, so I'm wondering if I can use the class's constructor to perform that setup operation (calling a 3rd party setup method). Is this appropriate/safe to do? Are there any other alternatives for this kind of thing? I'm new to Spring, so I might just be missing something that's meant for this kind of thing.
Thanks
Configuration class would be an appropriate place to contain some initialization logic. You can place it in a constructor, method annotated with #PostConstruct or afterPropertiesSet() method if you implement the InitializingBean interface for example. The difference is that the constructor code will be called before the beans in your configuration class are instantiated, so if your initialization code depends on some Spring beans, go with the #PostConstruct / InitializingBean approach.
Example:
#Configuration
public class Config {
#PostConstruct
public void initialize() {
// Run some action
}
}

Logging with spring-aop

I am trying to add some kind of tracing to my app. It would work like that: I set package name in my config and all calls to public methods of classes in this package are logged.
I can't use weaving here (due to some technical reasons), so I tried to use spring-proxy.
My pointcut
execution(public * com.my.package.*.*(..))
and it works fine. But what Spring uses Proxy or CGLIB to proxy class, so each class should at least
Have parameterless constructor
All methods should be implementations of some interface
Other classes could not be proxied. That is ok for me to do not log them. But spring creates proxies and ruins my app.
How can I tell spring: "do not proxy this class if it has no parameterless constructor and some of its methods are not implementations of interface"?
Not sure about the answer to your question, however, another way to do the tracing, is to use an annotation:
public #interface Monitor {
}
aspect:
public aspect MonitoringAspect {
pointcut methodToMonitor() : execution(#Monitor * *(..));
}
Usage:
#Monitor
public void methodToBeMonitored() {
}
This way you only affect the methods you want to.
I suppose for a big project, this might not work as you want to monitor many methods.

Resources