2016-04-22 3 views
0

Общая информация: Новинка для загрузки спринта и захотели проверить мои соединения JDBC с помощью модульных тестов. Я сделал простой класс для подключения к моей базе данных и простому тестовому классу, чтобы следить за правильным тестовым случаем.Получение java.lang.NullPointerException с Spring Boot JdbcTemplate

Проблема: Непрерывное получение исключения java.lang.NullPointer при выполнении jdbcTemplate.getDataSource().getConnection(); У меня возникли проблемы с пониманием причин. Я пробовал использовать разные базы данных и обеспечил связь с обычным JDBC. Я упомянул множество других вопросов о переполнении стека, но я все еще застрял на этом в течение последних двух дней без какого-либо прогресса. Я даже пытался использовать разные типы библиотек DataSource, но все они дают одинаковый результат.

Вопрос: Как это решить? Если кто-то может также объяснить, почему проблема возникает, и почему нам нужно использовать Spring JDBC на уровне предприятия, это было бы здорово.


Мой код:

DatabaseTableService.java

import org.springframework.jdbc.core.JdbcTemplate; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.ResponseBody; 
import org.springframework.web.bind.annotation.RestController; 

import com.vertica.jdbc.DataSource; 

@RestController 
@RequestMapping("/databaseServices") 
public class DatabaseTableService { 

    private JdbcTemplate jdbcTemplate; 
    private DataSource dataSource; 


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


    @RequestMapping("/testConnection") 
    @ResponseBody 
    public boolean canConnectToDB() { 
     boolean result; 
     try { 
      jdbcTemplate.getDataSource().getConnection(); 
      result = true; 
     } catch (Exception e) { 
      e.printStackTrace(); 
      result = false; 
     } 
     return result; 
    } 

}


beans.xml

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

    <context:component-scan base-package="com.company.project"></context:component-scan> 

    <mvc:annotation-driven/> 

    <bean id="dataSource" 
      class="com.vertica.jdbc.DataSource"> 
     <property name="URL" value="DBURLHERE"/> 
     <property name="userID" value="USERIDHERE"/> 
     <property name="password" value="PASSWORDHERE"/> 
    </bean> 






    <bean id="databaseTableService" 
      class="com.company.project.services.DatabaseTableService"> 
     <property name="dataSource" ref="dataSource"></property> 
    </bean> 


    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
     <property name="prefix"> 
      <value>/WEB-INF/</value> 
     </property> 
     <property name="suffix"> 
      <value>.jsp</value> 
     </property> 
    </bean> 

</beans> 

DatabaseTableServiceTest.java

import org.junit.After; 
import org.junit.Assert; 
import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.test.SpringApplicationConfiguration; 
import org.springframework.jdbc.core.JdbcTemplate; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 
import org.springframework.test.context.web.WebAppConfiguration; 
import org.springframework.test.web.servlet.MockMvc; 
import org.springframework.test.web.servlet.setup.MockMvcBuilders; 
import org.springframework.web.context.WebApplicationContext; 

import com.vertica.jdbc.DataSource; 


@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = ApplicationController.class) 
@WebAppConfiguration 
public class DatabaseTableServiceTest { 

    @Autowired 
    private WebApplicationContext webApplicationContext; 

    private JdbcTemplate jdbcTemplate; 
    private MockMvc mockMvc; 
    DatabaseTableService databaseTableServiceObject; 
    DataSource testDataSource = new DataSource(); 

    @Before 
    public void setUp() throws Exception { 
     mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext) 
       .build(); 

     databaseTableServiceObject = new DatabaseTableService(); 
    } 




    @Test 
    public void setDataSource() throws Exception { 
     databaseTableServiceObject.setDataSource(testDataSource); 
    } 

    @Test 
    public void validateCanConnectToDB() throws Exception { 
     Assert.assertTrue(databaseTableServiceObject.canConnectToDB()); 
    } 


    @After 
    public void tearDown() throws Exception { 
     mockMvc = null; 
     databaseTableServiceObject = null; 
     testDataSource = null; 
    } 

} 

ApplicationController.java

import org.springframework.boot.*; 
import org.springframework.boot.autoconfigure.*; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.stereotype.*; 
import org.springframework.web.bind.annotation.*; 


@SpringBootApplication 
@ImportResource({"beans.xml"}) 
@ComponentScan(basePackages = "com.company.project") 
public class ApplicationController { 

    public static void main(String[] args) throws Exception { 

     SpringApplication.run(ApplicationController.class, args); 
    } 
} 

Структура папок

Folder Structure


Spring Application Context Информация Spring Application Context Information

+0

Является ли 'ApplicationController' аннотированным с' SpringBootApplication'? Если это так, вы импортировали в него ресурс 'beans.xml'? Добавьте класс 'ApplicationController'. –

+0

Это не правило или что-то еще, но мы обычно используем автоконфигурации, когда используем Spring Boot. –

+0

@AliDehghani добавлен в класс ApplicationController. Я попытался импортировать файл beans.xml раньше, но он дал мне ошибку: java.lang.IllegalStateException: Не удалось загрузить ApplicationContext – abhi

ответ

1

Вы используете Spring бутсу и следующий очень стараться не делать. Удалите свои beans.xml и с вашего ApplicationController (который не является контроллером, а вашим фактическим приложением btw, так как ваша служба является вашим фактическим контроллером). Также предполагая, что ваш ApplicationController находится в одном пакете, вы также можете удалить @ComponentScan.

Тогда в вашем application.properties добавить следующее

spring.datasource.url=<your-url> 
spring.datasource.username=<your-username> 
spring.datasource.password=<your-password> 
spring.datasource.type=com.vertica.jdbc.DataSource 

spring.mvc.view.prefix=/WEB-INF/ 
spring.mvc.view.suffix=.jsp 

Spring Загрузочный не создаст DataSource и JdbcTemplate для вас, так что нет необходимости создавать сами. Просто @AutowireJdbcTemplate в вашем классе.

@RestController 
@RequestMapping("/databaseServices") 
public class DatabaseTableService { 

    private final JdbcTemplate jdbcTemplate; 

    @Autowired 
    public DatabaseTableService(JdbcTemplate jdbcTemplate) { 
     this.jdbcTemplate=jdbcTeplate; 
    } 

    @RequestMapping("/testConnection") 
    @ResponseBody 
    public boolean canConnectToDB() { 
     boolean result; 
     try { 
      jdbcTemplate.getDataSource().getConnection(); 
      result = true; 
     } catch (Exception e) { 
      e.printStackTrace(); 
      result = false; 
     } 
     return result; 
    } 
} 

Теперь ваш тест, это довольно беспорядок. Вы используете Spring, но сами делаете, поэтому не знаете, чего вы пытаетесь достичь.

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = ApplicationController.class) 
@WebAppConfiguration 
public class DatabaseTableServiceTest { 

    @Autowired 
    private WebApplicationContext webApplicationContext; 

    private MockMvc mockMvc; 
    private DatabaseTableService databaseTableServiceObject; 

    @Before 
    public void setUp() throws Exception { 
     mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext) 
       .build(); 
    } 

    @Test 
    public void setDataSource() throws Exception { 
     databaseTableServiceObject.setDataSource(testDataSource); 
    } 

    @Test 
    public void validateCanConnectToDB() throws Exception { 
     Assert.assertTrue(databaseTableServiceObject.canConnectToDB()); 
    } 

} 

Вы можете просто @Autowired услуга, которая в настоящее время полностью построена.

Последнее, что ваш canConnectToDB метод неисправен. Вы получаете соединение, но никогда не возвращаете/не закрываете его. Поэтому после вызова этого метода несколько раз ваше приложение перестанет работать, поскольку пул соединений будет исчерпан или ваша база данных перестает принимать соединения.

Вкратце работа с каркасом вместо рамки/вокруг рамки. Прочитайте документацию, вместо того чтобы пытаться взломать ее.

+0

Спасибо! Я пытаюсь восстановить его без использования Spring Boot. Я уточню вас, как только я получу его работу. Извините за отложенный ответ - не работал над этим проектом в течение последних нескольких недель и не хотел, чтобы вы думали, что я забыл :) – abhi

+0

Еще раз спасибо - я потратил некоторое время, чтобы прочитать документацию и перестроить ее без весны Загрузочный. – abhi