this.userDAO is null - NullPointerException

2022. 8. 19. 15:27Spring

728x90

현재, login.jsp에 들어가서 로그인을 하려는 상태이다.

 

 

로그인을 시도하면 위와같은 에러가 뜬다. 도대체 왜 이러는 걸까??

 

일단, 코드를 따라가보도록 하자!!

 

web.xml에서 *.do는 모두 presentation-layor.xml을 따라가도록 설정되어 있다.

 

 

presentation-layor 파일에서는 /login.do가 실행되어있을 경우 LoginController가 실행되도록 설정되어 있다.

 

package sonny.spring.web.user;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import sonny.spring.web.user.impl.UserServiceImpl;


public class LoginController implements Controller {
	
	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
			
		System.out.println("로그인 처리");
		// 1. 사용자 입력 정보 추출
		String id = request.getParameter("id");
		String password = request.getParameter("password");
		// 2. 데이터베이스 연동 처리
		UserVO vo = new UserVO();
		vo.setId(id);
		vo.setPassword(password);
		System.out.println(id);
		System.out.println(password);
		UserService userService = new UserServiceImpl();		
		UserVO user = userService.getUser(vo);
		
		// 3. 화면 네비게이션
		ModelAndView mav = new ModelAndView();
		if(user != null){
			mav.setViewName("health.html");
		}else{
			mav.setViewName("login.jsp");
		}
		return mav;
	}

}

 

 

오류 메세지를 다시 한번 읽어보면,  LoginController에서 UserVO user = userService.getUser(vo); 에서 오류가 발생하고,

 

package sonny.spring.web.user.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import sonny.spring.web.user.UserService;
import sonny.spring.web.user.UserVO;

@Service("userService")
public class UserServiceImpl implements UserService {

	@Autowired
	private UserDAO userDAO;

	@Override
	public UserVO getUser(UserVO vo) {
		return userDAO.getUser(vo);
	}
}

 

여기서 userDAO.getUser(vo)를 실행시키려 하였는 데, userDAO 가 NULL 값 이어서 오류가 나온 것을 확인할 수 있다.

 

@Autowired를 주었는 데 왜 객체가 자동적으로 생성이 되지 않은 것일까???

 

그 이유는 다음과 같다.

 

 

위 그림을 보면, ServiceImpl에서 @Autowired를 사용해 UserDAO에게 객체를 주입한다.

마찬가지로, DAO에서 @Autowired를 사용해 JdbcTemplate에게 객체를 주입한다.

LoginController는 UserDAO가 주입된 ServiceImpl을 받아 사용해야 된다.

 

package sonny.spring.web.user;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import sonny.spring.web.user.impl.UserServiceImpl;


public class LoginController implements Controller {
	
	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
			
		System.out.println("로그인 처리");
		// 1. 사용자 입력 정보 추출
		String id = request.getParameter("id");
		String password = request.getParameter("password");
		// 2. 데이터베이스 연동 처리
		UserVO vo = new UserVO();
		vo.setId(id);
		vo.setPassword(password);
		System.out.println(id);
		System.out.println(password);
		UserService userService = new UserServiceImpl();		
		UserVO user = userService.getUser(vo);
		
		// 3. 화면 네비게이션
		ModelAndView mav = new ModelAndView();
		if(user != null){
			mav.setViewName("health.html");
		}else{
			mav.setViewName("login.jsp");
		}
		return mav;
	}

}

하지만, 위 코드를 보면, UserService userService = new UserServiceImpl()을 이용해 객체를 생성하고 있는 것을 보고 있다.

이렇게 한다면, 스프링컨테이너 상에서 LoginController와 userService가 연결되지 않았기 때문에 자동적으로, userDAO is null이 나온다.

 

따라서, 해결 방법은 의존성주입이다.

의존성 주입 중 생성자를 이용한 의존성 주입을 사용하겠다.

(왜 ? @Autowired를 사용하지 않고 생성자를 이용해 의존성을 주입하는 지는 다음 포스팅에서 다루도록 하겠다.)

 

먼저, LoginController에 생성자를 만들어준다.

 

package sonny.spring.web.user;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;


public class LoginController implements Controller {
	
	UserService userService;
	
	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		
		System.out.println("로그인 처리");
		// 1. 사용자 입력 정보 추출
		String id = request.getParameter("id");
		String password = request.getParameter("password");
		// 2. 데이터베이스 연동 처리
		UserVO vo = new UserVO();
		vo.setId(id);
		vo.setPassword(password);
		System.out.println(id);
		System.out.println(password);
		
		UserVO user = userService.getUser(vo);
		
		// 3. 화면 네비게이션
		ModelAndView mav = new ModelAndView();
		if(user != null){
			mav.setViewName("health.html");
		}else{
			mav.setViewName("login.jsp");
		}
		return mav;
	}

	public LoginController(UserService userService) {
		super();
		this.userService = userService;
	}

	
}
	<bean id="login" class="sonny.spring.web.user.LoginController">
		<constructor-arg ref="userService"></constructor-arg>
	</bean>

 

이제 다시 실행하면,  다시 에러가 뜬다.. (에러가 뜬다고 위의 설명이 잘못된 것이 아니라, 새로운 에러가 나온 것이다.)

 

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#0' defined in ServletContext resource [/WEB-INF/config/presentation-layor.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'login' defined in ServletContext resource [/WEB-INF/config/presentation-layor.xml]: Cannot resolve reference to bean 'userService' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'userService' available

 

아 왜 이러는 것일까?? 이는 다음 포스팅에서 다루겠습니다.

 

728x90