I am running into an issue with my Spring Applications and SonarQube. SQ is flagging both examples with "Annotate this member with "#Autowired", "#Resource", "#Inject", or "#Value", or remove it." on the instance variable mapLoadedByDatabaseCalls
Example 1:
#Service
public class Service implements InitializingBean {
#Autowired
private Dao dao;
private Map<Object, Object> mapLoadedByDatabaseCalls;
#Override
public void afterPropertiesSet() throws Exception {
mapLoadedByDatabaseCalls= new HashMap<>(Object.class);
....
}
}
Example 2:
#Service
public class Service {
#Autowired
private Dao dao;
private Map<Object, Object> mapLoadedByDatabaseCalls;
#PostConstruct
private void setMap() {
mapLoadedByDatabaseCalls= new HashMap<>(Object.class);
....
}
}
What is the correct way to instantiate variables after DI has completed?
A more generic solution to this that does not involve any additional annotations, is to initialize the offending variable in the class constructor.
public Service() {
mapLoadedByDatabaseCalls = new HashMap<>();
}
I believe that this is kludgy and that your original code is better, but this will eliminate the SonarQube complaint. Initialize your map in a #Bean, then reference that as #Autowired. Load the map with data in the #PostConstruct.
#Bean
public Map<Object, Object> getMapLoadedByDatabaseCalls() {
return new HashMap<>(Object.class);
}
#Autowired
private Map<Object, Object> mapLoadedByDatabaseCalls;
#PostConstruct
private void setMap() {
...
// load data into the map
mapLoadedByDatabaseCalls.put(key, value);
....
}
From the Spring Documentation > Initialization callbacks section
It is recommended that you do not use the InitializingBean interface
because it unnecessarily couples the code to Spring. Alternatively,
use the #PostConstruct annotation or specify a POJO initialization
method.
Essentially InitializingBean pre-existed in Spring before the JSR-250 support came on Spring 2.5 onwards (including the #PostConstruct annotation)
The rule S3749 describes that Spring #Component, #Controller, #Service, and #Repository classes are singletons by default, meaning only one instance of the class is ever instantiated in the application. Typically such a class might have a few static members, such as a logger, but all non-static members should be managed by Spring. That is, they should have one of these annotations: #Resource, #Inject, #Autowired or #Value.
Having non-injected members in one of these classes could indicate an attempt to manage state. Because they are singletons, such an attempt is almost guaranteed to eventually expose data from User1's session to User2.
Given the above details, Spring should be managing its all non-static members states. It all depends on the use case and should be avoided either using #Autoworied, class constructor or #PostConstruct.
SECURITY WARNING: OWASP A3:2017. This could leak sensitive data
Related
Consider the below code:
Service
class MyService{
#Autowired
private ModelMapper modelMapper;
void validate(){
ResponseObject obj = modelMapper.map( REQUEST, ResponseObject.class);
// In testing, if I am not mocking this Model Mapper, an exception will be thrown.
}
}
Testing
Here in JUnit test cases, instead of mocking, I am making use of ReflectionTestUtils.setField("", "", "") and the mapping takes place as expected. But I am not aware of what's happening and how it's working. I referred to many sources, but I couldn't find any reliable resource regarding this. Can someone tell me whats ReflectionTestUtils, how its works, and when to use it?
#InjectMocks
MyService service;
private ModelMapper modelMapper;
#BeforeEach
void setup() {
modelMapper = new ModelMapper();
ReflectionTestUtils.setField( service, "modelMapper", modelMapper);
}
It uses reflection API under the cover to set the value for an object 's field.
About when to use it , the documentation already provides some info :
You can use these methods in testing scenarios where you need to
change the value of a constant, set a non-public field, invoke a
non-public setter method, or invoke a non-public configuration or
lifecycle callback method when testing application code for use cases
such as the following:
ORM frameworks (such as JPA and Hibernate) that condone private or
protected field access as opposed to public setter methods for
properties in a domain entity.
Spring’s support for annotations (such as #Autowired, #Inject, and
#Resource), that provide dependency injection for private or protected
fields, setter methods, and configuration methods.
Use of annotations such as #PostConstruct and #PreDestroy for
lifecycle callback methods.
I normally use it for setting up some dummy domain objects which are JPA entities for testing. Since their ID are managed by Hibernate and to have a good encapsulation , they do not have any setter or constructor to configure their ID value , and hence need to use it to setup some dummy values for their ID.
Instead of doing the very anti-pattern (if you ask me) :
#Autowired
private ModelMapper modelMapper;
you can always inject it via the constructor:
private final ModelMapper modelMapper;
class MyService(ModelMapper modelMapper) {
this.modelMapper = modelMapper;
}
when MyService is a bean that spring is aware of, the auto-wiring will happen for you. So no need to use the ReflectionTestUtils.setField; which will start failing in jdk-17 and up.
Since you now pass it via a constructor, injection with a mock for example, is trivial.
I'm not so familiar with Spring and I have the following situation:
A repository class:
#Repository
public class MyRepository {
// ...
}
A class that uses the repository class:
public class MyClass extends AbstractClass {
#Autowired
private MyRepository myRepository;
//...
}
I know that if I annotate my MyClass with #Component and use it with an #Autowired, then the #Autowired MyRepository is resolved just fine.
Problem is I am in a situation that I need to create new instances of MyClass with reflection. So MyRepository is never resolved and is null all the time.
Is there a way to use #Autowired in this situation?
Explaining better my situation:
I have some implementations of AbstractClass.
In a setup phase of my application I create a HashMap of these implementations. Basically:
{"MyClass", MyClass.class}
//...
Then I have a generic Controller that maps to the url /{class}?options=...
Using the {class} #PathVariable, the HashMap above and reflection I am able to create a instance of a class based on the given options (this part is important). Do you guys think there's a better way of doing this?
Thanks in advance
Spring itself offers some functionality for doing auto-wiring in your objects
which you created by new or newInstance() or whatever.
To use it you need an AutowireCapableBeanFactory
which you get by Spring's normal dependency injection with #Autowired.
#Autowired
private AutowireCapableBeanFactory autowireCapableBeanFactory;
Then you use its autowireBean(Object) method
to inject the #Autowired properties into your bean.
Object myBean = map.get(className).newInstance();
autowireCapableBeanFactory.autowireBean(myBean);
Design note:
Think well if you really need the approach above.
The javadoc of AutowireCapableBeanFactory advises against using this interface for most use-cases:
This subinterface of BeanFactory is not meant to be used in normal application code: stick to BeanFactory or ListableBeanFactory for typical use cases.
Integration code for other frameworks can leverage this interface to wire and populate existing bean instances that Spring does not control the lifecycle of. This is particularly useful for WebWork Actions and Tapestry Page objects, for example.
You can use Factory Design Pattern over here.
This might seem a little complicated in start but I am sure you will love it after you have implemented it.
Steps:
Add #Component on all implementations of AbstractClass.
Create a factory class as:
#Component
public class MyFactory {
private final Map<String, AbstractClass> impletationMap = new HashMap<>();
#Autowired
ApplicationContext context;
#PostConstruct
public void initialize() {
populateDataMapperMap(context.getBeansOfType(AbstractClass.class).values().iterator());
}
private void populateDataMapperMap(final Iterator<AbstractClass> classIterator) {
while (classIterator.hasNext()) {
AbstractClass abstractClassImpl = (AbstractClass) classIterator.next();
impletationMap.put(abstractClassImpl.getClass().getName(), abstractClassImpl);
}
}
}
When the Bean of this MyFactory class is initialized, then it will lookup for all beans of type AbstractClass and put them in the HashMap(implementationMap).
Now from this factory you can get the HashMap and then get the implementations as and when you require. It will be very easy when you add new implementation of AbstractClass as factory will take care of it.
One work around is instead of binding the MyClass to the Hashmap to bind a Factory class. MyClassFactory. This way you will delegate the construction to a concrete factory that will do the job to instantiate the correct class and initialize the correct repository.
Here is an example:
{"MyClass", MyClassFactory.class}
The factory can be Component as well, then you need to bind the hashmap to the factory instance instead of the factory class. But lets say it is not a component:
//#Component this is optional
public MyClassFactory {
//#Autowired optional
ApplicationContext ctx;
public MyClass createInstance() {
MyRepository repo = ctx.getBean("")
MyClass myclass = new MyClass(repo)
return myclass;
}
}
If you mark it as component you can well also use ApplicationContextAware interface if you are going to autowire the ApplicationContext.
One approach is to declare #Component on top of MyClass.
Then, in the setup phase, you can pass the instance of MyClass instead of MyClass.class itself, in the HashMap. There won't be any need to create instances via reflection.
Note: You can fetch the instance of MyClass from your ApplicationContext in the setup phase.
Try this
#Component
public class SomeClass extends AbstractClass {
private static ApplicationContext applicationContext;
public MyClass getMyClass(){
// Now #Autowired MyRepository will work
return applicationContext.getBean(MyClass.class);
}
}
Yes, you can annotate all your AbstractClass implementation beans with #Component and use the next declaration
#Autowired
private List<AbstractClass> beans;
You can then convert that to a Map in a #PostConstruct method.
Spring won't complain about duplicate definitions if you autowire Lists.
I don't know if it is the better way to implement my solution:
#Component
#Scope("singleton")
public class GetFromJson implements Serializable{
/**
*
*/
private static final long serialVersionUID = -8203722696439228358L;
Map<String, Map<String, ArrayList<String>>> jsonMap;
public Map<String, Map<String, ArrayList<String>>> getJsonMap() {
return jsonMap;
}
public void setJsonMap(Map<String, Map<String, ArrayList<String>>> jsonMap) {
this.jsonMap= jsonMap;
}
}
The class is Serializable because I get the content from a Json from a database and I map the content in an Object GetFromJson (I need do the query in database only one time). For this reason I need use the Object in all my APp, for this reason I think that I need use a Singleton
Somebody publish to me a library to get the JSON from database. the JSON object parse to Map<String, Map<String, ArrayList<String>>> for this reason I create my GetFromJson class.
Now I have many rest Service, in my rest services I need use my object: GetFromJson to get the content of jsonMap.
I have many questions.
With the annotation #Scope("singleton") I guarantee have the GetFromJson only one instance available in all my app?
Or what is the better way to have in Spring a singleton and session object available in my app?
To access to get the content of jsonMap of GetFromJson is enough use
#Autowired
private GetFromJson jsonObject;
Or how can I get my singleton class?
and in my rest method service use:
jsonObject.getJsonMap();
How can Initialize my singleton, because i am trying initialize my object with:
#Autowired
private GetFromJson jsonObject;
public methodToInitialize(){
jsonObject = methodLibraryFromDatabase(GetFromJson.class);
}
ANd the IDE tell to me that the field initialization is not used
I need the same logic, but with session Object, I think that if I understand the singleton implementation with my session object will be the same but only changing the anotation to: #Scope("session")
I think what OP is wants to initialize database based POJO once in application lifecycle and autowire it where needed.
Typically this is done by creating a bean (which are singletons unless otherwise specified) and autowiring it where needed.
This sample should get you started.
#Configuration // beans are declerated in #Configuration classes
public class GetJsonInitializer {
#Bean // singleton by default
public GetFromJson jsonMap(){
GetFromJson jsonObject = methodLibraryDatabase(GetFromJson.class);
return jsonOBject;
}
}
Now autowire GetFromJson in any Spring service/component etc.
#Service
public class SomeService {
#Autowired
private GetFromJson jsonMap;
}
Hope this helps!
a bean annotated with session scope is going to be bound to user's session life cycle, that is, for each user accessing your app, you'll have an instance of this class. If you want to guarantee only one instance of this bean in your application (at JVM level) you just need to remove the #Scope annotation. However, if you want to mix singletons with session scoped beans, then you should just let spring handle everything seamless for you, your session scope beans will only be destroyed when the user session ends.
The best way to handle initialization code in your bean is in a public method annotated with javax.annotation.PostConstruct
#PostConstruct
public void setUp() {
//initialization code
}
In order to handle a clean up code when a bean is going to be destroyed, you should make your class implement org.springframework.beans.factory.DisposableBean or add a method annotated with javax.annotation.PreDestroy
#PreDestroy
public void onDestroy() {
//clean up code
}
I hope this has helped you out!
I've seen the #Autowired annotation placed just before the constructor of a POJO used as controller.
#Controller
public class LoginController{
private UsuarioService usuarioService;
#Autowired
public void LoginController(UsuarioService usuarioService){
this.usuarioService = usuarioService;
}
// More code
}
This constructor takes as argument the reference to the object we want Spring to inject.However if I place this annotation just before the property declaration the application works just the same.
#Controller
public class LoginController{
#Autowired
private UsuarioService usuarioService;
// More code
}
My question is what is the difference between this two approaches in terms of pros and cons.
My advice to you would be to never use #Autowired on fields (except in Spring #Configuration classes).
The reason is very simple: TESTING!!!!
When you use #Autowired on fields of a class, then that class becomes harder to unit test because you cannot easily use your own (possible mocked) dependencies for the class under test.
When you use constructor injection then is becomes immediately evident what the dependencies of the class are, and creating that class becomes straight forward (simple constructor call).
Some points that need to made:
1) Some might argue that even when #Autowired is used the class can still be unit tested with the use of Mockito's #InjectMocks, or Spring's ReflectionTestUtils.setField, but my opinion is that the creation of a unit under test should be as dead simple as possible.
2) Another point that could be mentioned is that there might be many arguments in the constructor making the manual invocation of the constructor (either in the test or elsewhere) difficult. This however is not a problem regarding the creation of the class, but a problem in the design. When a class has to many dependencies, in most cases it is trying to do too much and needs to broken into smaller classes with fewer dependencies.
#Autowired annotation on setter methods is to get rid of the element in XML configuration file. When Spring finds an #Autowired annotation used with setter methods, it tries to perform byType autowiring on the method
#Autowired annotation on properties is to get rid of the setter methods. When you will pass values of autowired properties using Spring will automatically assign those properties with the passed values or references.
Here is an example of both the usage:
http://www.tutorialspoint.com/spring/spring_autowired_annotation.htm
This Springsource blog post mentions that constructor injection makes it easy to validate required dependencies, if used in combination with contructors assertions that are good practice anyway and would also work if the class is instantiated outside Spring with the new operator:
#Controller
public class LoginController{
private UsuarioService usuarioService;
#Autowired
public void LoginController(UsuarioService usuarioService){
if (usuarioService == null) {
throw new IllegalArgumentException("usuarioService cannot be null.");
}
this.usuarioService = usuarioService;
}
}
This type of assertions are general best practice that is advised to do independently of the class being a Spring bean or not.
For setter or property injection there is also the #Required annotation for validating missing dependencies or #Autowired(required = true). According to the blog post, constructor injection provides this advantage, but for historical reasons setter injection is more frequently used in Spring.
Is it possible to use #Configurable on a class that's weaved using AspectJ and get Spring to load in values on fields/methods which are annotated with #Value?
I know its possible with #Autowired and #Resource etc... Are there any others.
e.g.
#Configurable
public Class MyObj{
#Value("$(my.prop)")
private String aField;
public String getAField(){
return aField;
}
}
And then have something like
public aMethodSomewhereElse(){
MyObj obj = new MyObj()
assertNotNull(obj.getAField());
}
Are there any alternatives to being able to create MyObj with the new operator and still get spring to handle the annotations?
--EDIT:--
It IS possible to do this using new when using #Autowired, have a look at some Hibernate and JPA stuff with Spring and AOP... I've used this in the past to do some profiling of Java code. But I really want to use SPEL and #Value before I mock up a full example I was hoping to find the answer here. FYI - if you don't belive me the Spring Manual even says it is possible to do this, what I want to know is if its possible to use #Value annotations in the same scope...
The Spring container instantiates and configures beans defined in your
application context. It is also possible to ask a bean factory to
configure a pre-existing object given the name of a bean definition
containing the configuration to be applied. The spring-aspects.jar
contains an annotation-driven aspect that exploits this capability to
allow dependency injection of any object.
And...
Using the annotation on its own does nothing of course. It is the
AnnotationBeanConfigurerAspect in spring-aspects.jar that acts on the
presence of the annotation. In essence the aspect says "after
returning from the initialization of a new object of a type annotated
with #Configurable, configure the newly created object using Spring in
accordance with the properties of the annotation". In this context,
initialization refers to newly instantiated objects (e.g., objects
instantiated with the 'new' operator) as well as to Serializable
objects that are undergoing deserialization (e.g., via readResolve()).
http://static.springsource.org/spring/docs/3.0.0.RC2/reference/html/ch07s08.html
Cheers.
You are absolutely right - #Autowired fields will be wired in an #Configurable annotated class even outside of a Spring container, assuming that you have a AspectJ infrastructure in place.
You have noted a good catch though, #Value fields are processed by a Spring bean post processor(AutowiredAnnotationBeanPostProcessor), which resolves the #Value annotated fields. It does not act on objects instantiated outside of the container though - so in short, the #Autowired fields should get wired in, but #Value properties will not.
Doing
MyObj obj = new MyObj()
means that obj is not managed by spring, so it will not do autowiring.
Only way to do that is to obtain instance from an application context. For example:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MyObj obj = context.getBean("myBean");
I don't think it is possible to use new operator and ask spring to autowire properties. I think 1 way to solve this is to get a static reference to applicationContext and create a prototype scoped bean.
#Component
public class ApplicationContextLocator {
private static ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public ApplicationContextLocator() {
super();
}
#Autowired
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextLocator.applicationContext = applicationContext;
}
}
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Component
public class MyObj {
.....
}
public aMethodSomewhereElse(){
MyObj obj = ApplicationContextLocator.getApplicationContext().getBean(MyObj.class)
assertNotNull(obj.getAField());
}