This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 8 years ago.
When I create my ApplicationContext the myBean Constructors are used successfully.
But after creation the beans are null using #Autowired tag.
I though #Autowired would replace getBean() somehow? Am I getting this wrong?
Why do I need to call GetBean, when I already created my Beans (during ApplicationContext startup) and also Autowired them?
Here is what I have done so far:
Main:
#EnableAutoConfiguration
#Configuration
#ComponentScan("com.somePackage")
public class Main {
ApplicationContext ctx= new AnnotationConfigApplicationContext(AppConfig.class);
SomeBean myBean = ctx.getBean(SomeBean.class);
myBean.doSomething();//succeeds
AnyOtherClass aoc = new AnyOtherClass();//Nullpointer (see AnyOtherClass.class for details)
}
AnyOtherClass:
public class AnyOtherClass {
#Autowired
protected SomeBean someBean;
public AnyOtherClass(){
someBean.doSomething();//Nullpointer
}
AppConfig:
#Configuration
public class AppConfig {
#Bean
#Autowired
public SomeBean BeanSomeBean() {
return new SomeBean();
}
}
MyBean:
public class SomeBean {
public SomeBean (){}
public void doSomething() {
System.out.println("do Something..");
}
}
Note: Interface ApplicationContextAware works fine but without #Autowired. And I would really like to go with #Autowired since it sounds more comfortable and less errorprone to me.
For #Autowired to work in AnyOtherClass, AnyOtherClass needs to be a Spring bean.
Something like this
AppConfig
#Configuration
public class AppConfig {
#Bean
#Autowired
public SomeBean BeanSomeBean() {
return new SomeBean();
}
#Bean
#Autowired
public AnyOtherClass BeanAnyOtherClass() {
return new AnyOtherClass();
}
}
Main
#EnableAutoConfiguration
#Configuration
#ComponentScan("com.somePackage")
public class Main {
ApplicationContext ctx= new AnnotationConfigApplicationContext(AppConfig.class);
SomeBean myBean = ctx.getBean(SomeBean.class);
myBean.doSomething();//succeeds
AnyOtherClass aoc = ctx.getBean(AnyOtherClass.class);
}
If you instantiate a class using new AnyOtherClass(), it will bypass Spring and none of the annotations will work. You must get it out of Spring context in order for it to be a Spring bean.
Try
#Component
public class AnyOtherClass {
#Autowired
protected SomeBean someBean;
public AnyOtherClass(){
someBean.doSomething();//Nullpointer
}
Besides, you need to make sure this class is in com.somePackage package.
Related
This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 2 years ago.
Field in my project is null and I don't have idea why. I don't initalize in project any autowired variable like new BingoGameService(); - so I don't know why I got null.
public class MessageReaction extends ListenerAdapter {
#Autowired
BingoGameService bingoGameService; //NULL
#Override
public void onMessageReceived(#Nonnull MessageReceivedEvent event) {
if(event.getMessage().getContentRaw().equals("!createBingo")) bingoGameService.createBingoGameForUser(event.getAuthor().getIdLong());
This is my service class:
#Service
public class BingoGameService {
#Autowired
DiscordUserRepo discordUserRepo;
#Autowired
BingoBoardRepo bingoBoardRepo;
#Autowired
GameMechanics gameMechanics;
public void createBingoGameForUser(Long id) {
if(bingoBoardRepo.findById(1L).isPresent()){
String[][] officialBingoBoard = bingoBoardRepo.findById(1L).get().getBingoBoard();
int[][] scoreBoard = gameMechanics.createScoreBoard(3,3);
DiscordUser discordUserToSave = new DiscordUser();
BingoGame bingoGame = new BingoGame(discordUserToSave, officialBingoBoard, scoreBoard);
discordUserToSave.setUserId(id);
discordUserToSave.setBingoGame(bingoGame);
discordUserRepo.save(discordUserToSave);
}
}
you don't need use #Autowired if you create class with constructor.
Add #Component over MessageReaction class
Spring Boot search for annotation like "#Component" "#Service" etc. if you don't include them over class name, it won't know where inject values/classes
#Component
public class MessageReaction extends ListenerAdapter {
private FooService fooService;
public MessageReaction(FooService fooService){
this.fooService = fooService
}
}
Depends on the category of layering of your app, you can annotate classes as #Component, #Service or #Repository.
I didn't see any annotation for the class MessageReaction. If it is a generic component you have to annotate it with #Component.
This annotation helps Spring container to instantiate the instance of your class MessageReaction and autowire the injected dependencies. Since there is no default constructor for the class MessageReaction, you have to annotate the dependency BingoGameService with #Autowired annotation.
I'm having a problem injecting mock into one class I need for testing. I'm trying to mock a Dao class and had no problem doing so using ReflectionTestUtils in various services I'm using, however this one just does not want to work, it keeps calling the Dao class and getting errors from the database.
This is the test class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
#WebAppConfiguration
public class DedicationControllerTest extends AbstractRestTest {
#Mock
UserDaoImpl userDao;
#Autowired
#InjectMocks
GrantedAuthoritiesLevelsHolder grantedAuthoritiesLevelsHolder;
#Test
public void shouldTest() throws Exception {
//given
String json = this.getJsonFromFile("json/my.json");
Mockito.when(userDao.getUser(Mockito.anyString())).thenReturn(new User(1l, "mock"));
ReflectionTestUtils.setField(grantedAuthoritiesLevelsHolder, "userDao", userDao);
ResultActions result = mockMvc.perform(post( controllerUrl + "/action")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(json));
// then
result
.andExpect(status().isOk());
}
}
And this is the class I'm trying to inject mock into:
#Component
#Scope(value="session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class GrantedAuthoritiesLevelsHolder {
#Autowired
private UserDao userDao;
// some methods
}
You will have to register mocked bean as UserDao when the context is getting loaded. You can register it as shown below. Put this in any class annotated with #Configuration
#Bean
#Primary
public UserDao UserDao() {
return mock(UserDao.class);
}
I believe that your configuration may be not enough to put a mock into Spring context.
My advice:
#MockBean(answer=Answers.RETURNS_SMART_NULLS)
UserDao userDao;
#Autowired
GrantedAuthoritiesLevelsHolder grantedAuthoritiesLevelsHolder;
It should put a mock into Spring context, moreover it should give you hints with incorrect/missing stubbing.
I have a setup like:
#Configuration
public class MyConfig {
#Autowired
ApplicationContext applicationContext;
#Bean
public MyBean myBean() {
return applicationContext.getAutowireCapableBeanFactory().createBean(MyBean.class);
}
}
Soon as I launch my Application, Spring tries to create myBean even before injecting applicationContext. As the latter is null, it will cause a NullPointerException in the method myBean().
Strangely, injecting the Application Context works in some other #Configuration classes, but not in the one mentioned above.
Is there a way force the injection of applicationContext before the method myBean() is called?
I don't think that you have the guarantee that the fields declared with #Autowired be always loaded before the invocation of the methods declared with #Bean .
To ensure that the ApplicationContext object is valued, you could make your configuration class implement ApplicationContextAware.
#Configuration
public class MyConfig implements ApplicationContextAware {
private ApplicationContext context;
public void setApplicationContext(ApplicationContext context) {
this.context = context;
}
...
}
I have several classes in a Spring Boot project, some work with #Autowired, some do not. Here my code follows:
Application.java (#Autowired works):
package com.example.myproject;
#ComponentScan(basePackages = {"com.example.myproject"})
#Configuration
#EnableAutoConfiguration
#EnableJpaRepositories(basePackages = "com.example.myproject.repository")
#PropertySource({"classpath:db.properties", "classpath:soap.properties"})
public class Application {
#Autowired
private Environment environment;
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
#Bean
public SOAPConfiguration soapConfiguration() {
SOAPConfiguration SOAPConfiguration = new SOAPConfiguration();
SOAPConfiguration.setUsername(environment.getProperty("SOAP.username"));
SOAPConfiguration.setPassword(environment.getProperty("SOAP.password"));
SOAPConfiguration.setUrl(environment.getProperty("SOAP.root"));
return SOAPConfiguration;
}
HomeController (#Autowired works):
package com.example.myproject.controller;
#Controller
class HomeController {
#Resource
MyRepository myRepository;
MyService (#Autowired does not work):
package com.example.myproject.service;
#Service
public class MyServiceImpl implements MyService {
#Autowired
public SOAPConfiguration soapConfiguration; // is null
private void init() {
log = LogFactory.getLog(MyServiceImpl.class);
log.info("starting init, soapConfiguration: " + soapConfiguration);
url = soapConfiguration.getUrl(); // booom -> NullPointerException
I do not get the SOAPConfiguration but my application breaks with a null pointer exception when I try to access it.
I have already read many Threads here and googled around, but did not find a solution yet. I tried to deliver all necessary information, please let me know if anything misses.
I guess you call init() before the autowiring takes place. Annotate init() with #PostConstruct to make it call automatically after all the spring autowiring.
EDIT: after seeing your comment, I guess you are creating it using new MyServiceImpl(). This takes away the control of the MyServiceImpl from Spring and gives it to you. Autowiring won't work in those case
Did you created a bean for the class SOAPConfiguration in any of your configuration classes? If you want to autowire a class in your project, you need to create a bean for it. For example,
#Configuration
public class SomeConfiguration{
#Bean
public SOAPConfiguration createSOAPConfiguration(){
return new SOAPConfiguration();
}
}
public class SomeOtherClass{
#Autowired
private SOAPConfiguration soapConfiguration;
}
I try to implement using Spring 3.1.0.RELEASE + Hibernate to make RESTful web service followed this guy's project https://github.com/eugenp/REST
when I run my project is contain error like this.
SEVERE: Context initialization failed
*.BeanCreationException: Error creating bean with name 'userServiceController': Injection of autowired dependencies failed;
*.BeanCreationException: Error creating bean with name 'defaultUserService': Injection of autowired dependencies failed;
*.BeanCreationException: Could not autowire field: private com.cloudlb.dao.UserDAO com.cloudlb.service.DefaultUserService.userDao;
*.NoSuchBeanDefinitionException: No matching bean of type [com.cloudlb.dao.UserDAO]
This is my configuration: (persistence.properties)
ApplicationConfig:
#Configuration
#ComponentScan(basePackages = "com.cloudlb", excludeFilters = { #ComponentScan.Filter(Configuration.class)})
public class ApplicationConfig {
#Bean
public static PropertyPlaceholderConfigurer properties() {
final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
final Resource[] resources = new ClassPathResource[]{new ClassPathResource("persistence.properties"), new ClassPathResource("restful.properties")};
ppc.setLocations(resources);
ppc.setIgnoreUnresolvablePlaceholders(true);
return ppc;
}
In PersistenceHibernateConfig contain like this:
#Profile("hibernate")
#EnableTransactionManagement
public class PersistenceHibernateConfig { ...
#Bean
public LocalSessionFactoryBean alertsSessionFactoryBean() { ...
#Bean
public DataSource restDataSource() { ...
#Bean
public HibernateTransactionManager transactionManager() { ...
WebConfig:
#Configuration
#EnableWebMvc
public class WebConfig { ... }
So, it start get an error in autowired from here:
UserServiceController:
#Controller
public class UserServiceController {
#Autowired
private UserService userService;
UserService which is implemented by DefaultUserService:
#Service
#Transactional(propagation = Propagation.REQUIRED)
public class DefaultUserService implements UserService {
#Autowired
private UserDAO userDao;
UserDAO:
public interface UserDAO extends GenericDAO<User> { ... }
UserHibernateDAO:
#Profile("hibernate")
public class UserHibernateDAO extends GenericHibernateDAO<User> implements UserDAO{ ... }
GenericHibernateDAO:
#Profile("hibernate")
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class GenericHibernateDAO<T extends Serializable> extends AbstractHibernateDAO<T> implements GenericDAO<T> { ... }
And last one AbstractHibernateDAO:
#Transactional( propagation = Propagation.SUPPORTS )
public abstract class AbstractHibernateDAO<T extends Serializable> implements DAO<T> {
private Class<T> clazz;
#Autowired
private SessionFactory sessionFactory;
public AbstractHibernateDAO() {
super();
}
public final void setClazz(final Class<T> clazz) {
this.clazz = clazz;
}
#Override
#Transactional( readOnly = true )
public T findById(String id) {
return (T) this.getCurrentSession().get(this.clazz, id);
}
protected Session getCurrentSession() {
return this.sessionFactory.getCurrentSession();
}
}
I thought it could find UserHibernateDAO. May be I missing something here. So, hope someone know how to fix it. I struck at this problem for 2 day.
I guess there could be a problem in SessionFactory too. Because I start to fix that thing and this came up.
Thank you in advance.
In addition to #Profile("hibernate") the UserHibernateDAO needs an annotation declaring it a Spring bean like #Named or #Component.