NullPointerException on a Spring bean successfully injected - java

I'm trying to use property files with Spring. Files injection works fine and I have access to my bean.
For instance, this code
#Autowired
private Properties properties;
gives me this error : No qualifying bean of type [java.util.Properties] is defined: expected single matching bean but found 2: csvHeaderProperties,systemProperties.
When I inject properties using resource, I get no error and everything seems fine :
#Component
public Class MyClass {
#Resource(name="csvHeaderProperties")
private Properties properties;
}
However, this code gives me a NPE :
#Component
public class DynCSVService {
#Autowired
private DynCSVDictionnary headerDico;
public void processFile() {
System.out.println(headerDico);
}
}
Both files are located in the same package.
Is there something wrong with this code ?

How should Spring deduce which one to insert?
You have to name it if there are two or more possible matches for injection.

You should use #Named annotation
Here is an example
#Named("userDAO")
public class EfaUserDAOImpl
And inject it where you need;
#Inject
private #Named("userDAO")
EfaUserDAO userDAO;

I found the error : it was in another file where I didn't inject DynCSVService, I used the default constructor.

Related

Access Spring Boot Actuator build.version property with #Value

THis should be easy, but doesn't work.
I have spring-boot-actuator activated in my Spring Boot (2.0.1-RELEASE) application.
The Actuator-Endpoint /actuator/info works as expected and also shows the correct version info. The file build-info.properties is present.
When trying to access the version property with (e.g. in my Spring-Controller-Class):
#Value("${build.version}) private String version;
The action fails with the error Could not resolve placeholder 'build.version' in value "${build.version}".
ANy suggestions?
With spring expression language it is pretty simple and clean.
#Value("#{buildProperties.get('version')}") // not 'build.version'
private String myAppBuildVersion;
Or better, Autowire the buildProperties bean directly to your components so you can play with it as you want.
#Autowired
private BuildProperties buildProperties;
NOTE: The autoconfiguration strips off the build. prefix. So your
SpEL expressions should use version as key. Not build.version.
I needed to add the file build-info.properties as #PropertSource
#SpringBootApplication()
#PropertySource("classpath:META-INF/build-info.properties")
public class MyApp implements WebMvcConfigurer {
[...]
}
Then you can use the build-info in annotations
#SomeAnnotation(value = "${build.version}")
public class someClass { ... }
In your #Service, put the #Value in the constructor, as a parameter of the constructor. Don't use a standalone value and try to reference it.
like this:
#Service
public class myService {
public myService(#Value("${my.param}") String myParam) {
client.withParam(myParam).build();
}
}
Where your application.properties has a value like:
my.param=http://google.com
I have tried other implementations and they do not work. for example,
#Service
public class myService {
#Value("${my.param}")
String myParam;
public myService() {
client.withParam(myParam).build();
}
}
Does not work.
In this case, the service will be initialized, but the string will be null. I can't explain it. Something to do with param construction and bean initialization timing, I guess.

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.

Inject bean at runtime reading properties file

Suppose I have a class MailConsoleService and a class MailSMTPService, both implement the MailService interface. I have a class EmailJob which loads the users from a db and send an email through a MailService instance injected by Spring.
How could I read a properties and determine at runtime which implementation of MailService to inject? The properties could change at any time the app is running, obviously.
I've thought about to create a factory bean which returns the right instance from the spring container to EmailJob but I don't know how to implement this.
Note: All my beans are configured to Singleton scope, so I guess I'll have to change to Prototype EmailJob at least.
Note 2: In the factory bean how could I avoid to read the properties file each time?
Thanks!
You can do something like this:
#Component
public class Factory {
#Autowired
private MailService mailConsoleService;
#Autowired
private MailService mailSmtpService;
#Value("${mailServiceProperty}")
private String mailServiceProperty;
public MailService getMailService() {
switch (mailServiceProperty) {
case "CONSOLE":
return mailConsoleService;
case "SMTP":
return mailSmtpService;
}
return null;
}
}
Also, you need to inject properties using PropertyPlaceholderConfigurer
I am not sure I fully understood your question. But based on what I understood, if you would like to get a bean at runtime from a properties file and the file could be changed at runtime, then the below is one way of doing this. You need a handle to the app context and get the bean name from the properties file.
The prototype scope has nothing to do with this. If you declare a bean of type prototype it means that you will get a new bean instance everytime you ask the app context for it.
#Component
public class EmailJob {
#Autowired
private ApplicationContext appContext;
public void sendEmail(){
MailSender mailSender=(MailSender)appContext.getBean(<get bean name from properties file>);
// do remaining things
}
}

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

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.

Java/Spring Problem with #Service and #Autowired annotations

[spring 3.0.5]
[jboss 5.1]
I have several classes labeled as #Service, which implements thet same interface.
For example,
#Service(value="test1")
public TestImpl1 implements Test {}
#Service(value="test2")
public TestImpl2 implements Test {}
Next, I have the following structure
public SomeClass {
#Autowired
#Qualifier("test1")
Test test1;
#Autowired
#Qualifier("test2")
Test test2;
I am getting an exception (at deployment)
10:36:58,277 ERROR [[/test-web]] Servlet /test-web threw load()
exception
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
unique bean of type [pl.tests] is defined: expected single matching
bean but found 2: [test1, test2]
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.doReso lveDependency(DefaultListableBeanFactory.java:
796)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolv eDependency(DefaultListableBeanFactory.java:
703)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostPro cessor
$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:
474)
Anyone know how to solve this?
T.
A few options:
Use #Resource(name="test1") in the injection point
can use the javax.inject.Qualifer mechanism. In short - you define an annotation (#Test) and annotate the annotation with #Qualifier. Then use #Autowired #Test on the injection point.
explicitly set qualifiers on the target bean. The docs say show only the xml version <qualifier />, but try adding #Qualifier("test1") on the service definition
Here is the documentation about it

Categories

Resources