2016-08-11 4 views
0

저는 Spring을 처음 접했을 때 이미 기본 구성에 매우 이상한 문제가 있습니다.SpringRest (MVC + Security) Java 구성 : "이미 루트 응용 프로그램 컨텍스트가 있기 때문에 컨텍스트를 초기화 할 수 없습니다."

에 의해 발생 : java.lang.IllegalStateException : 이미 루트 애플리케이션 컨텍스트 존재가 있기 때문에 문맥을 초기화 할 수 없습니다 - 당신은 당신의 web.xml에 * 정의 여러 ContextLoader를가 있는지 여부를 확인! org.springframework.web.context.ContextLoaderListener.contextInitialized에서 org.springframework.web.context.ContextLoader.initWebApplicationContext (ContextLoader.java:297) (ContextLoaderListener.java:107) io.undertow.servlet.core에서 에서 . io.undertow.servlet.core.DeploymentManagerImpl.deploy에서 ApplicationListeners.contextInitialized (ApplicationListeners.java:173) 나는 두 개의 서로 다른 REST 서블릿을 필요로 7 개

(DeploymentManagerImpl.java:194) ... 하나 내부 호출 (서버에 대한보기) 및 외부 API 용. 또한 두 서블릿에서 일부 서비스를 공유하기를 원하기 때문에 SpringRootConfiguration을 사용하여 두 개의 인터셉터와 하나의 서비스가 포함 된 패키지를 검사했습니다.

모든 구성은 web.xml

web.xml을

<context-param> 
    <param-name>contextClass</param-name> 
    <param-value> 
     org.springframework.web.context.support.AnnotationConfigWebApplicationContext 
    </param-value> 
</context-param> 

<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 

SpringRestExternalAppInitializer

@Override 
protected Class<?>[] getRootConfigClasses() { 
    return new Class[]{SpringRootConfiguration.class}; 
} 

@Override 
protected Class<?>[] getServletConfigClasses() { 
    return new Class[]{SpringRestExternalConfiguration.class}; 
} 

@Override 
protected String[] getServletMappings() { 
    return new String[]{"/api/*"}; 
} 

@Override 
protected String getServletName() { 
    return "restexternal"; 
} 

SpringRootConfiguration 단지 컨텍스트와 청취자와 함께 자바에서 이루어집니다

@ComponentScan({"be.xperthis.common"}) 
@Configuration 
public class SpringRootConfiguration { 

} 

SpringRestExternalConfiguration

@ComponentScan("com.polymedis.result.web.api") 
@Configuration 
public class SpringRestExternalConfiguration extends WebMvcConfigurationSupport { 

@Autowired 
private NoCacheHandler noCacheHandler; 

@Autowired 
private RestMetricHandler restMetrics; 

@Override 
public void addInterceptors(final InterceptorRegistry registry) { 
    registry.addInterceptor(noCacheHandler); 
    registry.addInterceptor(restMetrics); 
} 

@Override 
public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) { 
    configurer.enable(); 
} 

@Override 
public void configureMessageConverters(final List<HttpMessageConverter<?>> converters) { 
    .... 
} 

@Override 
public RequestMappingHandlerMapping createRequestMappingHandlerMapping() { 
    return new ApiVersionRequestMappingHandlerMapping(); //used to check a custom annotation on every RestController methods 
} 
} 

이론적으로, 두 번째 나머지 구성 (내부)을가한다,하지만 난 그것을 제거 지금 ... 예외를 이해하려고 노력하면서

참고 : Spring 보안 튜토리얼에 따라 getRootConfigClasses() {...}에 SpringSecurityConfiguration을 넣는 동안 동일한 오류가 발생했습니다.

web.xml에서 삭제하거나 추가해야합니까? Wildfly 8을 사용하고 있으며 Wildfly의 버그에 대한 해결 방법을 이미 찾아야했습니다. 스프링 라이브러리 (jar)가 WEB-Inf/lib 폴더에 추가되지 않은 경우 스프링 구성이 선택되지 않습니다.

+1

문제가 있습니다.xml과'SpringRestExternalAppInitializer' (아마도'AbstractAnnotationConfigDispatcherServletInitializer'를 확장합니다). 실제로는 거의 동일합니다. web.xml은 XML 변형이며,'AbstractAnnotationConfigDispatcherServletInitializer'를 확장하면 Java에서 같은 작업을 수행 할 수 있습니다. 따라서 web.xml 또는 Java 클래스를 그대로 두어야합니다. 이 질문에 대한 답변을 확인하십시오 - 도움이 될 수도 있습니다. http://stackoverflow.com/questions/26676782/when-use-abstractannotationconfigdispatcherservlet 초기화 및 웹 응용 프로그램 – lenach87

+0

web.xml 부분을 제거하면 첫 번째 문제가 해결되었습니다. 하지만 이제는 내부 REST 호출을위한 두 번째 서블릿을 추가하려고합니다. 두 개의 AbstractAnnotationConfigDispatcherServletInitializer를 만들면 같은 오류가 발생합니다 ... – ALansmanne

+0

두 클래스를 추가하면 곧바로 작동하지 않아야합니다. 이 답변을 확인하면 더 많은 정보를 얻을 수있는 일반적인 이해와 방법을 얻는 데 도움이 될 것입니다. http://stackoverflow.com/questions/12059307/multiple-application-context-multiple-dispatcher-servlets – lenach87

답변

0

자, 해결책을 찾았습니다. AbstractAnnotationConfigDispatcherServletInitializer를 두 번 겹쳐 쓰는 대신 WebApplicationInitializer를 구현하는 단일 클래스를 사용하고 있으며이 클래스에 두 개의 서블릿을 빌드합니다.

public class SpringAppInitializer implements WebApplicationInitializer { 

@Override 
public void onStartup(final ServletContext servletContext) throws ServletException { 
    final AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); 
    rootContext.register(SpringRootConfiguration.class, SpringSecurityConfig.class); 
    servletContext.addListener(new ContextLoaderListener(rootContext)); 

    // Internal REST 
    buildInternalRestContext(servletContext, rootContext); 

    // External REST 
    buildExternalRestContext(servletContext, rootContext); 

    ... 
} 

public void buildExternalRestContext(final ServletContext servletContext, final AnnotationConfigWebApplicationContext rootContext) { 
    final AnnotationConfigWebApplicationContext externalRestContext = new AnnotationConfigWebApplicationContext(); 
    externalRestContext.setParent(rootContext); 
    externalRestContext.register(SpringRestExternalConfiguration.class); 

    final ServletRegistration.Dynamic externalRestServlet = servletContext.addServlet("externalrest", new DispatcherServlet(externalRestContext)); 
    externalRestServlet.addMapping("/api/*"); 
} 

public void buildInternalRestContext(final ServletContext servletContext, final AnnotationConfigWebApplicationContext rootContext) { 
    final AnnotationConfigWebApplicationContext internalRestContext = new AnnotationConfigWebApplicationContext(); 
    internalRestContext.setParent(rootContext); 
    internalRestContext.register(SpringRestConfiguration.class); 

    final ServletRegistration.Dynamic restDispatcherServlet = servletContext.addServlet("rest", new DispatcherServlet(internalRestContext)); 
    restDispatcherServlet.addMapping("/rest/*"); 
} 

}

지금 SpringSecurity을 설정하는 것입니다,하지만 그건 다른 주제 : 당신은 모두 웹을 가지고 있기 때문에