공부/JAVA

JNDI셋팅(tomcat,mysql) 중 발생한 에러 및 처리

JangGiraffe 2022. 9. 28. 22:00
	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiName" value="java:comp/env/jdbc/npwbDB"></property>
	</bean>

tomcat - mysql - jndi 셋팅 중 에러 및 처리에 대한 기록입니다.

 

1. SqlSession Autowired 문제

sqlSession autowired가 안되 발생한 문제다.

에러 내용을 보면 datasource bean을 못찾는것.

실제로 소스를 확인해보면, sqlSessionFactory에 등록된 datasource가 찾을 bean이 없다.!

 

 

testDao.java

@Repository
public class testDao {

	@Autowired
	SqlSession sqlSession;
	
	@SuppressWarnings("unchecked")
	public List<HashMap<String,String>> getGospe() {
		HashMap<String,String> input = new HashMap<String, String>();
		input.put("type", "AD");
		return sqlSession.selectList("sqlBibleMapper.selectGospel",input);	
	}
	
}

root-context.xml

<?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:context="http://www.springframework.org/schema/context"
	
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	https://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
        <context:component-scan base-package="com.wb.hb.bible.dao"></context:component-scan>	
	
	<!-- Root Context: defines shared resources visible to all other web components -->
	<bean id ="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<property name="configLocation" value="classpath:/mybatis-config.xml"></property>
		<property name="mapperLocations" value="classpath:mappers/**/*_sql.xml"></property>
	</bean>
	
	<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
         <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
    </bean>
</beans>

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <environments default="jndi">
    <environment id="jndi">
      <transactionManager type="JDBC" />
      <dataSource type="JNDI">
        <property name="data_source" value="java:comp/env/jdbc/npwbDB" />
      </dataSource>
    </environment>
  </environments>
</configuration>
  <mappers>
  	<mapper resource="/mappers/Bible_sql.xml"/>
  </mappers>

 

에러메시지

ERROR: org.springframework.web.servlet.DispatcherServlet - Context initialization failed 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field:

더보기

ERROR: org.springframework.web.servlet.DispatcherServlet - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.wb.hb.bible.dao.testDao com.wb.hb.HomeController.dao; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testDao': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.apache.ibatis.session.SqlSession com.wb.hb.bible.dao.testDao.sql; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.apache.ibatis.session.SqlSession] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:631)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:588)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:645)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:508)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:449)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:133)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1199)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1143)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1032)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5006)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5298)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:939)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:465)
at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1608)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at org.apache.catalina.manager.ManagerServlet.check(ManagerServlet.java:1460)
at org.apache.catalina.manager.ManagerServlet.deploy(ManagerServlet.java:733)
at org.apache.catalina.manager.ManagerServlet.doPut(ManagerServlet.java:432)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:651)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:606)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)

 

해결책

1)web.xml에 root-context.xml 설정파일을 읽도록 추가하기

<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>
			/WEB-INF/spring/appServlet/servlet-context.xml
			/WEB-INF/spring/root-context.xml
			</param-value>
			<!--2019.10.05 root-context.xml에 있는 sqlsession을 authwired를 못해서 설정파일을 추가해줌-->
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

2)root-context.xml에 datasource bean등록

 	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="datasource" value="java:comp/env/jdbc/npwbDB"></property>
	</bean>

 

 

1-2. datasource의 getter,setter를 못찾는 문제

에러메시지는 다음과 같다.

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.wb.hb.bible.dao.testDao com.wb.hb.HomeController.dao; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testDao': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.apache.ibatis.session.SqlSession com.wb.hb.bible.dao.testDao.sqlSession; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSession' defined in ServletContext resource [/WEB-INF/spring/root-context.xml]: Cannot resolve reference to bean 'sqlSessionFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in ServletContext resource [/WEB-INF/spring/root-context.xml]: Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in ServletContext resource [/WEB-INF/spring/root-context.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'dataSource' of bean class [org.springframework.jndi.JndiObjectFactoryBean]: Bean property 'dataSource' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:506)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284)
	... 65 more

내가 설정한 dataSource의 getter,setter를 찾지 못해 autowired를 실패하는것.

 

해결책

이건 단순한 내 삽질덕이었다.

https://stackoverflow.com/questions/16466759/spring-jndi-datasource-setup

 

spring jndi datasource setup

Hi i am trying to use jndi data source. below is the code context.xml stackoverflow.com

스택오버플로우에 따르면, 아래와 같이 적혀있다.

Looking at the JndiObjectFactoryBean it looks like you want the setJndiName() method from JndiObjectLocator super class.

수정된 소스는 다음과 같다.. datasource propertydml name옵션을 다음과같이 바꾸는것.

	<bean id ="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<property name="configLocation" value="classpath:/mybatis-config.xml"></property>
		<property name="mapperLocations" value="classpath:mappers/**/*_sql.xml"></property>
	</bean>

 

 

2.  Mapped Statements collection already contains value.

에러메시지는 다음과 같다.

nested exception is java.lang.RuntimeException: Error parsing Mapper XML. Cause: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for sqlBibleMapper.selectGospel

뭔가 메퍼 xml파일의 sql id가 중복된다는 에러메시지.

하지만 딱히 중복되어 쓰지 않았고, 설정파일 문제일것이라고 생각했다.

 

문제는 매퍼파일을 여러개의 설정파일에서 부르는것.

 

 

root-context.xml (mapperLocations)

	<!-- Root Context: defines shared resources visible to all other web components -->
	<bean id ="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<property name="configLocation" value="classpath:/mybatis-config.xml"></property>
		<property name="mapperLocations" value="classpath:mappers/**/*_sql.xml"></property>
	</bean>

root-context.xml에서 호출한 mybatis-config.xml

  <mappers>
  	<mapper resource="/mappers/Bible_sql.xml"/>
  </mappers>

이런식으로 두번 호출하는게 문제가 됐음.

해결방법은뭐..

mybatis-config.xml에 해당 소스 주석처리.

 

3. expected at least 1 bean which qualifies as autowire candidate for this dependency.

이건 신규 Dao를 생성하고 발생한 문제인데, 클래스에 @Repository어노테이션이 없어 발생한 문제이다.

 

 

이후 정상적으로 쿼리가 작동했음.

반응형