PMD Ignore Spring Field Injections in gradle config - java

Currently I have several Controllers that inject dependencies through a field marked with #Autowired. When I try to run gradle build the following violations come up.
These all correspond to the instances of where a spring component has been injected.
I am aware of the ignoreAnnotations property that seems to exist for PMD, however, I am not sure if one can actually specify this in a gradle configuration?
Any help would be appreciated.

The root cause is: field injection is code smell and bad design practice.
When #Autowired is used on a non-transient field it can cause issues with serialization. This is because the field will not be properly initialized when the object is deserialized, leading to a NullPointerException when the object is used.
To fix this issue either make the fields transient or -- much better -- use constructor injection. To use constructor injection add a constructor to your class that takes all of the required dependencies as arguments, and annotate the constructor with #Autowired (the annotation is optional in modern Spring versions).
#Component
class MyClass {
private final Dependency1 dependency1;
private final Dependency2 dependency2;
#Autowired
public MyClass(Dependency1 dependency1, Dependency2 dependency2) {
this.dependency1 = dependency1;
this.dependency2 = dependency2;
}
}

Related

How can I pass parameters to a constructor of a class that uses #RequiredArgsConstructor?

I am trying to instantiate a class passing a parameter by constructor drMessage, I am using the #RequiredArgsConstructor annotation, and some dependency injections using #Autowired as I show below, the problem is that when using the #RequiredArgsConstructor annotation it implements the default constructors internally, and I tried to build the constructors manually but the IDE tells me that the variable of those constructors has not been initialized, how could I solve it? Thanks
#RequiredArgsConstructor
#Service
public class ServiceImpl implements IService {
#Autowired
private final DtoMapper dtoMapper;
#Autowired
private final CDtoMapper cDtoMapper;
private DrMessage drMessage;
**other sentences**
}
Constructor Injection With Lombok
With Lombok, it's possible to generate a constructor for either all class's fields (with #AllArgsConstructor) or all final class's fields (with #RequiredArgsConstructor). Moreover, if you still need an empty constructor, you can append an additional #NoArgsConstructor annotation.
Let's create a third component, analogous to the previous two:
1.Example
#Component
#RequiredArgsConstructor
public class ThankingService {
private final Translator translator;
public String produce() {
return translator.translate("thank you");
}
}
The above annotation will cause Lombok to generate a constructor for us:
2.Example
#Component
public class ThankingService {
private final Translator translator;
public String thank() {
return translator.translate("thank you");
}
/* Generated by Lombok */
public ThankingService(Translator translator) {
this.translator = translator;
}
}
#Service annotated classes are Spring managed beans. You don't manually instantiate these classes. Spring does it for you.
These #Service annotated beans have default singleton scope. Which means this bean is only initialize once. So they are called stateless beans, or says they have a shared state. You do not crate a state or change the state of these kind of beans.
Note: Read this document about bean scopes.
In your ServiceImpl you only have two final state variables. Which means are the only required filed when ServiceImpl initialize, so only they will be included in #RequiredArgsConstructor.
Lombok works at compile time while Spring works at runtime.
So when you place a Lombok annotation of the constructor (#AllArgsConstructor, #RequiredArgsConstructor, etc) on your class (it can be a regular java class, spring bean, whatever), Lombok creates a constructor for you.
In this case, it will create a constructor for all final fields (see the documentation
As you see lombok doesn't take into consideration the #Autowired annotation,
Since you haven't placed #NonNull annotation on drMessage (check the documentation) it won't generate a constructor parameter for it, so your class will look like:
#RequiredArgsConstructor
#Service
public class ServiceImpl implements IService {
#Autowired
private final DtoMapper dtoMapper;
#Autowired
private final CDtoMapper cDtoMapper;
private DrMessage drMessage;
public ServiceImpl(DtoMapper dtoMapper, cDtoMapper cDtoMapper) {
this.dtoMapper = dtoMapper;
this.cDtoMapper = cDtoMapper;
}
**other sentences**
}
So if you want the lombok to generate a parameter for DrMessage make it final, or put a #NonNull annotation on it.
At this point the job of Lombok is done, in fact, you can exclude it from being available at runtime at all. Now regarding the spring part:
First of all, you say that you by yourself are trying to create the instance of ServiceImpl class, why? It's a spring bean (you've put a #Service annotation on it), so let Spring manage this class.
With this definition, placing #Autowired on the final field won't work in spring.
See this thread, so you should not place #Autowired on these fields.
Luckily Spring in its recent versions is smart enough to understand that if the class has a single constructor (in your case the one that you've generated with Lombok) spring will call it to create the instance of your class, so instead of field injection, you'll use constructor injection.

Internal working of field injection in spring and why is it not recommended to use

As the title suggests , I want to know how does field injection internally works in spring , I read many articles on this and got to know few things like below but didn't understood the exact reason behind it :
-> It should not be used because when you do unit testing then you are dependent upon the spring
container to instantiate the class in case of field injection.
-> You cannot use "final" keyword in case of field injection , means you cannot make the field immutable.
-> It internally uses reflection
I want to know how exactly does #Autowired works internally , how does it uses reflection , I am trying to understand the exact reason behind all the above mentioned points, what happens behind the scenes when we write the below code :
#Component
public class B {
#Autowired
private A a1;
}
I have read similar questions on stack overflow about this topic , but I couldn't find the exact explanation that I am looking.
Spring has a concept of Bean Post Processors.
When spring builds a bean it applies registered bean post processors that help to "initialize" the bean.
So, there is org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor that handles autowiring.
Basically it works with an newly created object. Spring introspects the fields of the beans (by using reflection). The fields that have #Autowired is a subject for processing with this bean post processor. It finds the candidate for injection in the application context and actually injects the value.
Now given this information, its understandable why final fields cannot be autowired. Leave alone spring, In pure Java, final fields must be instantiated directly right during the declaration (final int i = 123) or in the constructor of the class. But the autowiring happens after constructor, so its impossible to autowire the final fields.
As for the unit testing, the private properties must be somehow configured from the test. But since they're encapsulated (yes, spring kind of breaks encapsulation in this case for its usage), its impossible to write a good test for the class that contains fields injection. That's is a reason to switch to constructor injection.
public class FieldInjection {
#Autowired
private A a;
}
VS.
public class ConstructorInjection {
private final A a;
// this can be generated by lombok, you don't have to put #Autowired on constructor in the case of single constructor, spring will use it to create a bean
public ConstructorInjection(A a) {
this.a = a;
}
}
Now the test for FieldInjection class is impossible:
public class FieldInjectionTest {
#Test
void test() {
FieldInjection underTest = new FieldInjection();
how do you know that you should instantiate A a. ????
}
}
However in the case of constructor injection its a trivial task:
public class ConstructorInjectionTest {
#Test
void test() {
A a = mock(A.class);
ConstructorInjection underTest = new ConstructorInjection(a);
// the dependencies must be supplied in the constructor
// otherwise its impossible to create an object under test
}
}

Difference between SCOPE_SINGLETON and private constructor

what is the difference between SCOPE_SINGLETON and private constructor?
After initialized any class with SCOPE_SINGLETON, i am able to create object also.
Error:-
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class utility: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: No visible constructors in class utility
First i want to clear that i was not making object using new operator. i used #Component and private constructor. it was working fine. but when i upgrade our sb 1.5 to sb2.0 with gradle upgrade to 4.1. Sonar was start giving me this error. then i removed private constructor and added scope_singleton. it worked for me. even i removed #Component and added throw in my private const. it worked. that's why i asked, what is difference b/w scope_singleton and private constructor.
Working Code:
#Component
#Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
public class utility1 {
}
Error Code:
#Component
public class utility2 {
private utility2() {
}
}
Spring is a framework here you are focusing on the part of the deoendency injection.
By default, the components in Spring are singletons, you do not need to specify that it is a scope_singleton.
Spring does have requirements for its components and one of them is to have a visible constructor (otherwise, spring is not able to create them, so making a public constructor should work for you).
It wiol be a Singleton for Spring as Spring will manage only one instance, but using new you can create as much as you want (I rather think is not a good idea)
If you are using Spring framework you shouldn't try to create annotated classes with new operator or somehow else. Only Spring core should be responsible for bean class creation and only in this situation you could be sure that your class is really singleton etc.

Is it possible to make Optional<T> and #Lazy work together in Spring?

I have to make me #Component #Lazy as it is used rarely and creates circular dependency problem
I have to make it Optional<T> because feature it represents can be disabled on startup (#ConditionalOnProperty) so it might not be available at runtime
Problem:
When I use Optional<T> as injection point, bean is initialized eagerly.
So the questions:
Is it possible to make it work like that?
Can I replace Optional<T> with Provider<T>? will it simply return null if feature is disabled or it will throw exception?
Can it be replaced with ObjectProvider<T>?
I would like to stick to #Resource or #Inject annotation so #Autowired(required=false) will be last resort for me.
There is no code to share here actually (as it would be class and field declarations as those are relevant onl IMHO)
Since you do not belive me the code is worthless here, let me share :)
#Comonent
#Lazy
public class MyType{
}
injection point
#Lazy
#Autowired
private Optional<MyType> myType;
usage
MyType instance=myType.getOrThrow(()->throw something)
Iv tested Optional and debugger hits MyType upon application startup. It is skipped when I use plain field, provider or object provider.
In situations like this I do not wire the Component directly, but lazily. There are different options:
Go through the ApplicationContext and retrieve MyType when you need it. You would only retrieve it, when you know it is enabled:
#Autowire
private ApplicationContext context;
...
MyType instance = context.getBean(MyType.class);
Provider or Factory approach, where you have an autowired service which provides you an instance of MyType. This service is also only called when the feature is enabled.
#Autowire
private MyTypeFactory factory;
...
MyType instance = factory.getMyType();
Using the Provider would require you to define a bean in your configuration, so it might be easier to just have a POJO service on which you can slap #Service, that does the same.
Let me present an alternative Point of View. I think that using Optional dependency for this is not justified.
The class that has an Autowired MyType probably counts on this dependency (notwithstanding the fact that usage of Optional for data fields if a kind of bad practice).
The reason for Laziness of the component also seems to be more "hack" than intention (circular dependency is never a good thing).
So, if we'll pretend that this class makes something "Optionally available", one way is to provide an additional no-op implementation for this MyType problematic bean:
interface MyType {
void doSomeHeavyStuff();
}
public class MyTypeRegularImpl() implements MyType {
public void doSomeHeavyStuff() {
....work..work..work..
}
}
public class NoOpMyType implements MyType {
public void doSomeHeavyStuff() {
// do nothing here
}
}
Now the trick is to provide two mutually exclusive conditions and make sure that only one bean out of these two loads (otherwise it will produce an ambiguity in beans and probably fail during the application startup).
So the class that uses MyType won't need Optional at all.
Now regarding the Laziness.
In general, Lazy beans only get ini
Lazy Bean can still be used since the bean will be initialized during the first call in a class that has that lazy dependency.
For no-op beans it won't matter at all.

Dependency Injection And Fluent Design

Say you have a spring component like below with dependencies constructor injected (builder is a singleton):
#Component
public class houseBuilder{
private WindowMaker windowMaker;
private DoorMaker doorMaker;
private RoofMaker roofMaker;
#Autowired
public houseBuilder(WindowsMaker wm, DoorMaker dm, RoofMaker rm){
this.windowMaker = wm;
this.doorMaker = dm;
this.roofMaker = rm;
}
//Other methods omitted for brevity
}
However the house requires something called "foundation" that should be passed in through the constructor or set before making the house begins and foundation is not a spring bean. I'd like to use the builder pattern as well so I could do something like the below but I am unsure how to do this with spring. Something like the below is what I am after except I want to use spring:
Foundation foundation = new Foundation();
HouseBuilder hb = new HouseBuilder(foundation)
.windowMaker(args)
.doorMaker(args)
.roofMaker(args);
Any advice is appreciated.
Spring Dependency injection and fluent builders are not really designed to work together.
The first is a way to set dependencies of an object in an "automatic" way via annotation or configuration.
While the second is a way for clients of the class to specify how the object should be build.
Automatic dependency injection and declarative construction are so really two distinct ways to create objects.
As a side note, Spring dependency injection with constructor brings two major fluent builder benefits : no more cumbersome constructor to call as the injection is performed by the container and the object may be immutable as no setter are required.

Categories

Resources