Issue 89: fixed npe in google appengine live

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2592 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2010-01-04 04:25:34 +00:00
parent 69b247cbf4
commit 3087cce540
3 changed files with 148 additions and 150 deletions

View File

@ -13,6 +13,7 @@ import java.util.Properties;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import javax.inject.Singleton;
import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.BlobStoreContextBuilder;
@ -37,14 +38,13 @@ import com.google.common.io.Closeables;
* @see SpringServletConfig * @see SpringServletConfig
*/ */
@Configuration @Configuration
@Singleton
public class SpringAppConfig implements ResourceLoaderAware { public class SpringAppConfig implements ResourceLoaderAware {
/* /*
* The call to TwitterContextFactory.createContext in initialize() * The call to TwitterContextFactory.createContext in initialize() must be carried out before the
* must be carried out before the servlet context loads, otherwise the * servlet context loads, otherwise the GAE will throw an access exception. For this reason, this
* GAE will throw an access exception. * code cannot be in the default servlet context loaded by the DispatcherServlet, but is executed
* For this reason, this code cannot be in the default servlet context * in the root application context (which is processed by a listener).
* loaded by the DispatcherServlet, but is executed in the root application
* context (which is processed by a listener).
*/ */
private final Properties props = new Properties(); private final Properties props = new Properties();
@ -53,9 +53,14 @@ public class SpringAppConfig implements ResourceLoaderAware {
TwitterClient twitterClient; TwitterClient twitterClient;
String container; String container;
private boolean initializing;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@PostConstruct @PostConstruct
public void initialize() { public void initialize() {
if (initializing)
return;
initializing = true;
// shared across all blobstores and used to retrieve tweets // shared across all blobstores and used to retrieve tweets
twitterClient = TwitterContextFactory.createContext(props, twitterClient = TwitterContextFactory.createContext(props,
new GaeHttpCommandExecutorServiceModule()).getApi(); new GaeHttpCommandExecutorServiceModule()).getApi();
@ -63,10 +68,9 @@ public class SpringAppConfig implements ResourceLoaderAware {
// common namespace for storing tweets. // common namespace for storing tweets.
container = checkNotNull(props.getProperty(PROPERTY_TWEETSTORE_CONTAINER), container = checkNotNull(props.getProperty(PROPERTY_TWEETSTORE_CONTAINER),
PROPERTY_TWEETSTORE_CONTAINER); PROPERTY_TWEETSTORE_CONTAINER);
ImmutableList<String> contextBuilderClassNames = ImmutableList.<String>of( ImmutableList<String> contextBuilderClassNames = ImmutableList.<String> of(checkNotNull(
checkNotNull(props.getProperty(PROPERTY_BLOBSTORE_CONTEXTBUILDERS), props.getProperty(PROPERTY_BLOBSTORE_CONTEXTBUILDERS),
PROPERTY_BLOBSTORE_CONTEXTBUILDERS) PROPERTY_BLOBSTORE_CONTEXTBUILDERS).split(","));
.split(","));
// instantiate and store references to all blobstores by provider name // instantiate and store references to all blobstores by provider name
providerTypeToBlobStoreMap = Maps.newHashMap(); providerTypeToBlobStoreMap = Maps.newHashMap();
@ -79,9 +83,8 @@ public class SpringAppConfig implements ResourceLoaderAware {
builderClass = (Class<BlobStoreContextBuilder<?, ?>>) Class.forName(className); builderClass = (Class<BlobStoreContextBuilder<?, ?>>) Class.forName(className);
name = builderClass.getSimpleName().replaceAll("BlobStoreContextBuilder", ""); name = builderClass.getSimpleName().replaceAll("BlobStoreContextBuilder", "");
constructor = builderClass.getConstructor(Properties.class); constructor = builderClass.getConstructor(Properties.class);
context = constructor.newInstance(props) context = constructor.newInstance(props).withModules(
.withModules(new GaeHttpCommandExecutorServiceModule()) new GaeHttpCommandExecutorServiceModule()).buildContext();
.buildContext();
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("error instantiating " + className, e); throw new RuntimeException("error instantiating " + className, e);
} }
@ -106,8 +109,7 @@ public class SpringAppConfig implements ResourceLoaderAware {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see * @see org.springframework.context.ResourceLoaderAware#setResourceLoader(org
* org.springframework.context.ResourceLoaderAware#setResourceLoader(org
* .springframework.core.io.ResourceLoader) * .springframework.core.io.ResourceLoader)
*/ */
@Override @Override
@ -116,6 +118,8 @@ public class SpringAppConfig implements ResourceLoaderAware {
try { try {
input = resourceLoader.getResource("/WEB-INF/jclouds.properties").getInputStream(); input = resourceLoader.getResource("/WEB-INF/jclouds.properties").getInputStream();
props.load(input); props.load(input);
if (!initializing)
initialize();
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} finally { } finally {

View File

@ -1,21 +1,33 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.demo.tweetstore.config; package org.jclouds.demo.tweetstore.config;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map; import java.util.Map;
import javax.inject.Inject;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import org.jclouds.demo.tweetstore.controller.AddTweetsController; import org.jclouds.demo.tweetstore.controller.AddTweetsController;
import org.jclouds.demo.tweetstore.controller.StoreTweetsController; import org.jclouds.demo.tweetstore.controller.StoreTweetsController;
import org.jclouds.demo.tweetstore.functions.ServiceToStoredTweetStatuses; import org.jclouds.demo.tweetstore.functions.ServiceToStoredTweetStatuses;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.ServletConfigAware; import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.SimpleServletHandlerAdapter; import org.springframework.web.servlet.handler.SimpleServletHandlerAdapter;
@ -24,59 +36,46 @@ import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
/** /**
* Creates servlets (using resources from the {@link SpringAppConfig}) and mappings. * Creates servlets,(using resources from the {@link SpringAppConfig}) and mappings.
* *
* @author Andrew Phillips * @author Andrew Phillips
* @see SpringAppConfig
*/ */
@Configuration @Configuration
public class SpringServletConfig implements ServletConfigAware { public class SpringServletConfig {
private ServletConfig servletConfig;
@Inject
private SpringAppConfig appConfig;
@Bean @Bean
public StoreTweetsController storeTweetsController() { public StoreTweetsController storeTweetsController(SpringAppConfig appConfig) {
StoreTweetsController controller = new StoreTweetsController(appConfig.providerTypeToBlobStoreMap, return new StoreTweetsController(checkNotNull(appConfig.providerTypeToBlobStoreMap,
appConfig.container, appConfig.twitterClient); "contexts"), checkNotNull(appConfig.container, "container"), checkNotNull(
injectServletConfig(controller); appConfig.twitterClient, "twitterClient"));
return controller;
} }
@Bean @Bean
public AddTweetsController addTweetsController() { public AddTweetsController addTweetsController(SpringAppConfig appConfig) {
AddTweetsController controller = new AddTweetsController(appConfig.providerTypeToBlobStoreMap, return new AddTweetsController(
serviceToStoredTweetStatuses()); checkNotNull(appConfig.providerTypeToBlobStoreMap, "contexts"),
injectServletConfig(controller); serviceToStoredTweetStatuses(appConfig));
return controller;
}
private void injectServletConfig(Servlet servlet) {
checkNotNull(servletConfig);
try {
servlet.init(servletConfig);
} catch (ServletException exception) {
throw new BeanCreationException("Unable to instantiate " + servlet, exception);
}
} }
@Bean @Bean
ServiceToStoredTweetStatuses serviceToStoredTweetStatuses() { ServiceToStoredTweetStatuses serviceToStoredTweetStatuses(SpringAppConfig appConfig) {
return new ServiceToStoredTweetStatuses(appConfig.providerTypeToBlobStoreMap, return new ServiceToStoredTweetStatuses(checkNotNull(appConfig.providerTypeToBlobStoreMap,
appConfig.container); "contexts"), checkNotNull(appConfig.container, "container"));
} }
@Bean @Bean
public HandlerMapping handlerMapping() { public HandlerMapping handlerMapping(AddTweetsController add, StoreTweetsController store,
WebApplicationContext context) {
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping(); SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setServletContext(context.getServletContext());
Map<String, Object> urlMap = Maps.newHashMapWithExpectedSize(2); Map<String, Object> urlMap = Maps.newHashMapWithExpectedSize(2);
urlMap.put("/store/*", storeTweetsController()); urlMap.put("/store/*", checkNotNull(store, "store"));
urlMap.put("/tweets/*", addTweetsController()); add.setServletContext(checkNotNull(context.getServletContext(), "servletContext"));
urlMap.put("/tweets/*", checkNotNull(add, "add"));
mapping.setUrlMap(urlMap); mapping.setUrlMap(urlMap);
/* /*
* "/store" and "/tweets" are part of the servlet mapping and thus stripped * "/store" and "/tweets" are part of the servlet mapping and thus stripped by the mapping if
* by the mapping if using default settings. * using default settings.
*/ */
mapping.setAlwaysUseFullPath(true); mapping.setAlwaysUseFullPath(true);
return mapping; return mapping;
@ -86,12 +85,5 @@ public class SpringServletConfig implements ServletConfigAware {
public HandlerAdapter servletHandlerAdapter() { public HandlerAdapter servletHandlerAdapter() {
return new SimpleServletHandlerAdapter(); return new SimpleServletHandlerAdapter();
} }
}
/* (non-Javadoc)
* @see org.springframework.web.context.ServletConfigAware#setServletConfig(javax.servlet.ServletConfig)
*/
@Override
public void setServletConfig(ServletConfig servletConfig) {
this.servletConfig = servletConfig;
}
}

View File

@ -69,8 +69,9 @@ public class AddTweetsController extends HttpServlet implements
@Inject @Inject
public AddTweetsController(Map<String, BlobStoreContext<?, ?>> contexts, public AddTweetsController(Map<String, BlobStoreContext<?, ?>> contexts,
ServiceToStoredTweetStatuses blobStoreContextToContainerResult) { ServiceToStoredTweetStatuses blobStoreContextToContainerResult) {
this.contexts = contexts; this.contexts = checkNotNull(contexts, "contexts");
this.blobStoreContextToContainerResult = blobStoreContextToContainerResult; this.blobStoreContextToContainerResult = checkNotNull(blobStoreContextToContainerResult,
"blobStoreContextToContainerResult");
} }
@Override @Override
@ -100,6 +101,7 @@ public class AddTweetsController extends HttpServlet implements
return statuses; return statuses;
} }
@Inject
@Override @Override
public void setServletContext(ServletContext context) { public void setServletContext(ServletContext context) {
this.servletContext = context; this.servletContext = context;
@ -107,6 +109,6 @@ public class AddTweetsController extends HttpServlet implements
@Override @Override
public ServletContext getServletContext() { public ServletContext getServletContext() {
return checkNotNull(servletContext, "servletContext"); return (servletContext != null) ? servletContext : super.getServletContext();
} }
} }