Spring #Cachable method within the same class (self-invocation, proxy issue) - What is the best way to solve it? - spring

I'm trying to call a #Cacheable method from within the same class.
And it didn't work. Because of:
In proxy mode (the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation (in effect, a method within the target object that calls another method of the target object) does not lead to actual caching at runtime even if the invoked method is marked with #Cacheable. Consider using the aspectj mode in this case. Also, the proxy must be fully initialized to provide the expected behavior, so you should not rely on this feature in your initialization code (that is, #PostConstruct).
It means, #Cachable(also #Transactional) works by proxy classes which is Spring AOP in. a internal call in the same class make call by 'this' instead of proxy classes.
To solve the problem, I should call a method by proxy or using AspectJ(another AOP).
So, I found 4 solutions.
What is your choice? and why others are not recommended?
Please, share your opinion!
using AspectJ (another AOP)
get the Bean from ApplicationContext and use it
#Service
public class UserService implements Service {
#Autowired
private ApplicationContext applicationContext;
private Service self;
#PostConstruct
private void init() {
self = applicationContext.getBean(UserService.class);
}
}
self-autowiring using #Resource //since Spring 4.3
#Component
#CacheConfig(cacheNames = "SphereClientFactoryCache")
public class CacheableSphereClientFactoryImpl implements SphereClientFactory {
/**
* 1. Self-autowired reference to proxified bean of this class.
*/
#Resource
private SphereClientFactory self;
#Override
#Cacheable(sync = true)
public SphereClient createSphereClient(#Nonnull TenantConfig tenantConfig) {
// 2. call cached method using self-bean
return self.createSphereClient(tenantConfig.getSphereClientConfig());
}
#Override
#Cacheable(sync = true)
public SphereClient createSphereClient(#Nonnull SphereClientConfig clientConfig) {
return CtpClientConfigurationUtils.createSphereClient(clientConfig);
}
}
make the Bean scope of the class as 'prototype' instead of 'singleton'
#Service
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
class AService {
private final AService _aService;
#Autowired
public AService(AService aService) {
_aService = aService;
}
#Cacheable("employeeData")
public List<EmployeeData> getEmployeeData(Date date){
..println("Cache is not being used");
...
}
public List<EmployeeEnrichedData> getEmployeeEnrichedData(Date date){
List<EmployeeData> employeeData = _aService.getEmployeeData(date);
...
}
}
I'm a newbie in spring :)
Actually, I choose the 4th solution, but I felt it isn't a good way. because I just need to call the caching method by proxy, and it make several beans to achieve it.
After reading articles, I think AspectJ is the best choice. It looks cool, Spring recommends it, and many people also recommend too.
But I don't understand how to AspectJ works (I will study) and I also don't know why others is not recommended.
references
Spring Cache #Cacheable - not working while calling from another method of the same bean
Spring cache #Cacheable method ignored when called from within the same class
https://spring.io/blog/2012/05/23/transactions-caching-and-aop-understanding-proxy-usage-in-spring
https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache

Related

Dependency injection through constructor vs property [duplicate]

So since I've been using Spring, if I were to write a service that had dependencies I would do the following:
#Component
public class SomeService {
#Autowired private SomeOtherService someOtherService;
}
I have now run across code that uses another convention to achieve the same goal
#Component
public class SomeService {
private final SomeOtherService someOtherService;
#Autowired
public SomeService(SomeOtherService someOtherService){
this.someOtherService = someOtherService;
}
}
Both of these methods will work, I understand that. But is there some advantage to using option B? To me, it creates more code in the class and unit test. (Having to write constructor and not being able to use #InjectMocks)
Is there something I'm missing? Is there anything else the autowired constructor does besides add code to the unit tests? Is this a more preferred way to do dependency injection?
Yes, option B (which is called constructor injection) is actually recommended over field injection, and has several advantages:
the dependencies are clearly identified. There is no way to forget one when testing, or instantiating the object in any other circumstance (like creating the bean instance explicitly in a config class)
the dependencies can be final, which helps with robustness and thread-safety
you don't need reflection to set the dependencies. InjectMocks is still usable, but not necessary. You can just create mocks by yourself and inject them by simply calling the constructor
See this blog post for a more detailed article, by one of the Spring contributors, Olivier Gierke.
I will explain you in simple words:
In Option(A), you are allowing anyone (in different class outside/inside the Spring container) to create an instance using default constructor (like new SomeService()), which is NOT good as you need SomeOtherService object (as a dependency) for your SomeService.
Is there anything else the autowired constructor does besides add code
to the unit tests? Is this a more preferred way to do dependency
injection?
Option(B) is preferred approach as it does NOT allow to create SomeService object without actually resolving the SomeOtherService dependency.
Please note, that since Spring 4.3 you don't even need an #Autowired on your constructor, so you can write your code in Java style rather than tying to Spring's annotations.
Your snippet would look like that:
#Component
public class SomeService {
private final SomeOtherService someOtherService;
public SomeService(SomeOtherService someOtherService){
this.someOtherService = someOtherService;
}
}
Good to know
If there is only one constructor call, there is no need to include an #Autowired annotation. Then you can use something like this:
#RestController
public class NiceController {
private final DataRepository repository;
public NiceController(ChapterRepository repository) {
this.repository = repository;
}
}
... example of Spring Data Repository injection.
Actually, In my experience, The second option is better. Without the need for #Autowired. In fact, it is wiser to create code that is not too tightly coupled with the framework (as good as Spring is). You want code that tries as much as possible to adopt a deferred decision-making approach. That is as much pojo as possible, so much such that the framework can be swapped out easily.
So I would advise you create a separate Config file and define your bean there, like this:
In SomeService.java file:
public class SomeService {
private final SomeOtherService someOtherService;
public SomeService(SomeOtherService someOtherService){
this.someOtherService = someOtherService;
}
}
In ServiceConfig.java file:
#Config
public class ServiceConfig {
#Bean
public SomeService someService(SomeOtherService someOtherService){
return new SomeService(someOtherService);
}
}
In fact, if you want to get deeply technical about it, there are thread safety questions (among other things) that arise with the use of Field Injection (#Autowired), depending on the size of the project obviously. Check this out to learn more on the advantages and disadvantages of Autowiring. Actually, the pivotal guys actually recommend that you use Constructor injection instead of Field Injection
I hope I won't be downgraded for expressing my opinion, but for me option A better reflects the power of Spring dependency injection, while in the option B you are coupling your class with your dependency, in fact you cannot instantiate an object without passing its dependencies from the constructor. Dependency Injection have been invented for avoid that by implementing Inversion of Control,so for me option B doesn't have any sense.
Autowired constructors provides a hook to add custom code before registering it in the spring container. Suppose SomeService class extends another class named SuperSomeService and it has some constructor which takes a name as its argument. In this case, Autowired constructor works fine. Also, if you have some other members to be initialized, you can do it in the constructor before returning the instance to spring container.
public class SuperSomeService {
private String name;
public SuperSomeService(String name) {
this.name = name;
}
}
#Component
public class SomeService extends SuperSomeService {
private final SomeOtherService someOtherService;
private Map<String, String> props = null;
#Autowired
public SomeService(SomeOtherService someOtherService){
SuperSomeService("SomeService")
this.someOtherService = someOtherService;
props = loadMap();
}
}
I prefer construction injection, just because I can mark my dependency as final which is not possible while injecting properties using property injection.
your dependencies should be final i.e not modified by program.
There are few cases when #Autowired is preferable.
One of them is circular dependency. Imagine the following scenario:
#Service
public class EmployeeService {
private final DepartmentService departmentService;
public EmployeeService(DepartmentService departmentService) {
this.departmentService = departmentService;
}
}
and
#Service
public class DepartmentService {
private final EmployeeService employeeService;
public DepartmentService(EmployeeService employeeService) {
this.employeeService = employeeService;
}
}
Then Spring Bean Factory will throw circular dependency exception. This won't happen if you use #Autowired annotation in both beans. And this is understandable: the constructor injection happens at very early stage of Spring Bean initialization, in createBeanInstance method of Bean Factory, while #Autowired-based injection happens way later, on post processing stage and is done by AutowiredAnnotationBeanPostProcessor.
Circular dependency is quite common in complex Spring Context application, and it needs not to be just two beans referring one another, it could a complex chain of several beans.
Another use case, where #Autowired is very helpful, is self-injection.
#Service
public class EmployeeService {
#Autowired
private EmployeeService self;
}
This might be needed to invoke an advised method from within the same bean. Self-injection is also discussed here and here.
There is a way to inject the dependencies through constructor using #RequeiredArgsContructor annotation from Lombok
#RequiredArgsConstructor
#Service
class A {
private final B b // needs to be declared final to be injected
}
In this way you don't need to specify a constructor

Spring Proxy Creation of Classes annotated with #Configuration or #Component

Spring uses either JDK dynamic proxies or CGLIB to create the proxy for a given target object. If a class is annotated with #Configuration, then CGLIB is used.
However, one limitation of Spring AOP is that once the call has finally reached the target object, any method calls that it may make on itself are going to be invoked against the this reference, and not the proxy. This piece of information is important to remember when using #Transactional and in other places as well.
So having that knowledge, in the code below, is Spring injecting the actual instance or the proxy of SimpleBean?
#Configuration
public class Config {
#Bean
public SimpleBean simpleBean() {
return new SimpleBean();
}
#Bean
public SimpleBeanConsumer simpleBeanConsumer() {
return new SimpleBeanConsumer(simpleBean()); //<---
}
}
And what is the behavior if a class is annotation with #Component?
Let me give you another perspective.
Say there is an another bean AnotherBeanConsumer that also needs a simpleBean. Simple Bean has a Singleton scope:
#Configuration
public class Config {
#Bean
public SimpleBean simpleBean() {
return new SimpleBean();
}
#Bean
public SimpleBeanConsumer simpleBeanConsumer() {
return new SimpleBeanConsumer(simpleBean());
}
#Bean
public AnotherBeanConsumer anotherBeanConsumer() {
return new AnotherBeanConsumer(simpleBean());
}
}
Now the question is, how its possible that two calls to simpleBean() made from different methods simpleBeanConsumer and anotherBeanConsumer return the same instance of the simple bean (since its a singleton obviously)?
IMO (and disclaimer, I'm not affiliated with spring or something), This is the main reason of creating proxies that wrap Configurations.
Now indeed Spring AOP has a limitation of calling methods just as you've stated, however who said that spring under-the-hood uses spring AOP? The bytecode instrumentation done on much lower levels doesn't have a limitation like this. After all creating a proxy means: "create a proxy object that will have the same interface but will alter the behavior", right?
For example if you use CGLIB that uses inheritance you could create a proxy out of configuration that looks like this (schematically):
class CGLIB_GENERATED_PROXY extends Config {
private Map<String, Object> singletonBeans;
public SimpleBean simpleBean() {
String name = getNameFromMethodNameMaybePrecached();
if(singletonBeans.get(name) != null) {
return singletonBeans.get(name);
}
else {
SimpleBean bean = super.simpleBean();
singletonBeans.put(name, bean);
return bean;
}
}
....
}
Of course its only a schematic picture, in real life there is an application context that basically provides the access to the map like this, but you get the point.
If its not enough, then there are some even more sophisticated frameworks that spring must make use of in order to load a configuration (like ASM)...
Here is an example:
If you use #ConditionalOnClass(A.class) and the class doesn't really exist in runtime, how spring can load the bytecode of the configuration that uses this configuration and not fail on something like NoClassDefFoundException?
My point is that it goes far beyond the spring AOP, and has its quirks :)
Having said that, nothing that I've describe above requires the real components to be always wrapped in Proxies of any kind. So in the most trivial case, when SimpleBean does not by itself have some annotations that require proxy generation (stuff like #Cached, #Transactional and so forth), Spring won't wrap the object of that type and you'll get a plain SimpleBean object.

What is the magic behind Field #Autowired

I am currently improving my Spring knowledge. I wonder what really happens when I use Spring annotation #Autowire on a field.
Here is a piece of code :
OutputHelper file
#Component
public class OutputHelper {
#Autowired
#Qualifier("csvOutputGenerator")
private IOutputGenerator outputGenerator;
public void setOutputGenerator(IOutputGenerator outputGenerator) {
this.outputGenerator = outputGenerator;
}
// I can focus only on what my code do because my objects are injected
public void generateOutput(){
outputGenerator.generateOutput();
}
}
CsvOutputGenerator file
#Component
public class CsvOutputGenerator implements IOutputGenerator {
public void generateOutput(){
System.out.println("Csv Output Generator");
}
}
Application file
public static void main(String[] args) {
// Create the spring context
ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/spring-module.xml");
// Get the configured OutpuHelper from the spring-module.xml
OutputHelper output = (OutputHelper) context.getBean("outputHelper");
// Display output from the output configured
output.generateOutput();
}
My configuration file just contain <context:component-scan base-package="com.xxx.xxx.output"/>
When I execute this code all work fine. But what makes me surprised is when I delete the setOutputGenerator in OutPutHelper file, my piece of code keeps working. I tought that with this configuration, the OutputHelper was first created with default constructor and initialized with setter.
I expected an error because the variable outputGenerator was not be able to be initialized.
Is anyone can help me to understand ?
The idea to have fields #Autowired is questionable. It works, but it will difficult other aspects of your implementation (i.e. testing).
There are 3 types of injections:
fields - basically configured applying reflection (Field.set(Object, Object)) directly to the field:
#Autowired
private MyInterface field;
setters - with this approach the configuration of each dependency goes through a property (spring goes through all methods and execute each one annotated with #Autowired using Method.invoke(Object, Object...), thus its value is configured using its setter as follows:
#Autowired
public void setField(MyInterface value) {
this.field = value;
}
constructors - the last, and my preferable approach, the constructor injection. That one basically annotates an constructor with #Autowired and instead of using methods or fields, you can configure your bean directly on your constructor. For that spring will elect the a constructor to be used to instantiate your #Component, and it will use an #Autowired if existent or a empty params constructor, invoking it using Constructor.newInstance(Object...). Example:
#Component
public class Implementation {
private MyInterface field;
#Autowired
public Implementation(MyInterface value) {
Assert.notNull(value, "value should not be null");
this.field = value;
}
}
One of the ideas behind Inversion of Control (or Dependence Injection) is to be able to isolate a piece of code in order to provide decent test implementation support.
In order to go deeper, it is necessary to comment that during a unit test you want the class in its isolated form, all you will use with that class are basically mocks for its dependencies (injections).
So, what are the results:
If you do field injection, it will be quite costly to every single time set the beans using some reflection to configure the bean during your tests (another logic needs to be introduced to configure the bean to be tested).
With setter injection approach you will be able to use your own bean to configure it with mocks necessary to isolate your implementation and test its functionality.
And finally, with the constructor injection approach you will have not only the support to configure your bean, but you will be able to require its dependencies. This means that for every new dependency a new parameter on your constructor is added, this brings you come advantages on development time, for example, you will be able to see on development time the unit tests affected with the introduction of that new dependency (once your IDE will point it out for your).
Simple answer
Actually, the setter is useless, since the CDI use java Reflection to access fields.
It means that fields are no longer accessed by method calls.
Reflection allow iterating throught all fields of a class and check if there are annoted with a specific annotation.
In this case, if a field in your class is annoted With #Autowired (or #Inject wich is more J2E complient), the container will iterate throught searching if there is a registered bean that fits the current property.
Going deeper
When you context is starting, the container iterate classes and search all field annoted with #Inject or #Autowired.
For these fields, it search an available bean.
Here is the must simple example :
public class SpringClassInChargeOfDependencyInjection {
public void handdleInjections(T objectWithInjectableField) {
Class<T> clazz = objectWithInjectableField.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Autowired.class) || field.isAnnotationPresent(Inject.class)) {
//find a bean for the type;
Object injectableBean = getAvailablebean(field.getType());
field.setAccessible(true);
//inject the value into the class, this line explain why the setter is not necessary
field.set(objectWithInjectableField, injectableBean);
}
}
}
}
This is a non-working example just to explain how it works.
Tips
You might consider using #Inject instead of #Autowired, the later was created by Spring, #Inject is a part of the the JSR-330. Spring does understand #Inject as well, you just need to add the javax.inject jar dependency to your project. If later you want to switch from spring to something else (guice for example) you won't have to change all your #Autowired annotations
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>

How to re-inject a transient #ManagedProperty at deserializing?

I'm using Spring and JSF 2 to create a web application.
The business objects are kept in the Spring container, and I inject them in the Managed Beans using the #ManagedProperty, like this:
#ManagedBean
#ViewScoped
public class SomeMB implements Serializable {
private static final long serialVersionUID = 1L;
#Getter #Setter
#ManagedProperty("#{someService}")
private SomeService someService;
// ...
The problem is, I keep getting a NotSerializableException for a class from Spring (ServiceLocatorFactoryBean) that it's being used by the SomeService bean.
If I make it transient, how could I do the re-injection of it after deserializing?
Or, what would be other ways to solve this problem?
I've been reading several other questions similar here, but couldn't find any that dealt exactly with this problem.
Instead of injecting the Spring beans via EL in a #ManagedProperty annotation (executed on the ManagedBean initialization), obtain the beans evaluating the EL at runtime.
With this approach, this is what the JSF beans should look like:
#ManagedBean
#ViewScoped
public class SomeMB implements Serializable {
private static final long serialVersionUID = 1L;
private static SomeService someService() {
return SpringJSFUtil.getBean("someService");
}
// ...
And the utility class SpringJSFUtil.java that gets the bean via EL:
import javax.faces.context.FacesContext;
public class SpringJSFUtil {
public static <T> T getBean(String beanName) {
if (beanName == null) {
return null;
}
return getValue("#{" + beanName + "}");
}
#SuppressWarnings("unchecked")
private static <T> T getValue(String expression) {
FacesContext context = FacesContext.getCurrentInstance();
return (T) context.getApplication().evaluateExpressionGet(context,
expression, Object.class);
}
}
This eliminates the Spring bean property (at the cost of doing a few more EL evaluations), thus avoiding all the serialization issues of having the property in first place.
The same approach, using OmniFaces:
In my actual code, I use the evaluateExpressionGet(String expression) method of an utility class available from OmniFaces. So, for those of you who use it too, this is what my code really look like:
import static org.omnifaces.util.Faces.evaluateExpressionGet;
#ManagedBean
#ViewScoped
public class SomeMB implements Serializable {
private static final long serialVersionUID = 1L;
private static SomeService someService() {
return evaluateExpressionGet("#{someService}");
}
// ...
Notice that here the method gets the full EL ("#{expression}"), not just the Spring bean name (or you would get a ClassCastException).
Try #Scope(value = BeanDefinition.SCOPE_SINGLETON, proxyMode = ScopedProxyMode.INTERFACES) on your Spring #Service. This should inject a serializable proxy object into your managed bean that will relocate the service upon access after deserialization.
For those to follow - I had a similar problem with an injected ResourceBundle. Using part of BalusC's answer, I did the following:
#ManagedProperty(value="#{myBundle}")
private transient ResourceBundle myBundle;
private Object readResolve() {
myBundle = FacesContext.getCurrentInstance().getApplication()
.evaluateExpressionGet(FacesContext.getCurrentInstance(), "#{myBundle}",
ResourceBundle.class);
return this;
}
This way, the EL is evaluated only when the managed bean is deserialized.
Well keep this in mind from the Spring manual ( link to spring):
Constructor-based or setter-based DI?
Since you can mix both, Constructor- and Setter-based DI, it is a good rule of thumb to use constructor arguments for mandatory dependencies and setters for optional dependencies. Note that the use of a #Required annotation on a setter can be used to make setters required dependencies.
The Spring team generally advocates setter injection, because large numbers of constructor arguments can get unwieldy, especially when properties are optional. Setter methods also make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is a compelling use case.
Some purists favor constructor-based injection. Supplying all object dependencies means that the object is always returned to client (calling) code in a totally initialized state. The disadvantage is that the object becomes less amenable to reconfiguration and re-injection.
Use the DI that makes the most sense for a particular class. Sometimes, when dealing with third-party classes to which you do not have the source, the choice is made for you. A legacy class may not expose any setter methods, and so constructor injection is the only available DI.

Does a Spring annotated controller necessarily need a default constructor

I have a spring controller that uses annotations. I gave this controller a constructor that takes two arguments. I want both ways of initializing the controller: constructor injection and setter injection.
#Controller("viewQuestionController")
#RequestMapping("/public/viewQuestions")
public class ViewQuestionController
{
#Resource(name="questionService")
private QuestionService questionService;
/*public ViewQuestionController()
{
int i=0;
i++;
}
*/
public ViewQuestionController(#Qualifier("questionService") QuestionService questionService)
{
this.questionService = questionService;
}
#Resource(name="questionService")
public void setQuestionService(QuestionService questionService)
{
this.questionService = questionService;
}
}
When I uncomment the default constructor, the controller is initiated correctly. However, if I don't, I get a BeanInstantiationException, No default constructor found; nested exception is java.lang.NoSuchMethodException.
So, is my configuration for the annotated constructor wrong or does a completely annotated controller in spring always need a default constructor?
If you want to configure constructor injection via annotations, you need to put the corresponding annotation on the constructor. I'm not sure how it can be done with #Resource, but #Autowired and #Inject support it:
#Autowired
public ViewQuestionController(#Qualifier("questionService") QuestionService questionService)
or
#Inject
public ViewQuestionController(#Named("questionService") QuestionService questionService)
I think Controller beans need a default constructor as they are initialized by the framework but there is no way to tell the framework hot to provide the dependency.
On second thought why not you autowire your question service and Spring will take care of it.
The following code should be good
#Controller("viewQuestionController")
#RequestMapping("/public/viewQuestions")
public class ViewQuestionController
{
#Autowired
private QuestionService questionService;
//Not providing any constructor would also be fine
public ViewQuestionController(){}
questionService will be initialized properly by Spring

Resources