Web Project에다가 Spring MVC를 적용하는 과정에서 web.xml 에 `Listener`를 추가하고 서버를 실행시키면 아래의 메시지가 출력한다.

  
2월 04, 2013 2:50:09 오후 org.apache.catalina.core.StandardContext listenerStop
심각: Exception sending context destroyed event to listener instance of class org.springframework.web.context.ContextLoaderListener
java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext
	at org.springframework.context.support.AbstractRefreshableApplicationContext.getBeanFactory(AbstractRefreshableApplicationContext.java:172)
	at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1071)
	at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1045)
	at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:993)
	at org.springframework.web.context.ContextLoader.closeWebApplicationContext(ContextLoader.java:548)
	at org.springframework.web.context.ContextLoaderListener.contextDestroyed(ContextLoaderListener.java:142)
	at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4831)
	at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5478)
	at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:160)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
	at java.util.concurrent.FutureTask.run(FutureTask.java:166)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:722)


 

 발생원인

 

ContextLoaderListener 을 Listener로 등록해두면, 웹 애플리케이션이 시작할 때 자동으로 루트 애플리케이션 컨텍스트를 만들고 초기화를 한다. 디폴트Default로 XmlWebApplicationContext를 애플리케이션 컨텍스트 클래스가 지정되고 /WEB-INF/applicationContext.xml을 탐색한다. 이때, applicationContext.xml 파일을 찾지 못하면서 발생한다.


 

 해결방법

 

1. /WEB-INF/applicationContext.xml 생성 및 설정

2. web.xml 내에  <context-param></context-param> 으로 ~Context.xml 을 지정

  

        contextConfigLocation
        /WEB-INF/spring/appServlet/applicationContext.xml


위의 두 가지 방법 중 하나를 선택해서 처리하면 된다.


  오늘 회사 동료가 알려준 방법인데, 꽤 유용할 것 같아서 이렇게 기록으로 남긴다.


  
package dreaminfra.ipams.web.assessment;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;

@Controller
@SessionAttributes({"simpleForm"})
@RequestMapping("/simple")
public class SimpleController {

    private final static String SIMPLE_FORM = "simpleForm";
    
    /**
     *   컨트롤러에서 @SessionAttribute({"simpleForm"}) 으로 선언한 simpleForm을 초기화하여
     * Session에서 유지하기 위해 반드시 구현해줘야 하는 부분이다.
     * @return
     */
    @ModelAttribute(SIMPLE_FORM)
    public SimpleForm createSimpleForm() {
        return new SimpleForm();
    }
    
    @RequestMapping(value="/request", method=RequestMethod.GET)
    public String request(Model model) {
        /**
         * Session에 SIMPLE_FORM을 생성하여 등록한다.
         */
        model.addAttribute(SIMPLE_FORM, new SimpleForm());
        
        return "/simple/response";
    }

    @RequestMapping(value="/response", method=RequestMethod.POST)
    public String response(@ModelAttribute(SIMPLE_FORM) SimpleForm form, SessionStatus status) {
        /**
         * Session 에 등록된 SimpleForm 은 SessionStatus.setComplete()을 실행하기 전까지는
         * Session에서 내부의 데이터를 유지하게 된다. SessionStatus.setComplete()을 실행하면
         * Controller에서 선언해둔 SessionAttribute에 등록된 form이 초기화된다. 
         */
        status.setComplete();
        
        return "redirect:/simple/request";
    }
    
    class SimpleForm {
        
        private String name;
        private String nickName;
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getNickName() {
            return nickName;
        }
        public void setNickName(String nickName) {
            this.nickName = nickName;
        }
    }
}


위에서 중요한 것은 Contoller 에서 선언한

SessionAttributes({"simpleForm"})

...

@ModelAttribute(SIMPLE_FORM)
    public SimpleForm createSimpleForm() {
        return new SimpleForm();
    }

...

model.addAttribute(SIMPLE_FORM, new SimpleForm());

...

session.setComplete()

부분이다.





  1. saru 2019.06.03 19:04

    와 정말 도움이 되었네요

토비의스프링3
카테고리 컴퓨터/IT > 프로그래밍/언어 > 프로그래밍일반
지은이 이일민 (에이콘출판, 2010년)
상세보기

진정한 POJO란
객체지향적인 원리에 충실하면서, 환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 오브젝트를 말한다. 그런 POJO에 애플리케이션의 핵심 로직과 기능을 담아 설계하고 개발하는 방법을 POJO 프로그래밍이라고 할 수 있다.

객체지향 프로그래밍의 기본이며 가장 궁극의 수준이라고 할 수 있겠다.
 

+ Recent posts