Mahi Mali
Mahi Mali

Reputation: 37

Property 'dataSource' is required Error in java (Spring)

I am developing an web application in Java (Spring)

My java file is as,

try
    {
        JdbcTemplate jt = new JdbcTemplate(dataSource);

        System.out.println("Connection ....."+jt.toString());

        Connection conn;
        Statement st;
        conn =DriverManager.getConnection(jt.toString());
        conn = (Connection) jt.getDataSource();
        st=conn.createStatement();
        System.out.println("Connection created....."+st);
    }
    catch (Exception e) {
         System.out.println("Error Found...."+ e.getMessage());
         System.out.println("Strack Trace....."+e.getStackTrace());
    }

My spring-servlet.xml file is as,

<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/cjbranchdb" />
    <property name="username" value="root" />
    <property name="password" value="root" />
</bean>
<bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 
    <property name="dataSource"><ref bean="dataSource"/></property> 
</bean> 

But it gets an error as,

Error Found: Property 'dataSource' is required.
Strack Trace: [Ljava.lang.StackTraceElement;@7948dd

Here, I want to make a connection in Java file and pass it to the another variable as Jasper Report.

Please help, How to fix this issue?

Upvotes: 2

Views: 16083

Answers (3)

Pavel Horal
Pavel Horal

Reputation: 18224

I am guessing you are completely new to Java, JEE, Spring and JDBC. As I have stated in my comment, it is hard to answer your question, if what you are doing in there is incorrect in its base. I will try to go through few topics and hopefully also pin point where your current issue is.

Spring app structure

You need to be sure to correctly structure your project:

  • src
    • main
      • java - directory for Java sources
        • in/mmali/springtest/controller/IndexController.java - Your controller class
      • resources - directory for non-Java (re)sources
      • webapp - root for the web application resources
        • WEB-INF/web.xml - JEE web application configuration
        • WEB-INF/spring-servlet.xml - application context configuration for dispatcher servlet
  • pom.xml - Maven config (in case you are using Maven)

I would call this a common structure for Java project, mostly "standardized" by Maven.

Correct JEE config

You need to have correct web.xml configuration:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> 

    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

This is a basic configuration (without root context), which will use your spring-servlet.xml as Spring context configuration.

Correct Spring configuration

You need to have correct Spring context configuration:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <mvc:annotation-driven />
    <mvc:resources location="/resources/" mapping="/resources/**" />

    <!-- With ROOT context we would restrict component scan on controllers here -->
    <context:component-scan base-package="in.mmali.springtest" />

    <!-- Data source configuration would normally go inside ROOT context. -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/cjbranchdb" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 
        <property name="dataSource" ref="dataSource" />
    </bean> 
</beans>

This will load all classes annotated with @Component (and its companions @Controller, @Service, @Repository) as your beans. Bean in a context of Spring application is a object managed by Spring -> i.e. object which is being instantiated by Spring itself. When you want to work with a Spring bean, you need to have it injected (e.g. by using @Autowired annotation) or you need to pull it out from ApplicationContext#getBean manually.

Working with JDBC

Working with JDBC is painful with all the closeable resources and checked exceptions. That is why Spring-JDBC project wraps JDBC API so you don't have to use it.

To showcase how you should work with JDBC and also how to let Spring inject dependencies, here is a simple controller:

@Controller // Will be detected by <context:component-scan>
@RequestMapping // Will be detected by <mvc:annotation-driven> (more specifically by one of its component - RequestMappingHandlerMapping)
public class IndexController {

    @Autowired // Spring will inject JdbcTemplate here
    private JdbcOperations jdbcOperations; 

    @RequestMapping // This method should be called for requests to "/" 
    @ResponseBody // Returned string will be returned to client... normally you would register view resolver and just return name of a JSP to render
    public String renderIndex() {
        // You don't need to worry about JDBC's DataSource, Connection, ResultSet, ... just use JdbcTemplate
        long rowCount = jdbcOperations.queryForLong("SELECT COUNT(*) FROM my_test_table;");
        return "Number of rows in database is: " + String.valueOf(rowCount);
    } 

}

Note, that in a real application you would not allow controller to work with your data source directly, but rather through service and data layer.

Next steps

  • Start using logging system and never use System.out.println in a web application again ;). I suggest slf4j with its simple binding for start (later you can configure it to use logback or log4j).
  • Configure your application to use transactions. Use Spring's transaction handling (<tx:annotation-driven/> with @Transactional). It might look as magic at first, but when you discover something about AOP and proxy classes, you will then start really appretiating the principles of how Spring works.
  • Split your application logic to service layer and data (DAO) layer.
  • Check Spring's sample application (http://docs.spring.io/docs/petclinic.html) and reference application (https://github.com/spring-projects/greenhouse).

Upvotes: 10

Stanley Stein
Stanley Stein

Reputation: 397

According to the file name, I assume you that you are building a web-based application.

For capturing the error, please use a proper logging framework instead of System.out.println.

According to the error, dataSource seems null. Please kindly check if your web.xml has defined the servlet xml file, such as

<servlet>
    <servlet-name>spring_app</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
     <param-name>contextConfigLocation</param-name>
     <param-value>/WEB-INF/spring-servlet.xml</param-value>
  </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

In addition, DriverManagerDataSource is good enough for testing only. For production use, please consider Apache's Jakarta Commons DBCP or C3P0. See detail at the official webpage.

Since your XML file has mentioned

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

, the XML file should consist of a servlet section to call the object of id=JdbcTemplate. For example,

<bean id="MyServlet" class="com.my.MyServlet"> 
    <property name="jdbcTemplate"><ref bean="JdbcTemplate"/></property> 
</bean> 

Upvotes: 0

Subin Sebastian
Subin Sebastian

Reputation: 10997

JdbcTemplate jt = new JdbcTemplate(dataSource); You cant just use new keyword to construct a bean object. Obviously the references in that object will be null.

Instead you should ask spring to give you that bean object. Some thing like this.

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-servlet.xml");
JdbcTemplate jt = (JdbcTemplate)context.getBean("JdbcTemplate");

In this case spring will inject the dependency ie datasource as given in configuration.

Upvotes: 0

Related Questions