Sonar-linter think that right way to inject is:
#Bean
public Example example(DataSource datasource) {
return new Example(datasource)
}
but if only one method's using this field. I'm curious, why exactly one method? And maybe better do #Autowired?
Quote from Sonar's rule:
When #Autowired is used, dependencies need to be resolved when the class is instantiated, which may cause early initialization of beans or lead the context to look in places it shouldn't to find the bean. To avoid this tricky issue and optimize the way the context loads, dependencies should be requested as late as possible. That means using parameter injection instead of field injection for dependencies that are only used in a single #Bean method
As your Quote says, #Autowired needs the dependency to be resolved when the class is Initialzed. Parameter Injection instantiates the bean only when it‘s needed. This increases the effectivity of your Code.
The reason for the Single Method is caused by lifecycle of a Bean. By default Beans are singletons which means they are Shared like static Objects. So if multiple Objects will use the bean it is more effective to inject them with autowired because the possibility That it will be used is much higher and so you provide the Shared instance at Startup
Related
I want to inject field values to Camunda delegate. Because it's more convenient to have separate inputs for every listener (here - java classes), but not for them all, working within this activity.
(it is even more important for such technical and through task like logging – which we want not to be visible, but doing its work)
My delegate is a Spring bean, cause i want to autowire loggingRestService to it.
As Spring bean is a Singleton by default, for renewing injected fields' values (so, we can say, the delegate become statefull because of these inputs from a BPMN process) i use SCOPE_PROTOTYPE and it works as i wish:
#Service
#Scope(SCOPE_PROTOTYPE)
class BusinessLogDelegate : JavaDelegate {
private val loggingRestService: LoggingRestService
override fun execute(execution: DelegateExecution) {...}
}
But in the Camunda docs there is no info about such solution, only restriction not to use Spring/CDI beans:
For the same reasons as mentioned above, field injection should not be (usually) used with Spring beans, which are singletons by default. Otherwise, you may run into inconsistencies due to concurrent modification of the bean fields.
As written in Is Spring's #Autowired a huge performance issue? the most expensive operation is creating of a bean (not an injection), but without being bean, java class instance will be created every time when it called by Camunda bpm.
So there is no addition lack of performance.
Are there any other problems in this solution?
As you correctly observed, a Java class would also be instantiated every time it is required. There is no issue using a Spring bean, which autowires services.
The warning is only relevant when using Camunda's field injection feature to parameterize the delegate. The injected value would survive to the next bean usage if the same delegate expression is used repeatedly. That does not have to be an issue. If the desired value is always injected first, then one could reuse the bean. There is a certain room for unforeseen behavior, if the developer is not aware of Spring scope. As long as you consider the lifecycle, and set the scope to prototype as required, it is ok. Unless you are executing thousands of process instances per second, the performance impact of the instantiation is likely negligible.
In this example I played with different alernavites to inject parameters into delegates. Input data create a data value in the DB. Extension properties requite more code in the delegate.
https://github.com/rob2universe/flexible-delegate
To achieve this, either use the #Autowire annotation or implement the ApplicationContextAware interface:
public class SingletonAppContextBean implements ApplicationContextAware {
private ApplicationContext applicationContext;
public PrototypeBean getPrototypeBean() {
return applicationContext.getBean(PrototypeBean.class);
}
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
}
Every time the getPrototypeBean() method is called, a new instance of PrototypeBean will be returned from the ApplicationContext.
However, this approach has serious disadvantages. It contradicts the principle of inversion of control, as we request the dependencies from the container directly.
Also, we fetch the prototype bean from the applicationContext within the SingletonAppcontextBean class. This means coupling the code to the Spring Framework.
Everybody knows that #Autowired(#Inject etc) annotation is processed by AutowiredAnnotationBeanPostProcessor. It parses and set fields and setters annotated with #Autowired but what about constructors? This is bean PostProcessor, that means that it is called after bean was already created, but constructors can also be marked as #Autowired, so how such beans are created?
Good question. For clarification's sake, to re-word it:
How does Spring provide the capability to do dependency injection on
constructor parameters when it seems like dependencies are injected
only after the bean is created?!
If you look at the AutowiredAnnotationBeanPostProcessor you'll find that there is a method called #determineCandidateConstructors that doesn't get called anywhere from inside that class itself.
The reason it's not called there is because it's referenced in the AbstractAutowireCapableBeanFactory; a class that's used for the actual creation/instantion of the bean!
I would imagine Juergen and the Spring guys decided it made architectural sense to put the #determineCandidateConstructors in the AutowiredAnnotationBeanPostProcessor class because it fits in with the concept function of the real purpose of Autowire-ing an injected dependency.
FYI, these concepts of field #Autowire vs. constructor #Autowire is so tightly tied together, that there is a whole discussion in the Spring DI world on whether to use constructor vs. dependency injection. See the section entitled Constructor-based or setter-based DI of this article, Oliver Gierke's comment (i.e. head of Spring Data project), and google for more information.
I have the following scenario in my code base:
//this bean, which will be injected,
//is not annotated
public class HelperUtil {
//only default constructor with no args
public void doThis(String _in) {
//...
}
public void doThat() {
//...
}
}
In the below class we do the injection:
#Named
#Stateless
public class BusinessManager {
#PersistenceContext(unitName = "default")
private EntityManager em;
#Inject
private HelperUtil helperUtil ;
//...
}
Q1: When is the instance of HelperUtil which will be injected actually initialized by calling the default constructor? Is it done when the first client into which it is injected (like BusinessManager) is instantiated when the app server (in my case JBoss) starts (and that one will be initialized by the container because it is annotated as #Stateless)?
Q2: In the above exhibit, will HelperUtil remain a singleton as long as no client other than the container asks for an instance by calling the constructor directly and not obtaining an instance via DI?
Q3: What is the advantage of using DI and #Inject in this case vs. simply calling the constructor directly (HelperUtil helper = new HelperUtil();)?
It depends, but you can control these event to execute some code, for example:
If you need that your bean is executed when the app start you need to add #Startup annotation to your bean.
If you need to initialize your bean without access to other injected resources you can use the normal constructor.
If you need some method to be executed when the bean is initialized then use the #PostConstruct annotation in the method.
You need to remember that the creation depends on the scope of the bean, in you case, which is a stateless bean, the bean will be created if some client injects it and there are no other instance available, if is singleton then will bean created just once, in general the bean will be created when they are needed (a singleton bean initialize until the first client uses it, or at startup with the annotation)
EDIT:
For the third question, the advantage is that if you use a resource, or other bean inside your HelperUtil, they will be initialized with the proper values, for example, if you use an entity manager, or other beans inside your helper. If your helper will handle just things like static methods or other simple utilities then you are right, the advantage is none and you could simply manage like an static helper class, but if you need EE resources the you need the bean to be managed in order to get all injections and resources loaded
EDIT 2:
After some more years programming and using dependency injection in Java and C# Core, I can add: The question 3 is very open, using DI will allow your code to:
be less coupled, if you change your constructor, you then would have to go searching all the new ObjectModified(oldParams) to add the new parameters
more easy to test, because you can inject "fake objects" as dependencies, avoiding the need to load all the system and prepare the state for the test, for example, if you want to check some code that depends on the current hour, you could connect a fake provider in test mode to give always the same hour, or some sequence
Avoid cyclical dependency, where class A depends on B and B depends on A, normally this is more complex, like
ClasssA -> ClasssB -> ClasssC -> ClasssA
When this dependencies are present, you can start a modification, then modify the class that uses it, and so on... until somehow you find yourself modifying the same class as before!, so you start in a cycle because the communication path between your objects are complex.
When you use DI, this cycles can be detected early on, so you can rethink your architecture to avoid this productivity blackholes
DI is a very powerful tool to keep big projects maintainable, is now present in a lot of environments and frameworks because is very useful, if this still does not convince you, you can try start a project in Spring boot, PlayFramework, Net Core, Java EE, Ruby on Rails.... and many others that have include this as the normal flow and build a medium size app, then try without DI
Background: Everything within CDI operates within a Context. That being said
A managed bean's fields are instantiated, on request. From the spec:
When the container creates a new instance of a managed bean, session bean, or of any other Java EE component class supporting injection, the container must:
Initialize the values of all injected fields. The container sets the value of each injected field to an injectable reference.
What this means is that the first initialization of a dependent bean is when it's first called for, which is when the parent bean is initialized. Now, the JSF #ApplicationScoped has the eager="true" attribute, which allows beans of that scope to be initialized before they're needed by any other part of the application, on startup, EJB #Startup for the same effect on EJBs. CDI beans however, don't have that capability out of the box.
The default scope of CDI beans is #Dependent. What this means is that an injected bean inherits the scope of the injection target (except when the bean has its own scope; in that case, its own scope applies). In your case, HelperUtil is not going to live beyond the lifetime of that EJB, sorta like #RequestScoped
Related
how is the #RequestScoped bean instance provided to #SessionScoped bean in runtime here?
Non-lazy instantiation of CDI SessionScoped beans
JSF Named Bean, Eager application scoped (aka #ManagedBean(eager=true) )
I think its constructor is not called until the method is called like helperUtil.dothat(), its not when its containing bean is instantiated.
About all of the injected fields must be initialized by the container when the managed beans are instantiated like the other answer, its true, but all of the injected fields are injected with proxies so they are not the real objects so the real constructors aren't called.
If its constructor is called when its containing bean is instantiated then how about a #RequestScoped bean inside a servlet for example. The servlet is only instantiated one time but the injected #RequestScoped bean must be instantiated multiple times. If its true then surely the #RequestScoped annotation wouldn't work.
So by simply looking at those CDI annotations intention and name like "request" or "session", we know that the real CDI managed bean objects are made/ instantiated independent of the containing user bean instantiation.
Today, we found this pattern in our code:
class Foo {
private List<String> errors;
public void addError(String error) { ... }
public List<String> getErrors();
}
While the code seems to work, this is a singleton Spring bean and it's injected in several independent places and the consumers of the bean assume that they each have their own list of errors. So this introduces subtle bugs.
The obvious solution is to educate developers to avoid this kind of error but I was wondering if there is a static or runtime code analysis tool which can find this kind of bug.
For example, a bean postprocessor could analyze the bean before it's returned and look for private fields that aren't #Autowired.
After pouring some more brains (ours and other peoples) on this, we came up with this approach:
Install a BeanPostProcessor which makes sure that all singleton beans (i.e. where the scope in the bean definition is Singleton) have the custom annotation #Stateless on the actual bean type.
We chose a custom annotation instead of reusing #Singleton since we need this functionality elsewhere, too.
If the annotation is missing, the factory throws an error.
In a unit test, we use ClassPathScanningCandidateComponentProvider with out custom annotation to locate all classes on the classpath. We can then do the complex and expensive tests to make sure the bean has no state that changes after the initial configuration (i.e. after the autowiring has happened).
The second step could become a little bit easier if we moved the autowired fields into the constructor but we don't like methods that take many, many arguments. It would be nice if Java or an IDE could generate builders from the bean code. Since that's not the case, we stick to autowired fields and/or setters.
You could create a JUnit test that would load your app config.
This could combine ListableBeanFactory from here :
Can I dynamically create a List by scanning the beans in a spring configuration file?
with the 'isSingleton' check here :
How to enforce a prototype scope of Spring beans
i.e. list all the beans in the app context, then check to see which are singletons.
This would let you find all singleton beans...although it wouldn't really prevent your error case where someone treats one of these singletons as if it were not.
Is there anyway to specify order in which beans to be instantiated? i.e. I want specific beans to be instantiated before other beans, its like startup sequence.
I am using Spring 3.2 and annotation based declaration method.
If bean A depends on bean B by defining <property/>, #Autowired or <constructor-arg/> then the order is forced and fixed by the Spring container. No problem here.
But if you want to enforce specific order of bean creation which is not expressed via explicit dependencies feel free to use:
<bean id="A" depends-on="B"/>
<bean id="B"/>
or better (with annotations, works also with #Bean Java configuration):
#Service
#DependsOn("B")
public class A {}
or even better... don't use it. These constructs are a code smell and often suggest you have some nasty invisible dependency between your components.
Agreed with the answer provided by Tomasz. If you know that bean A depends on bean B then this is right approach.
Sometimes you have logic that should be executed before all beans instantiation. In this case you can use BeanFactoryPostProcessor. Spring creates and executes BeanFactoryPostProcessors first and after that only all other beans. At the same time if your BeanFactoryPostProcessor depends on some bean A you can use property or constructor injection. In this case Spring will create bean A first, then your BeanFactoryPostProcessor, call BeanFactoryPostProcessor and after that only instatiate all other beans in the context.
You can use the Ordered interface on your bean to define ordering relative to other beans.
Further,if you use BeanFactoryPostProcessor as emamedov said, Ordered interface can be implemented to control BeanFactoryPostProcessor instance sequence.