에러

org.h2.jdbc.JdbcSQLNonTransientConnectionException

 

[ 에러 화면 ]

 

 

에러 상세

org.h2.jdbc.JdbcSQLNonTransientConnectionException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-199]
	at org.h2.message.DbException.getJdbcSQLException(DbException.java:617) ~[h2-1.4.199.jar:1.4.199]
	at org.h2.message.DbException.getJdbcSQLException(DbException.java:427) ~[h2-1.4.199.jar:1.4.199]
	at org.h2.message.DbException.get(DbException.java:205) ~[h2-1.4.199.jar:1.4.199]
	at org.h2.message.DbException.get(DbException.java:181) ~[h2-1.4.199.jar:1.4.199]
	at org.h2.message.DbException.get(DbException.java:170) ~[h2-1.4.199.jar:1.4.199]
	at org.h2.jdbc.JdbcConnection.checkClosed(JdbcConnection.java:1571) ~[h2-1.4.199.jar:1.4.199]
	at org.h2.jdbc.JdbcConnection.checkClosed(JdbcConnection.java:1547) ~[h2-1.4.199.jar:1.4.199]
	at org.h2.jdbc.JdbcConnection.clearWarnings(JdbcConnection.java:708) ~[h2-1.4.199.jar:1.4.199]
	at org.apache.tomcat.jdbc.pool.PooledConnection.clearWarnings(PooledConnection.java:813) ~[tomcat-jdbc-9.0.10.jar:na]
	at org.apache.tomcat.jdbc.pool.ConnectionPool.returnConnection(ConnectionPool.java:937) [tomcat-jdbc-9.0.10.jar:na]
	at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:100) [tomcat-jdbc-9.0.10.jar:na]
	at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108) [tomcat-jdbc-9.0.10.jar:na]
	at org.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor.invoke(AbstractCreateStatementInterceptor.java:69) [tomcat-jdbc-9.0.10.jar:na]
	at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108) [tomcat-jdbc-9.0.10.jar:na]
	at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:81) [tomcat-jdbc-9.0.10.jar:na]
	at com.sun.proxy.$Proxy73.close(Unknown Source) [na:na]
	at org.springframework.boot.devtools.autoconfigure.DevToolsDataSourceAutoConfiguration$NonEmbeddedInMemoryDatabaseShutdownExecutor$InMemoryDatabase.lambda$new$1(DevToolsDataSourceAutoConfiguration.java:140) [spring-boot-devtools-2.1.6.RELEASE.jar:2.1.6.RELEASE]
	at org.springframework.boot.devtools.autoconfigure.DevToolsDataSourceAutoConfiguration$NonEmbeddedInMemoryDatabaseShutdownExecutor$InMemoryDatabase.shutdown(DevToolsDataSourceAutoConfiguration.java:157) [spring-boot-devtools-2.1.6.RELEASE.jar:2.1.6.RELEASE]
	at org.springframework.boot.devtools.autoconfigure.DevToolsDataSourceAutoConfiguration$NonEmbeddedInMemoryDatabaseShutdownExecutor.destroy(DevToolsDataSourceAutoConfiguration.java:103) ~[spring-boot-devtools-2.1.6.RELEASE.jar:2.1.6.RELEASE]
	at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:258) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:571) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:543) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:1036) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:504) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:1029) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1057) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:562) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:742) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:389) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:311) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
	at pt.server.chat.PtServerApplication.main(PtServerApplication.java:12) ~[classes/:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_111]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_111]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_111]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_111]
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.1.6.RELEASE.jar:2.1.6.RELEASE]

 

 

개발환경

IDE : Eclipse Java EE Oxygen.2 Release (4.7.2) Build id : 20171218-0600

OS : Windows10

Server Framework : Spring Boot 2.1.6 release

 

 

상황

작성자는 Spring Boot 를 사용해서 개발 중이다. 서버 프로젝트 2개를 병합하는 작업을 하던 중에 위 처럼 JdbcSQLNonTransientConnectionException 라는 에러가 발생했다. 에러가 발생한 정확한 시점은 (Run As > Java Run Application을 클릭해서) Java 서버 프로그램을 실행시키던 도중 런타임(Runtime)으로 발생한 것이다.

 

이 에러가 발생할 수 있는 상황들이 많이 있었기에, 다양한 해결방법들이 있었다. 하지만 현재 작성자가 처한 상황을 해결할 수있는 방법은 찾을 수 없었기에 포스팅을 한다.

 

작성자의 pom.xml은 아래와 같다. pom.xml의 정보가 위 에러를 발생시킨 원인과는 전혀 상관이 없지만 참고를 위해 기록한다.

 

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.6.RELEASE</version>
		<relativePath/>
	</parent>
    
	...
    
	<properties>
		<java.version>1.8</java.version>
		<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
    		<groupId>com.h2database</groupId>
		    <artifactId>h2</artifactId>
		    <scope>runtime</scope>
		</dependency>
        
		...        
        
	</dependencies>

	...

</project>

 

 

원인

작성자의 경우, @Service(=org.springframework.stereotype.Service)를 작성하지 않았기 때문에 발생한 것이다. 현재 작성자는 Spring을 사용해서 프로젝트를 아래처럼 Controller와 Service, Repository를 패키지로 나눈 형태로 구조화시켜서 개발 중이다. 

 

(개발중인) 프로젝트 패키지 일부

- com.sample.controller

 > AController.java

- com.sample.service

 > AService.java 

- com.sample.repository

 > ARepository.java

 

 

AController.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import com.sample.service.AService;

@Controller
public class AController {
	@Autowired
	AService aService;
	..
}

AService.java

import org.springframework.beans.factory.annotation.Autowired;
import com.sample.repository.ARepository;

public class ASerivce {
	@Autowired
	ARepository aRepo;
	..
}

ARepository.java

import org.springframework.data.repository.CrudRepository;
import com.sample.data.AItem;

public interface ARepository extends CrudRepository<AItem, Integer> {

}

 

위 3가지 java 파일을 보면 조금 잘못된 부분이 있다. AService 클래스 위에 @Service가 없고, AController에서는 AService를 @Autowired해서 사용하고 있다. 다시 말해서, 에러를 발생시킨 코드는 AService 를 Service로 등록시키지 않고 Controller에서 사용하려고 시도했기 때문이었다.

 

 

해결

앞에서 설명했다시피, @Service 어노테이션을 사용해서 ASerivce를 서비스로 등록시키면 된다. 코드를 수정하면 아래와 같다. 작성자의 경우 작은 실수로 인해 발생한 에러의 원인을 찾아내는데 시간이 한참 걸렸지만, 작성자처럼 이런 실수를 해서 시간을 허비하지 않기를 바란다. 

 

AService.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.sample.repository.ARepository;

@Service
public class ASerivce {
	@Autowired
	ARepository aRepo;
	..
}