2

Problem to solve: I am building a Spring MVC application and would like to interact with my database.


Approach: To start, I built a straightforward mapping which when called, prints out the number of items in a specified table within my database to the console.

My code is below:

@Controller
@RequestMapping("/databaseName")
public class DatabaseController {
    private JdbcTemplate jdbcTemplate;

    public void setDatabaseDataSource (DataSource dbDataSource) {
        this.jdbcTemplate = new JdbcTemplate(dbDataSource);
    }


    @RequestMapping(value = "/getSomeCountOfElementsInMyTable", method = RequestMethod.GET)
    public void getSomeTable() {
        System.out.println("SELECT count(*) FROM TEST_TABLE is now being executed...");
        int rowCount = this.jdbcTemplate.queryForObject("SELECT count(*) FROM TEST_TABLE", Integer.class);
        System.out.println(rowCount);
    }
}

beans.xml (Keep in mind that I changed up the database credentials for this post. Assume that they are correct.)

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



    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="DatabaseController" class="com.company.project.controller.DatabaseController"/>



    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.database.jdbc.Driver"/>
        <property name="url" value="some_url_here"/>
        <property name="username" value="user"/>
        <property name="password" value="pw"/>
    </bean>

</beans>

Issues faced based on approach: I receive the following error when I connect via Postman:

HTTP Status 500 - Request processing failed; nested exception is java.lang.NullPointerException

type Exception report

message Request processing failed; nested exception is java.lang.NullPointerException

description The server encountered an internal error that prevented it from fulfilling this request.

exception

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause

java.lang.NullPointerException
    com.company.project.controller.DatabaseController.getSomeTable(DatabaseController.java:44)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:497)
    org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:178)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:444)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:432)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
note The full stack trace of the root cause is available in the Apache Tomcat/7.0.52 logs.

Apache Tomcat/7.0.52

Additional relevant information:

  1. I have tested my database connectivity in a separate, simple Java application, and I am able to get a successful connection and returned the correct result.
  2. I added my database information to both the mvc-dispatcher-servlet.xml and beans.xml files in my WEB-INF folder.
  3. I am not using an Oracle database, my goal is to connect to a Vertica database (I have explored the possibility of using Hibernate).

Question: How do I resolve the HTTP status 500 issue? It's saying that rowCount isn't appropriate to store the object but based on Spring's documentation, it is the right way to do it to my understanding. I have taken a look at a few similar questions asked (SO Question 1, SO Question 2, and CodeRanch Question 3). I do see references to a DAO but not understanding why it is needed either since it conflicts with my understanding of Spring's documentation.

Community
  • 1
  • 1
abhi
  • 1,760
  • 1
  • 24
  • 40
  • 3
    You have a NPE, this has nothing to do with a db configuration or anything. Please post the code for "DatabaseController.getSomeTable", but you probably didn't inject a mandatory dependency. – Jérémie B Feb 26 '16 at 20:13
  • @JérémieB looks like I misspelled my own function calls as I was creating the question. I did inject the dependency but I am having trouble despite configuring it. I have edited my question with my beans.xml file as well. – abhi Feb 26 '16 at 20:54
  • I didn't see your beans.xml – Jérémie B Feb 26 '16 at 20:57
  • @JérémieB take a look now (sorry, was editing the post) – abhi Feb 26 '16 at 20:57
  • Did you try to annotate `setDatabaseDataSource` method with `Autowired`? If you registered any `Datasource` in `ApplicationContext`, it should does the trick for you. – Ali Dehghani Feb 26 '16 at 20:59
  • Oh..Jérémie's answer should fix your problem but i recommend to enable annotation based mvc controllers by using `mvc` namespace. With your current approach, you should define every single controller manually and even worse, wire their dependencies manually, which is cumbersome and error prone. – Ali Dehghani Feb 26 '16 at 21:05
  • 2
    @AliDehghani I agree with you ;-) I was answering just strictly at this question – Jérémie B Feb 26 '16 at 21:08
  • @AliDehghani I want to use annotation based mvc controllers but I was having the hardest time getting those to work properly :( I am quite new to using Spring MVC, and most resources I went through confused me. If you know any good resources please feel free to share :) – abhi Feb 26 '16 at 21:10
  • 1
    @Abhi IMO if you're new to spring, it's better off to start with Spring Boot. After gaining more and more experience with boot, you can play with underlying boot magic (MVC, Security, Data, etc.) with more confidence. Spring projects usually have great documentations, so you can study them and also, use their github sample projects. – Ali Dehghani Feb 26 '16 at 21:18

2 Answers2

3

You should set the datasource of your DatabaseController :

<bean id="DatabaseController" class="com.company.project.controller.DatabaseController">
  <property name="databaseDataSource" ref="dataSource"/>
</bean>

or just annotate your setter:

@Autowired
public void setDatabaseDataSource (DataSource dbDataSource) {
    this.jdbcTemplate = new JdbcTemplate(dbDataSource);
}
Jérémie B
  • 10,611
  • 1
  • 26
  • 43
  • Thanks, however when I try to use ref="dataSource" it results in a compilation error. How could that be the case? – abhi Feb 26 '16 at 21:09
  • When hovering over it, it says that "Bean must be of type com.vertica.jdbc.DataSource type" (I'm trying to connect to a Vertica database so this may explain something) Additionally, when I do switch the class over to com.vertica.jdbc.DataSource, my property name suddenly gets highlighted and says "cannot resolve property databaseDataSource, Spring XML model validation" – abhi Feb 26 '16 at 21:20
  • 1
    the code you post is not exactly the code you use i assume. You must adapt the answers here. – Jérémie B Feb 26 '16 at 21:21
  • 1
    You've imported the wrong `DataSource` in `DatabaseController`. It's `javax.sql.DataSource` – Ali Dehghani Feb 26 '16 at 21:22
  • 1
    Adapting the answers you guys gave. I'm trying to use annotation based mvc controllers. Thank you for all the insight, I will update everything once I get it working properly :) – abhi Feb 26 '16 at 22:06
  • 1
    @AliDehghani and Jeremie, thank you both so much! I used the annotation based mvc controllers and it works perfectly. It took a couple of days but I'm glad it works properly. I also tried the manual method of connecting each bean for practice and that worked out as well. Thanks again! – abhi Feb 29 '16 at 13:40
1

you have to inject the jdbcTemplate into your Controller.

Annotate it with @Autowired so that can Spring injects it.

WeMakeSoftware
  • 9,039
  • 5
  • 34
  • 52
  • Thanks for your answer! However when I do annotate the jdbcTemplate with @Autowired, I get the following error: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'databaseController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.jdbc.core.JdbcTemplate com.bnymellon.ca.controller.databaseController.jdbcTemplate; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException – abhi Feb 26 '16 at 20:32
  • your jdbcTemplate is not configured. you have to configure it – WeMakeSoftware Feb 26 '16 at 20:34