Tomcat 7.0.34、Spring 3.2.3、Spring Security 3.2.0.RC1、および Spring Social 1.1 に Web アプリケーションがあります。
何らかの理由で、Spring コンテキストが 2 回読み込まれています。2 番目のロードは、最初のロードが終了した直後に発生しています。以下のログは、Context Loader がルート WebApplicationContext をロードしていることを示しています。すべてが正常に進行し、すべての RequstMappingHandlers が正しく登録されています。その後すぐに、コンテキストが再び更新されます。
Context Loader と DispatcherServlet の一部として同時に構成をロードしないようにすることについて、SO でいくつかのソリューションを読み、これのさまざまな組み合わせをテストしましたが、それは修正されていないようです。 mもコードブラインドになります。
これに関する私のすべてのテストでは、コンテナとSpringコンポーネントの両方のアノテーションのみの構成に私を駆り立てましたが、構成クラスはgithubのSpring Socialの例からほとんどコピーして貼り付けています. 以下に SocialConfig.java の詳細を含めましたが、この問題は Spring Social を実装する前から発生していましたが、修正しないと先に進むことができません。
また、問題はハイブリッド xml (web.xml、security-app-context.xml) と注釈構成にも存在していました。
web.xml ではなく、WebApplicationInitializer を実装しています
public class WebClientInitialiser implements WebApplicationInitializer {
public void onStartup(ServletContext container) throws ServletException {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
// Manage the lifecycle of the root application context
appContext.setConfigLocation("com.mycompany.webclient.config");
appContext.setServletContext(container);
container.addListener(new ContextLoaderListener(appContext));
container.addListener(new MyCompanyContextListener());
container.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain"))
.addMappingForUrlPatterns(null, false, "/*");
// Register and map the dispatcher servlet
Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(appContext));
dispatcher.addMapping("/");
dispatcher.setLoadOnStartup(1);
}
}
私の MainConfig.java
/**
* Main configuration class for the application.
* Turns on @Component scanning, loads externalized application properties
* and imports legacy security configuration
*/
@Configuration
@ComponentScan(basePackages = "com.mycompany.webclient", excludeFilters = { @Filter(Configuration.class) })
@PropertySource("classpath:wc.properties")
@ImportResource("/WEB-INF/spring/appServlet/security-app-context.xml")
public class MainConfig {
@Bean
public PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
私の WebMvcConfig.java
@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("/WEB-INF/messages/messages");
return messageSource;
}
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
マイ SocialConfig.java
@Configuration
@EnableSocial
public class SocialConfig implements SocialConfigurer {
private SocialUserDAO socialUserDao;
//
// SocialConfigurer implementation methods
//
@Override
public void addConnectionFactories(ConnectionFactoryConfigurer cfConfig, Environment env) {
String clientId="XXXXXX";
String clientSecret="XXXXX";
cfConfig.addConnectionFactory(new FacebookConnectionFactory(clientId, clientSecret));
}
@Override
public UserIdSource getUserIdSource() {
return new UserIdSource() {
@Override
public String getUserId() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
throw new IllegalStateException("Unable to get a ConnectionRepository: no user signed in");
}
return authentication.getName();
}
};
}
@Override
public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
return new HibernateUsersConnectionRepository(socialUserDao, connectionFactoryLocator, Encryptors.noOpText());
}
//
// API Binding Beans
//
@Bean
@Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
public Facebook facebook(ConnectionRepository repository) {
Connection<Facebook> connection = repository.findPrimaryConnection(Facebook.class);
return connection != null ? connection.getApi() : null;
}
@Bean
@Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
public Twitter twitter(ConnectionRepository repository) {
Connection<Twitter> connection = repository.findPrimaryConnection(Twitter.class);
return connection != null ? connection.getApi() : null;
}
@Bean
@Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
public LinkedIn linkedin(ConnectionRepository repository) {
Connection<LinkedIn> connection = repository.findPrimaryConnection(LinkedIn.class);
return connection != null ? connection.getApi() : null;
}
//
// Web Controller and Filter Beans
//
@Bean
public ConnectController connectController(ConnectionFactoryLocator connectionFactoryLocator, ConnectionRepository connectionRepository) {
ConnectController connectController = new ConnectController(connectionFactoryLocator, connectionRepository);
connectController.addInterceptor(new PostToWallAfterConnectInterceptor());
connectController.addInterceptor(new TweetAfterConnectInterceptor());
return connectController;
}
@Bean
public ProviderSignInController providerSignInController(ConnectionFactoryLocator connectionFactoryLocator, UsersConnectionRepository usersConnectionRepository) {
return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new SimpleSignInAdapter(new HttpSessionRequestCache()));
}
@Bean
public DisconnectController disconnectController(UsersConnectionRepository usersConnectionRepository, Environment env) {
return new DisconnectController(usersConnectionRepository, env.getProperty("facebook.clientSecret"));
}
@Bean
public ReconnectFilter apiExceptionHandler(UsersConnectionRepository usersConnectionRepository, UserIdSource userIdSource) {
return new ReconnectFilter(usersConnectionRepository, userIdSource);
}
}
ヘルプ、コメント、ポインタは大歓迎です。
このログ出力は、各コンテキスト リフレッシュの開始時に 2 回繰り返されます。
org.springframework.web.context.ContextLoader- Root WebApplicationContext: initialization started
org.springframework.web.context.support.AnnotationConfigWebApplicationContext- Refreshing Root WebApplicationContext: startup date [Mon Nov 25 22:43:39 GMT 2013]; root of context hierarchy
org.springframework.context.annotation.ClassPathBeanDefinitionScanner- JSR-330 'javax.inject.Named' annotation found and supported for component scanning
org.springframework.web.context.support.AnnotationConfigWebApplicationContext- Registering annotated classes: [class com.mycompany.webclient.config.WebMvcConfig,class com.mycompany.webclient.config.SocialConfig]