Abhinab Kanrar
Abhinab Kanrar

Reputation: 1552

Spring 3 MVC:java.lang.IllegalArgumentException: Property 'dataSource' is required.How to set JdbcTemplate correctly?

I'm new to Spring development.And right now,i'm really facing a problem.Here are the code snippets to make you realize my problem clearly.............

Here is my DAO class:

public class LoginDaoImpl {

    private DataSource dataSource;              
    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public int checkLoginDetails(LoginVo loginVo){
        String sql = "select count(*) from empsctygrp where username=? and password=?";
        jdbcTemplate = new JdbcTemplate(dataSource);  
        int count = jdbcTemplate.queryForObject(sql,new Object[]{loginVo.getUserName(),loginVo.getPassword()},Integer.class);
        return count;
    }   
}

Now here is my Business-Object(BO) class:

public class LoginBo {

    LoginDaoImpl loginDaoImpl = new LoginDaoImpl();

    public int checkLoginDetails(LoginVo loginVo){      
        return loginDaoImpl.checkLoginDetails(loginVo);
    }
}

Now,here is my dispatcher-servlet xml code:

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

<bean id="loginDaoImpl" class="com.abhinabyte.dao.LoginDaoImpl">
    <property name="dataSource" ref="dataSource" />
</bean>

Now whenever i'm trying to run this on server the following exception is given:

SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/A] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: Property 'dataSource' is required] with root cause

java.lang.IllegalArgumentException: Property 'dataSource' is required


Please help me solve this problem.............:(

Upvotes: 1

Views: 10180

Answers (3)

Ivan Rodrigues
Ivan Rodrigues

Reputation: 469

You should annotate that beans that will suffer IoC. Like

@Bean public class LoginDAOImpl { @Inject DataSource dataSource;......}

You set up in spring context this beans, but, you're not using them.

OBS:

When I use the JDBCTemplate I configure de IoC of JDBC like

<bean id="dataSourcePerfil" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="${br.com.dao.jdbc.driver}" /> 
    <property name="url" value="${br.com.dao.jdbc.url}" /> 
    <property name="username" value="${br.com.dao.jdbc.user}" /> 
    <property name="password" value="${br.com.dao.jdbc.pass}" /> 
</bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <constructor-arg ref="dataSourcePerfil" />
</bean>

then.... after at all

@Bean

public class LoginDAOImpl {

@Autowired
private JdbcTemplate jdbcTemplate;


@Override
public List<ClienteReport> getClientes() {
    return Collections<ClienteReport>. emptyList();
}

}

Upvotes: 0

Lydia Ralph
Lydia Ralph

Reputation: 1473

I was having the same problem and could not find a comprehensive answer on the web, so I decided to post one here for anyone else, or for future me.

I'm still learning so if you think I have made a mistake below, please feel free to edit.

Summary:

  • Include <integration:annotation-config/> <context:component-scan base-package="myproject"/> in your servlet to pick up annotations
  • Configure JUnit tests with @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("file:WEB-INF/FinanceImportTool-servlet.xml")
  • Don't autowire dataSource or jdbcTemplate if these fields are already provided by a parent class e.g. StoredProcedure
  • Don't use new() as this initializes classes outside the applicationContext
  • Beware of using properties in your constructor which have not yet been set - obvious but embarrassingly easy to do

My original class (now altered):

public class MyDAOImpl extends StoredProcedure implements MyDAO {
    private static final String SPROC_NAME = "dbo.MySP";    

    public MyDAOImpl(DataSource dataSource) {
        super(dataSource, SPROC_NAME); 
        // ...declared parameters...
        compile();
    }
}

MyProject-servlet.xml file (only relevant bits included):

<!-- Used by Spring to pick up annotations -->
<integration:annotation-config/>
<context:component-scan base-package="myproject"/>

<bean id="MyDAOBean" class="myproject.dao.MyDAOImpl" >
    <constructor-arg name="dataSource" ref="myDataSource"/>
</bean>

<!-- properties stored in a separate file -->
<bean id="myDataSource" class="com.microsoft.sqlserver.jdbc.SQLServerDataSource">
    <property name="databaseName" value="${myDataSource.dbname}" />
    <property name="serverName" value="${myDataSource.svrname}" />
    <!-- also loaded portNumber, user, password, selectMethod -->
</bean>

Error: property 'dataSource' is required, or NullPointerException (1)

Other answers say make sure you have passed dataSource as a <property> for your bean in the servlet, etc.

I think @Abhinabyte the OP needed to annotate his setDataSource() method with @Annotation, and use <integration:annotation-config/> <context:component-scan base-package="myproject"/> in his servlet to successfully pass in dataSource as a dependency to LoginDaoImpl.

In my case, I tried adding 'dataSource' as a property and autowiring it. The "dataSource is required" error message became a NullPointerException error.

I realised after far too long that MyDAOImpl extends StoredProcedure.

dataSource was already a property of StoredProcedure. By having a dataSource property for MyDAOImpl, the autowiring was not picking up and setting the dataSource property of StoredProcedure, which left dataSource for StoredProcedure as null.

This was not picked up when I tested the value of MyDAOImpl.dataSource, as of course by now I had added a MyDAOImpl.dataSource field that had been autowired successfully. However the compile() method inherited from StoredProcedure used StoredProcedure.dataSource.

Therefore I didn't need public DataSource dataSource; property in MyDAOImpl class. I just needed to use the StoredProcedure constructor with super(dataSource, sql); in the constructor for MyDAOImpl.

I also didn't need a MyDAOImpl.jdbcTemplate property. It was set automatically by using the StoredProcedure(dataSource, sql) constructor.


Error: NullPointerException (2)

I had been using this constructor:

private static final String SPROC_NAME = "dbo.MySP";

public MyDAOImpl(DataSource dataSource) {
    super(dataSource, SPROC_NAME);
}

This caused a NullPointerException because SPROC_NAME had not been initialized before it was used in the constructor (yes I know, rookie error). To solve this, I passed in sql as a constructor-arg in the servlet.


Error: [same error message appeared when I had changed file name]

The applicationContext was referring to the bin/ instances of my beans and classes. I had to delete bin/ and rebuild the project.


My new class:

   public class MyDAOImpl extends StoredProcedure implements MyDAO {

   @Autowired // Necessary to prevent error 'no default constructor found'
   public MyDAOImpl(DataSource dataSource, String sql) {
       super(dataSource, sql);
        // ...declared parameters...
        compile();
   }

New MyProject-servlet.xml file (only relevant bits included):

<!-- Used by Spring to pick up annotations -->
<integration:annotation-config/>
<context:component-scan base-package="myproject"/>

<bean id="myDAOBean" class="org.gosh.financeimport.dao.MyDAOImpl" >
    <constructor-arg name="dataSource" ref="reDataSource"/>
    <constructor-arg name="sql" value="dbo.MySP" />
</bean>

<!-- properties stored in a separate file -->
<bean id="myDataSource" class="com.microsoft.sqlserver.jdbc.SQLServerDataSource">
    <property name="databaseName" value="${myDataSource.dbname}" />
    <property name="serverName" value="${myDataSource.svrname}" />
    <!-- also loaded portNumber, user, password, selectMethod -->
</bean>

Helpful places:

If you can get past the rage, this answer on Spring forums might help too

This answer gives a broad introduction to Spring configuration

This answer has simple but useful suggestions

Upvotes: 0

Shinichi Kai
Shinichi Kai

Reputation: 4513

Try this in LoginBo class:

@Autowired
LoginDaoImpl loginDaoImpl;

instead of

LoginDaoImpl loginDaoImpl = new LoginDaoImpl();

The problem is that you manually instantiate LoginDaoImpl.

Upvotes: 0

Related Questions