#Controller, #Service, #Repository beans fails on #EnableTransactionManagement in mode = AdviceMode.PROXY or default fails - spring

Why using #EnableTransactionManagement in default mode or PROXY mode attempts against beans creation like #Controller, #Service, and #Repositories. I don't discard another kind of beans targeting this bad behavior.
I have a project with:
SpringBoot 2.1.8.RELEASE + JPA + Rest Controller
PostgreSQL 9.6
#Transactional annotation on methods like save, update and delete (also, batch delete)
It creates proxy classes and nulls the remaining beans in the ApplicationContext.

The default mode is PROXY. When ASPECTJ advice mode is set, all the beans are injected in the right place. Check Spring current docs on the subject.
The mode() attribute controls how advice is applied: If the mode is AdviceMode.PROXY (the default), then the other attributes control the behavior of the proxying. Please note that proxy mode allows for interception of calls through the proxy only; local calls within the same class cannot get intercepted that way.
Note that if the mode() is set to AdviceMode.ASPECTJ, then the value of the proxyTargetClass() attribute will be ignored. Note also that in this case the spring-aspects module JAR must be present on the classpath, with compile-time weaving or load-time weaving applying the aspect to the affected classes. There is no proxy involved in such a scenario; local calls will be intercepted as well.
Like this:
Still, #Transactional methods fail. Due to "TransactionRequiredException", so ASPECTJ does not solve the problem in persistence layer, only grants beans injection (maybe no platform transaction manager is created). What to do next?
See the transaction exception:
!!! Solution:
When working with transactions, the scope has to be shared in the beans chain: #Service(also, caller method)<-#Repository(also, transactional method), #Service context (class, method) shall be marked as #Transactional. Applies to annotated methods or classes in the call stack that ends in transactional operation (bottom-up approach).
Annotation sequence:
#EnableTransactionManagement (in #Configuration alike classes or #SpringBootApplication -autoconfiguration-)
#Transactional annotated method/classes in beans injection chain (bottom-up: persistent method/class, then #Service/#Component layers)
#Autowired annotation on beans candidates (Service instance in #Controller class, Repository instance in #Service class)
Note: Spring AOP does not create proxy properties from functional interfaces based features, only object instances so recommended is using methods encapsulating persistence logic.
e.g
Function<T, R> function
BiFunction<T1,T2,R> function
Supplier<T> supplier
...

Related

Spring #Transactional and #Service

I'm working in a company where JPA #transactional are used within #Component beans. I've always been told that #Transactional should be used inside #Service beans. Does someone could explain spring mechanisms differences between those and what are the best pratctices .. and why
There is no difference.
Also, #Service and #Component are the same. #Service is just a stereotype that developers often use to indicate that the Spring Bean is kind of a Service (maybe in a DDD meaning or not)
First of all, there is no difference.
From the spring javadoc
#Component
Indicates that an annotated class is a "component". Such classes are considered candidates for auto-detection when using annotation-based configuration and classpath scanning.
...
#Transactional
Indicates that an annotated class is a "Service", originally defined by Domain-Driven Design (Evans, 2003) as "an operation offered as an interface that stands alone in the model, with no encapsulated state."
May also indicate that a class is a "Business Service Facade" (in the Core J2EE patterns sense), or something similar. This annotation is a general-purpose stereotype and individual teams may narrow their semantics and use it as appropriate.
This annotation serves as a specialization of #Component, allowing for implementation classes to be autodetected through classpath scanning.
Frankly speaking, they behave in the same way.
By using #Transactional annotation on a public method or class it simply creates a proxy with transaction code for you.
IMO great explanation of #Transactional
Spring Stereotype Annotations

Why proxy is not used to autowire

I can not find any reason why every autowired bean are not autowired by proxy. I know that becasue #Transactional annotations do not work and I checked autowired component during debugging in eclipse. Of course every component implements some interface and I use #Autowired annotations in relation to the interface.
I have only one configuration of aop:
<tx:annotation-driven transaction-manager="transactionManager" />
I use JPA with hibernate, spring-mvc,spring-webflow, spring-security and spring-data. Interfaces which extends org.springframework.data.repository.CrudRepository are autowired by proxy. But my components are not. For example I have class MyClass which implement MyInterface:
#Service
public class MyClass implements MyInterface {
#Autowired
MyCrudReposiotry reposiotry;
....
}
If I autowire MyInterface somewhere:
#Autowired
MyInterface mi;
then mi is just reference to MyClass object, repository is refrence to proxy org.springframework.aop.framework.JdkDynamicAopProxy. Very interesting is that in testing mi is reference to proxy. My test's context does not contain web-flow and mvc configuration.
Maybe there is some indirect aop configuration which I should check. What can switch the autowiring by proxy off?
My guess is that you are scanning for the same components twice. You probably have a in your root context (for the ContextLoaderListener) and one for the DispatcherServlet. NO if the both scan for the same classes you end up with duplicated (and one proxied and one non proxied instance).
Proxying and auto wiring are independent of each other. When you use #AutoWired it finds another bean that implements the required interface and injects it. The bean instance it finds might be a normal object or a proxy - it doesn't matter to Autowired.
Proxies are created for certain beans automatically by spring. As you have noticed one scenario in which this happens is when you use #Transactional. When the spring container instantiates a bean which has the #Transactional annotation the object gets wrapped in a proxy. The actual object is replaced by the proxy in the context. This is done so that spring can intercept calls to those methods and add the begin / commit transaction calls before and after the method call. This is implemented by the spring-aop module. Any feature that relies on AOP (#Transactional, #Secured) will result in creation of a proxy.
The other case where proxies are used is to create an implementation on the fly. In case of the CRUDRepository you are required to only implement the interface. The implementation of that is created on the fly using the same proxy infrastructure.

Spring-data-mongo: MongoRepository not being wired unless I add #Component annotation

I am having a little weird behavior with my spring-data-mongo where my repository package is not being scanned by the <mongo:repositories/> tag. I am using spring 3.2.3.RELEASE with spring-data-mongo 1.2.1.RELEASE.
I have a project called edowmis and in it there are 2 maven modules, datalayer and web which a webapp.I am using the datalayer in isolation so the other module can be ignored. I have an application context for datalayer
So I wanted to test my setup by writing a small Unit/Integration test but I've noticed I can't autowire my UserRepository because It says there isn't such a bean
Since I am using IntelliJ I can see certain visuals when things are ok and not ok. I've addec <context:component-scan/> to my application context but no result.
But when I add the #Component annotation it has started identifying the Class.
all information you might need is on pastie.org
Is the #component or #Repository really necessary or something is wrong with my configuration?
Yes, the #Component or #Repository is necessary. The scan simply indicates that spring should look for classes identified via annotations (#Component, #Repository, #Service) and load them as beans. If you don't use repository or component scan, you would have to manually instantiate all spring-managed beans via XML configuration or Java configuration.
You have to tell spring which classes to turn into beans as it doesn't assume everything in the classpath is supposed to be a spring-managed bean, which is why you need to use the annotations.

Using proxy-target-class="true" with Spring beans

Im using Jersey Rest and want a Jersey filter to have access to some spring beans.
however as I've discovered from other threads, Jersey does not obtain Spring beans if they are Java proxies as opposed to generated java proxies. I want to add the proxy-target-class="true"
What are the impacts of doing so and also can this just be set on a single bean or does it need to be set on all referenced beans?
By setting proxy-target-class="true" you will be using CGLIB2 for your proxies, instead of jdk proxys.
The implications are the following, as described in the documentation:
final methods cannot be advised, as they cannot be overriden.
You will need the CGLIB 2 binaries on your classpath, whereas dynamic proxies are available with the JDK. Spring will automatically
warn you when it needs CGLIB and the CGLIB library classes are not
found on the classpath.
The constructor of your proxied object will be called twice. This is a natural consequence of the CGLIB proxy model whereby a subclass
is generated for each proxied object. For each proxied instance, two
objects are created: the actual proxied object and an instance of the
subclass that implements the advice. This behavior is not exhibited
when using JDK proxies. Usually, calling the constructor of the
proxied type twice, is not an issue, as there are usually only
assignments taking place and no real logic is implemented in the
constructor.
Also, you should be able to make a "target-proxy" for a specific component by using
proxyMode=ScopedProxyMode.TARGET_CLASS
Forcing a CGLib-Proxy although the controller formally implements an interface (SpringBoot 1.2.3.RELEASE with Spring 4.1.6.RELEASE):
#Controller
#Scope( proxyMode = ScopedProxyMode.TARGET_CLASS )
public class ServiceImpl implements ServiceIntf
{ .... }
This enables valid and working #RequestMapping and #Transactional annotations
Use the following annotation in Java Spring Config class:
#EnableAspectJAutoProxy(proxyTargetClass = true)
This is the way I made my test working:
MyTarget target = new MyTarget();
AspectJProxyFactory factory = new AspectJProxyFactory(target);
factory.setProxyTargetClass(true);

Autowired spring bean is not a proxy

I'm working on a very small application connecting to a MySQL database.
I'm trying to create table record but getting 'no transaction in progress'.
I have all the right stuff in place:
a service interface MyService and its implementation MyServiceImpl
I have annotated the service impl with #Service
In the controller I used the interface name for the field #Autowired MyService
I have the correct transaction configuration as it was originally generated by roo
There is a public method MyService.create(...) which MyServiceImpl implements
But,
When I remote debug and inspect the controller's myService field what I see is something like
com.some.package.services.MyService#12345 (and NOT something like $Proxy73) which to me is not right, because what should be autowired is the proxy not he target bean (which is what I think this is). If I'm correct then it makes sense that there is no transaction as the annotation would only kick in when invoking a public method annotated with #Transactional on a proxy.
Please tell me why is spring injecting the target bean in this setup.
Thanks
If you have AspectJ-enabled transaction management (<tx:annotation-driven mode="aspectj" .../>) application of transactions happens in-place in the same class, either during build (compile-time weaving) or on startup (load-time weaving).
No new classes are created (like when using cglib) and no proxies (like with ordinary interface-based AOP in Spring). Instead bytecode of MyServiceImpl was modified directly without you even noticing. Unfortunately the only way to see AOP is to decompile your classes. If you use javap -c MyServiceImpl you'll find plenty of references to Spring transaction layer.
If you are using Spring MVC, make sure to scan specific controller classes alone in servlet context file. Otherwise it will scan 2 times and transaction is not available on the application context.

Resources