0

I have a jsp login page for identifying users. To configure JdbcTemplate , I set up its properties with spring under "WEB-INF/applicationContext.xml" , so for loading spring context , i added some tags in web.xml . But , autowiring jdbcTemplate bean in UserDao class is causing a NullPointerException !

applicationContext.xml

 <context:annotation-config />
 <context:component-scan base-package="com.firstapp.dao"/>

 <bean id="datasource" 
      class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
     <property name="driverClassName" 
     value="oracle.jdbc.driver.OracleDriver"  />  
     <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />  
     <property name="username" value="system" />  
     <property name="password" value="oracle" />  
 </bean>  

<bean id="jdbcTemplate" 
      class="org.springframework.jdbc.core.JdbcTemplate">  
      <property name="dataSource" ref="datasource"></property>  
 </bean>  

class DAO

 public class UserDAO 
  {
   @Autowired
   private JdbcTemplate jdbcTemplate;
   ....}

class Service

  public class UserService  
   {
      private UserDAO  userDAO  = new UserDAO ();       
    ....}

web.xml

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

<listener>
  <listener-class>
     org.springframework.web.context.ContextLoaderListener
  </listener-class>
</listener>
  • Is UserDAO object is created through Spring or using new operator? Is UserDAO class is annotated with any spring annotation? – RamPrakash Aug 27 '19 at 14:51
  • @RamPrakash UserDAO object is instantiated with a new operator – Najla Chabeb Aug 28 '19 at 18:21
  • 1
    To repeat: `You cannot create Spring Bean objects directly through constructor. It's not the idea of dependency injection. Wherever you need your UserDAO, you need to autowire it, or else it won't work.` – paulsm4 Aug 28 '19 at 22:02

1 Answers1

2

I bet your UserDAO class is not defined as a Spring Bean. In that case you have two options: define your bean in XML or annotating it.

Option 1: XML

applicationContext.xml

<bean id="userDao" class="[package of UserDAO class].UserDAO">
    <property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>

In that case you won't need @Autowired on the field.

Option 2: annotation-based

applicationContext.xml

<context:annotation-config/>
<context:component-scan base-package="[package of UserDAO class]"/>

UserDAO.java

@Component
public class UserDAO {
    @Autowired
    private JdbcTemplate jdbcTemplate;
}

Please also note that it is not recommended to have fields autowired directly. You can find more on this topic here.

DummyClass.java

@Component // must be a bean as well
public class DummyClass {
    private final UserDAO userDao;

    @Autowired
    public DummyClass(UserDAO userDao) {
        this.userDao = userDao;
    }
}

Option 3: manually extract Bean from the application context

I want to emphasize that this method is not recommended and you should avoid it and use dependency injection correctly. If you need to use that method - the architecture of your application is probably wrong.

SpringBeanUtil.java

@Component
public class SpringBeanUtil implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public static <T> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }
}

UserDAO.java

public class UserDAO {
    private JdbcTemplate jdbcTemplate = SpringBeanUtil.getBean(JdbcTemplate.class);
}
dominikbrandon
  • 408
  • 4
  • 16
  • 1
    @Najla Chabeb - dominikbrandon is absolutely correct. Please "upvote" and "accept" his answer if you find it helpful. Additionally, you might be interested in this link: https://www.baeldung.com/spring-boot-configure-data-source-programmatic – paulsm4 Aug 28 '19 at 18:35
  • @paulsm4 , i did not add anything to applicationContext beacause I already had the annotation-config and component-scan tags in applicatinoContext.xml . But I added component to UserDao. And it is not working – Najla Chabeb Aug 28 '19 at 18:39
  • What is the package of your UserDAO class? And how do you create objects of this class? – dominikbrandon Aug 28 '19 at 18:41
  • @dominikbrandon I am creating objects of UserDao with new operator . Name package is : com.firstapp.dao; – Najla Chabeb Aug 28 '19 at 19:01
  • 1
    Do you mean constructor? You cannot create Spring Bean objects directly through constructor. It's not the idea of dependency injection. Wherever you need your UserDAO, you need to autowire it, or else it won't work. – dominikbrandon Aug 28 '19 at 19:05
  • 1
    You can't do that. If, by any means, you want it to work, you'll need to manually extract your bean from the application context, but it's highly not recommended. Please use dependency injection correctly. You can read more [here](https://stackoverflow.com/questions/812415/why-is-springs-applicationcontext-getbean-considered-bad). – dominikbrandon Aug 28 '19 at 19:13
  • 1
    @NajlaChabeb I have just edited my answer and added third option, which is what you're looking for. This will make it work for you. However, I still encourage you to read more about using Spring Beans correctly. – dominikbrandon Aug 28 '19 at 19:39
  • @dominikbrandon I agree with you that the third option is not the wisest way to conceive an application. I have tried your second option and added a `@`Component to UserDao, still not working for me. Am I missing something ? – Najla Chabeb Aug 28 '19 at 19:51
  • 1
    In that case you'll need to autowire the UserDAO object. When you try to instantiate Spring Bean directly with constructor, the `@Autowired`-annotated fields won't be initialized. It means that whenever you want to use UserDAO object - the class where you use it must be a bean as well. – dominikbrandon Aug 28 '19 at 20:04
  • In the case you don't know what I mean - I've attached example in my answer. – dominikbrandon Aug 28 '19 at 20:11