#Autowired is not working with beans defined in application context file - java

I defined a bean in spring context file 'applicationContext.xml' like below :
<bean id="daoBean" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.xxx.DAOImpl" />
</bean>
In my service class (ServiceImpl), I am using this bean like below:
#Component("serviceImpl")
public class ServiceImpl{
// other code here
#Autowired
private transient DAOImpl daoBean;
// other code here
}
My service class is being accessed from my JUnit test class.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "/applicationContext.xml" })
public class JUnitTest{
// other code here
#Autowired
private transient ServiceImpl serviceImpl;
// test cases are here
}
When I execute the test case, it gives error saying:
Error creating bean with name 'ServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private transient com.xxx.DAOImpl
When I remove #Autowired from service class and use #Resource(name = "daoBean") the test case works fine.
public class ServiceImpl{
// other code here
#Resource(name = "daoBean")
private transient DAOImpl daoBean;
// other code here
}
My question is why #Autowired is not working in this case? Do I need to configure any thing else with #Autowired, so that it can work properly. I don't want to change my service layer classes to replace #Autowired to #Resource.

Mockito.mock() has a generic return type T which is erased at runtime, so Spring cannot infer the type of the created mock that will be simply registered as Object in the Spring context. That's why #Autowired doesn't work (as it tries to look up the dependency by its type).
Check out this answer for a solution to the problem.

Related

XML bean definitions don't pick up #Component annotated beans in dependency packages

Not sure what i'm missing here but some assistance would be appreciated.
I have a class annotated with #Component as follows in a package com.company.package:
#Component
public class ClassAService {
#Autowired
public ClassAService(ClassB classB) {
....
}
}
Within the same package, I have a second class that utilizes ClassAService in its constructor argument as follows. Note that this class is not annotated with #Component
public class ClassBService {
String id;
#Autowired
public ClassBService(ClassAService classAService) {
....
}
}
Finally, in the main Application that utilizes the package described above, i have the following xml configuration that utilizes ClassBService to create a bean definition as follows:
....
<bean id="classBService" class="com.company.package.ClassBService">
<property name="id" value="abcde" />
</bean>
Finally, i have annotated my run application class with the following:
#SpringBootApplication({
scanBasePackages= {
"com.company.package.*"
})
Given everything above, I would expect the bean defined in the xml file to inject ClassAService correctly and construct the bean. However, I keep getting the following exception
Parameter 0 of constructor in com.company.package.ClassBService required a bean of type 'com.company.package.ClassAService' that could not be found.
However, I have no such issues when I use ClassAService directly in code using #Autowire:
#Service
public class MainService {
#Autowire
public ClassAService classAService
}
It shouldn't make a difference how the beans are declared as they are stored in the application context when the app fully boots up. So what the issue here?

Class instantiation using the Autowired annotation

Is its advisable to instantiate the class using #Autowired annotation like below.
#Autowired
public static Car = new Car();
Case 1
If you are trying to autowire an attribute like following:
#Autowired
public Car car;
then Spring will try to search for a Bean definition in Spring context and will also instantiate it, hence no need to again invoke constructor.
Case 2
If you are getting confused with constructor autowire like following:
#Autowired
public Driver(License license){
this.license = license;
}
Here, it is trying to get the Bean of "License" class autowired, and it is not autowireing Driver.
In your case, I feel it is case 1.
If you are trying to set it manually cause you are seeing it as not initialized, then check the spring application context configuration file/class. You will need to have something like following in it:
<context:component-scan base-package="com.test.packagename" />
If using AppConfig class then:
#Configuration
#ComponentScan("com.test.packagename")
public class AppConfig {
}
Also, make sure that your spring core is deployed in lib where it is executing.
Also check that you are instantiating the class by using Spring application context as follows:
AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Car car= (Application)context.getBean("car");
Try to refer this: http://websystique.com/spring/spring-dependency-injection-annotation-beans-auto-wiring-using-autowired-qualifier-resource-annotations-configuration/
Happy coding DBZ fan :-)

two conversionService bean created

I am getting an error while trying to up my application
Description:
Field conversionService in com.profectus.dashboard.service.impl.DashBoardSettingsServiceimpl required a single bean, but 2 were found:
- mvcConversionService: defined by method 'mvcConversionService' in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]
- defaultConversionService: defined by method 'defaultConversionService' in class path resource [org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.class]
Action:
Consider marking one of the beans as #Primary, updating the consumer to accept multiple beans, or using #Qualifier to identify the bean that should be consumed
Why 2 beans are created and how to keep only one converter, I just want only spring core converter who can convert entity to pojo or pojo to entity.
I am stuck because of this issue, any lead would be helpful.
Service class code:-
import org.springframework.core.convert.ConversionService;
//other imports
#Service
public class DashBoardSettingsServiceimpl implements DashBoardSettingsService {
#Autowired
private DashBoardSettingJpaRepository dashBoardSettingRepo;
#Autowired
private ConversionService conversionService;
#Override
public DashBoardSettingResponse save(UserInfo userInfo, DashBoardSettingRequest request) {
//other coded
DashBoardSettigEntity entity = conversionService.convert(request.getDashBoardSetting(),
DashBoardSettigEntity.class);
DashBoardSettigEntity entityRetrieve = dashBoardSettingRepo.save(entity);
DashBoardSetting setting = conversionService.convert(entityRetrieve, DashBoardSetting.class);
DashBoardSettingResponse response = new DashBoardSettingResponse();
response.addDashBoardSetting(setting);
return response;
}
}
Autowire type DefaultConversionService instead of ConversionService
Seems like it has something to do with spring data rest having its own ConversionService instance.
Can you try this:
#Autowired #Qualifier("mvcConversionService") ConversionService conversionService;
It worked for me.
Don't forget to add your converters to a WebMvcConfigurer implementation.

Spring unit test objects autowired with null fields

I'm attempting to create unit tests for a rest service in my spring servlet. But when the controller object is created by #autowire, then all of its #autowired fields are null.
My test class is as follows, using the SpringJUnit runner and context configuration set
#ContextConfiguration(locations = "ExampleRestControllerTest-context.xml")
#RunWith(SpringJUnit4ClassRunner.class)
public class ExampleRestControllerTest {
#Autowired
private BaseService mockExampleService;
#Autowired
private ExampleRestController testExampleRestController;
The ExampleRestControllerTest-context.xml sets up the service to be mocked and injects the mocked object into the controller
<context:annotation-config/>
<import resource="classpath*:example-servlet.xml"/>
<bean id="mockExampleService" class="org.easymock.EasyMock" factory-method="createMock">
<constructor-arg index="0" value="za.co.myexample.example.services.BaseService"/>
</bean>
<bean id="testExampleRestController" class="za.co.myexample.example.rest.controller.ExampleRestController">
<property name="exampleService" ref="mockExampleService"/>
</bean>
The rest of the beans used by the controler are defined in the example-servlet.xml
<bean id="RESTCodeMapper" class="za.co.myexample.example.rest.util.RESTCodeMapper"/>
<bean id="restProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:RESTServiceCodeMapping.properties"/>
</bean>
Along with my Jax2BMarshaller.
My IDE links to these definitions just fine and if I remove any of the definitions I get an "No qualifying bean" error as expected.
My problem is that when I run my unit tests the controller that is provided has all of its fields as nulls
#Controller
public abstract class BaseRestController {
private static Logger LOGGER = Logger.getLogger(BaseRestController.class);
protected final String HEADERS = "Content-Type=application/json,application/xml";
#Autowired
protected RESTCodeMapper restCodeMapper;
#Autowired
protected BaseService exampleService;
#Autowired
protected Jaxb2Marshaller jaxb2Marshaller;
(and its implementing class)
#Controller
#RequestMapping("/example")
public class ExampleRestController extends BaseRestController {
When I run the proper code in my Weblogic server the fields get properly populated. More so if I add these fields in my test class directly those fields also get #autowired correctly. I could thus #autowire those objects in my test class and then set them directly into my controller. But that's not the right way of doing it.
So the question is, why are the autowired fields of an autowired object null in my test class when it autowires those objects directly in the same test class or if I run the code normally on my Weblogic server.
In your test class, the #Autowired objects are null because of context configuration, so change it to:
#ContextConfiguration(locations = "ExampleRestControllerTest-context.xml")
to
#ContextConfiguration(locations = "classpath:/ExampleRestControllerTest-context.xml")
in ExampleRestControllerTest
So the question is, why are the autowired fields of an autowired
object null in my test class when it autowires those objects directly
in the same test class or if I run the code normally on my Weblogic
server.
They must be null in autowired objects' constructor. You can try to create #PostConstruct method in autowired object and in this method the autowired objects must be not null

Strange spring-boot behaviour when trying to autowire javax.validation.Validator

Here's my problem:
I develop a web application based on spring-boot, the autowired annotation of spring works in every layers except for this interface "javax.validation.Validator".
When I'm trying to autowired "javax.validation.Validator" in my validator like this:
#Component
public class BrandValidator{
#Autowired
private javax.validation.Validator validator;
I've got this exception: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.validation.Validator] found for dependency
First I was thinking that no bean was available for this class in the spring context but actually when I list the bean available at the run time (after commenting the Autowired annotation on my validator) I see that this bean is available :
"mvcValidator" with the following type OptionalValidatorFactoryBean (this class extend LocalValidatorFactoryBean and LocalValidatorFactoryBean implements javax.validation.Validator and org.springframework.validation.Validator you can see here http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html)
I have try to add the #Qualifier(value ="mvcValidator") annotation but I got the same exception.
The strange part is that I m able to autowire the "spring" validator (org.springframework.validation.Validator) class perfectly well :
#Autowired
private org.springframework.validation.Validator validatorSpring;
I see in debug mode that the OptionalValidatorFactoryBean present in the context is injected.
And finally if I autowire org.springframework.validation.Validator just before javax.validation.Validator like this :
#Component
public class BrandValidator{
//workaround
#Autowired
private org.springframework.validation.Validator validatorSpring;
#Autowired
private javax.validation.Validator validator;
Now javax.validation.Validator is correctly injected(In debug mode I see that both validators the same object OptionalValidatorFactoryBean). I really don't understand what is going when the context is loaded and I really don't like this workaround (I don't need org.springframework.validation.Validator in my class).
Any idea how correctly inject javax.validation.Validator with spring boot ?
Try adding a #DependsOn(value="mvcValidator") on the BrandValidator class.

Categories

Resources