Spring Java config, #Autowire vs. Constructor Injection, #Transactional and CGLIB - spring

We've been using #Autowired plus Java-based Spring configuration with some success but now, we're losing control. Everyone is starting to add autowired dependencies everywhere, creating cycles and strange bugs.
So we are considering using constructor injection and autowiring of Spring configurations.
Old:
class Bean {
#Autowired Foo foo;
}
#Configuration
#Import( FooCfg.class )
class BeanCfg {
#Bean public Bean bean() { return new Bean(); }
}
New:
class Bean {
public Bean(Foo foo) {...}
}
#Configuration
class BeanCfg {
#Autowired FooCfg fooCfg;
#Bean public Bean bean() { return new Bean(fooCfg.foo()); }
}
This works pretty well (and it drives people to split beans instead of creating monsters with 10+ constructor arguments).
But it fails when Bean has a method annotated with #Transactional since CGLIB then tries to create a proxy which fails since it can't find a no-argument constructor.
What's the solution for this?

You have a couple of possible of solutions
Introduce interfaces your classes
Upgrade the Spring Version to at least 4.0
Add protected no-arg constructor
Introduce Interfaces
When introducing interfaces for your classes you can drop the usage of CgLib. Spring will then be able to use JDK Dynamic Proxies which work around interfaces. It creates a proxy around an already existing bean instance and that proxy implements all the interfaces of the class it is wrapping. That way it doesn't matter if your class has a no-arg constructor or not.
Upgrade to Spring 4
In Spring 4.0 support was added to allow proxying of classes with a missing no-arg constructor (See SPR-10594). To enable this upgrade your Spring version and add Objenesis to your classpath, Spring 4 comes with its own repacked cglib version so that shouldn't be needed anymore.
One thing to note is that you should have a constructor with no logic if you do null checks or init logic in the constructor it might fail in the case where cglib creates an instance. I would suspect that it pass null to all the constructor arguments (or some default for primitives).
Added protected no-arg constructor
Cglib needs to be able to create an instance which is used to wrap the actual class. It should be enough to have a protected constructor in your classes so that cglib can call it.

Related

Partially using Spring Dependency Injection during migration

I´m currently migrating an existing project to Spring. I´ve started to use dependency injection on some newer components that are loosely coupled, the project itself is however very messy, tightly coupled and it´s impossible for me to use DI entirely and I need to change the code step by step.
The "starting point" of where dependency injection is used is a component, that itself has also some dependencies which cannot be injected and have to be passed through a constructor. See this example
#Component
public class FromHellToDependencyInjectionHeaven extends ComplicatedMessyBaseComponent{
#Autowired
private InjectedComponentFromHeavenOne componentOne;
#Autowired
private InjectedComponentFromHeavenTwo componentTwo;
private UninjectableMess uninjectableMess;
/*
* Constructor that has to stay for now because of the ComplicatedMessyBaseComponent
* clashes with #Component
*/
public FromHellToDependencyInjectionHeaven(MessyDependencyOne dependencyOne,
MessyDependencyTwo dependencyTwo, UninjectableMess uninjectableMess){
super(dependencyOne,dependencyTwo);
this.uninjectableMess = uninjectableMess;
}
}
Here comes the problem:
To use #Autowired, the component that uses the dependencies has to be either a #Service or a #Component, otherwise I get
Autowired members must be defined in valid Spring bean
(#Component|#Service|...)
But when I do that, I run into complications with the existing constructor that I cannot remove.
Class doesn't contain matching constructor for autowiring
One idea was to tell Spring to disable the constructor dependency injection for this class, but I haven´t found any possible solution for that.
How can I partially use dependency injection in my project?

Spring: #Bean can still work without #Configuration

From https://projects.spring.io/spring-framework/ I have a spring framework hellpworld program. I delete the annotation #Configuration. However the program could still run as before. Why? What is #Configuration role here?
You can still mark the class with #Component for #Bean instances to be available to program. when you do that it is called lite mode. In this mode you can not use 'inter-bean references' , means referring other instance via methods.
On the the other hand #Bean with class #Configuration is wrapped in side cglib wrapper where any calls to this bean methods can be intercepted and bean instances can be return from context. Means you can use 'inter-bean references'.
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Bean.html
#Bean Methods in #Configuration Classes
Typically, #Bean methods are declared within #Configuration classes.
In this case, bean methods may reference other #Bean methods in the
same class by calling them directly. This ensures that references
between beans are strongly typed and navigable. Such so-called
'inter-bean references' are guaranteed to respect scoping and AOP
semantics, just like getBean() lookups would. These are the semantics
known from the original 'Spring JavaConfig' project which require
CGLIB subclassing of each such configuration class at runtime. As a
consequence, #Configuration classes and their factory methods must not
be marked as final or private in this mode.
#Bean Lite Mode
#Bean methods may also be declared within classes that are not
annotated with #Configuration. For example, bean methods may be
declared in a #Component class or even in a plain old class. In such
cases, a #Bean method will get processed in a so-called 'lite' mode.
Bean methods in lite mode will be treated as plain factory methods by
the container (similar to factory-method declarations in XML), with
scoping and lifecycle callbacks properly applied. The containing class
remains unmodified in this case, and there are no unusual constraints
for the containing class or the factory methods.
In contrast to the semantics for bean methods in #Configuration
classes, 'inter-bean references' are not supported in lite mode.
Instead, when one #Bean-method invokes another #Bean-method in lite
mode, the invocation is a standard Java method invocation; Spring does
not intercept the invocation via a CGLIB proxy.
And,
#Configuration gives you the ability use many other features with conjunction of other annotations
Importing other config
#Import(DatabaseConfig.class)
resource import #PropertySource("classpath:config.properties")
enable component scan #ComponentScan(basePackages = { "com.sample.*" })
marking profile #Profile("production")
To enable features #Enablexxxx
http://docs.spring.io/spring-framework/docs/4.0.4.RELEASE/javadoc-api/org/springframework/context/annotation/Configuration.html

Spring fallback bean implementation

I'm currently trying to configure Spring Boot (using Java Annotations and ComponentScan) for the following scenario:
Scenario
There's an interface MyService.
I want to provide a default implementation for MyService, let's call it MyDefaultService.
If the component scan detects no other implementation for MyService, Spring should instantiate MyDefaultService as a "fallback".
If there is a different implementation of MyService present, let's say MyCustomService, then that bean should always take precedence over MyDefaultService when autowiring a dependency to MyService. In that regard, MyDefaultService should be recessive (as opposed to #Primary).
Ideally, there should not need to be an additional annotation on MyCustomService to have it "override" MyDefaultService.
Ideally, no explicitly implemented factories or factory methods should be required.
Question
The question is: how do I need to annotate the MyDefaultService class in order to achieve this?
What I tried so far to solve the problem
Annotating MyDefaultService with #ConditionalOnMissingBean(MyService.class). Didn't work because MyDefaultService is never used, even if there is no other implementation of MyService.
There is an annotation called #Primarythat solves the problem. However, it needs to reside on MyCustomService, a class that I try to keep free of additional annotations. Essentially, I need the inverse annotation of #Primary on MyDefaultService. However, I couldn't find such an annotation.
Concrete use case
I am developing a service layer in one project, and a different project will implement a web UI layer on top of it. The UI project has a dependency to the service layer project. However, for certain functionalities implemented at the service layer, I need to know which user is currently logged in at the web context. So I have to define a service interface for that in the service layer project, such that it can be implemented by the UI project. However, for testing purposes in the service-layer project, I need a default implementation of that interface. Also, in case that the UI project team forgets to implement this interface, the app should not crash, but instead instantiate the fallback bean and issue a warning.
Thanks & kind regards,
Alan
I suggest writing an implementation of FactoryBean to do this. Your FactoryBean would scan the bean factory looking for beans that implement MyService, and if it finds one it returns that bean from getObject. If it doesn't, then it can instantiate MyDefaultService directly and return that. Your factory bean then gets annotated with #Primary.
So pieces like this (pseudo-code):
public class MyServiceFactory implements FactoryBean<MyService> {
ListableBeanFactory beanFactory;
public MyService getObject() {
Map beans = beanFactory.getBeansOfType(MyService.class)
if (beans.isEmpty())
return new MyDefaultService(); // plus args, obviously
else
return get_some_bean_from_the_map
}
}
and then
#Primary
#Bean
public MyServiceFactory MyServiceFactory() {
return new MyServiceFactory();
}
Spring will automatically handle the factory bean (i.e. it will make the MyService object available as a bean for injection like normal.
This solution doesn't require any special magic, and it's fairly obvious how it works. You can also handle errant cases such as multiple MyService beans being declared.

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.

How does Spring annotation #Autowired work?

I came across an example of #Autowired:
public class EmpManager {
#Autowired
private EmpDao empDao;
}
I was curious about how the empDao get sets since there are no setter methods and it is private.
Java allows access controls on a field or method to be turned off (yes, there's a security check to pass first) via the AccessibleObject.setAccessible() method which is part of the reflection framework (both Field and Method inherit from AccessibleObject). Once the field can be discovered and written to, it's pretty trivial to do the rest of it; merely a Simple Matter Of Programming.
Java allows you to interact with private members of a class via reflection.
Check out ReflectionTestUtils, which is very handy for writing unit tests.
No need for any setter, you just have to declare the EmpDao class with the annotation #component in order that Spring identifies it as part of the components which are contained in the ApplicationContext ...
You have 2 solutions:
To manually declare your beans in the XML file applicationContext :
<bean class="package.EmpDao" />
To use automatic detection by seeting these lines in your context file:
<context:component-scan base-package="package" />
<context:annotation-config />
AND to use the spring annotation to declare the classes that your spring container will manage as components:
#Component
class EmpDao {...}
AND to annotate its reference by #Autowired:
#Component (or #Controller, or #Service...)
class myClass {
// tells the application context to inject an instance of EmpDao here
#Autowired
EmpDao empDao;
public void useMyDao()
{
empDao.method();
}
...
}
Autowiring happens by placing an instance of one bean into the desired field in an instance of another bean. Both classes should be beans, i.e. they should be defined to live in the application context.
Spring knows the existence of the beans EmpDao and MyClass and will instantiate automatically an instance of EmpDao in MyClass.
Spring uses the CGLib API to provide autowired dependency injection.
References
Usage of CGLib forum comment by Rod Johnson
3.3.1. Injecting dependencies
Pro Spring - Analyzing Spring Dependencies
Further Reading
Introduction to the Spring Framework by Rod Johnson

Resources