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,89 +38,92 @@ 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();
Map<String, BlobStoreContext<?, ?>> providerTypeToBlobStoreMap; private final Properties props = new Properties();
TwitterClient twitterClient;
String container;
@SuppressWarnings("unchecked") Map<String, BlobStoreContext<?, ?>> providerTypeToBlobStoreMap;
@PostConstruct TwitterClient twitterClient;
public void initialize() { String container;
// shared across all blobstores and used to retrieve tweets
twitterClient = TwitterContextFactory.createContext(props,
new GaeHttpCommandExecutorServiceModule()).getApi();
// common namespace for storing tweets. private boolean initializing;
container = checkNotNull(props.getProperty(PROPERTY_TWEETSTORE_CONTAINER),
PROPERTY_TWEETSTORE_CONTAINER);
ImmutableList<String> contextBuilderClassNames = ImmutableList.<String>of(
checkNotNull(props.getProperty(PROPERTY_BLOBSTORE_CONTEXTBUILDERS),
PROPERTY_BLOBSTORE_CONTEXTBUILDERS)
.split(","));
// instantiate and store references to all blobstores by provider name @SuppressWarnings("unchecked")
providerTypeToBlobStoreMap = Maps.newHashMap(); @PostConstruct
for (String className : contextBuilderClassNames) { public void initialize() {
Class<BlobStoreContextBuilder<?, ?>> builderClass; if (initializing)
Constructor<BlobStoreContextBuilder<?, ?>> constructor; return;
String name; initializing = true;
BlobStoreContext<?, ?> context; // shared across all blobstores and used to retrieve tweets
try { twitterClient = TwitterContextFactory.createContext(props,
builderClass = (Class<BlobStoreContextBuilder<?, ?>>) Class.forName(className); new GaeHttpCommandExecutorServiceModule()).getApi();
name = builderClass.getSimpleName().replaceAll("BlobStoreContextBuilder", "");
constructor = builderClass.getConstructor(Properties.class);
context = constructor.newInstance(props)
.withModules(new GaeHttpCommandExecutorServiceModule())
.buildContext();
} catch (Exception e) {
throw new RuntimeException("error instantiating " + className, e);
}
providerTypeToBlobStoreMap.put(name, context);
}
// get a queue for submitting store tweet requests // common namespace for storing tweets.
Queue queue = QueueFactory.getQueue("twitter"); container = checkNotNull(props.getProperty(PROPERTY_TWEETSTORE_CONTAINER),
// submit a job to store tweets for each configured blobstore PROPERTY_TWEETSTORE_CONTAINER);
for (String name : providerTypeToBlobStoreMap.keySet()) { ImmutableList<String> contextBuilderClassNames = ImmutableList.<String> of(checkNotNull(
queue.add(url("/store/do").header("context", name).method(Method.GET)); props.getProperty(PROPERTY_BLOBSTORE_CONTEXTBUILDERS),
} PROPERTY_BLOBSTORE_CONTEXTBUILDERS).split(","));
}
@PreDestroy // instantiate and store references to all blobstores by provider name
public void destroy() { providerTypeToBlobStoreMap = Maps.newHashMap();
for (BlobStoreContext<?, ?> context : providerTypeToBlobStoreMap.values()) { for (String className : contextBuilderClassNames) {
context.close(); Class<BlobStoreContextBuilder<?, ?>> builderClass;
} Constructor<BlobStoreContextBuilder<?, ?>> constructor;
} String name;
BlobStoreContext<?, ?> context;
try {
builderClass = (Class<BlobStoreContextBuilder<?, ?>>) Class.forName(className);
name = builderClass.getSimpleName().replaceAll("BlobStoreContextBuilder", "");
constructor = builderClass.getConstructor(Properties.class);
context = constructor.newInstance(props).withModules(
new GaeHttpCommandExecutorServiceModule()).buildContext();
} catch (Exception e) {
throw new RuntimeException("error instantiating " + className, e);
}
providerTypeToBlobStoreMap.put(name, context);
}
/* // get a queue for submitting store tweet requests
* (non-Javadoc) Queue queue = QueueFactory.getQueue("twitter");
* // submit a job to store tweets for each configured blobstore
* @see for (String name : providerTypeToBlobStoreMap.keySet()) {
* org.springframework.context.ResourceLoaderAware#setResourceLoader(org queue.add(url("/store/do").header("context", name).method(Method.GET));
* .springframework.core.io.ResourceLoader) }
*/ }
@Override
public void setResourceLoader(ResourceLoader resourceLoader) { @PreDestroy
InputStream input = null; public void destroy() {
try { for (BlobStoreContext<?, ?> context : providerTypeToBlobStoreMap.values()) {
input = resourceLoader.getResource("/WEB-INF/jclouds.properties").getInputStream(); context.close();
props.load(input); }
} catch (IOException e) { }
throw new RuntimeException(e);
} finally { /*
Closeables.closeQuietly(input); * (non-Javadoc)
} *
} * @see org.springframework.context.ResourceLoaderAware#setResourceLoader(org
* .springframework.core.io.ResourceLoader)
*/
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
InputStream input = null;
try {
input = resourceLoader.getResource("/WEB-INF/jclouds.properties").getInputStream();
props.load(input);
if (!initializing)
initialize();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
Closeables.closeQuietly(input);
}
}
} }

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,74 +36,54 @@ 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
public StoreTweetsController storeTweetsController() {
StoreTweetsController controller = new StoreTweetsController(appConfig.providerTypeToBlobStoreMap,
appConfig.container, appConfig.twitterClient);
injectServletConfig(controller);
return controller;
}
@Bean @Bean
public AddTweetsController addTweetsController() { public StoreTweetsController storeTweetsController(SpringAppConfig appConfig) {
AddTweetsController controller = new AddTweetsController(appConfig.providerTypeToBlobStoreMap, return new StoreTweetsController(checkNotNull(appConfig.providerTypeToBlobStoreMap,
serviceToStoredTweetStatuses()); "contexts"), checkNotNull(appConfig.container, "container"), checkNotNull(
injectServletConfig(controller); appConfig.twitterClient, "twitterClient"));
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() { public AddTweetsController addTweetsController(SpringAppConfig appConfig) {
return new ServiceToStoredTweetStatuses(appConfig.providerTypeToBlobStoreMap, return new AddTweetsController(
appConfig.container); checkNotNull(appConfig.providerTypeToBlobStoreMap, "contexts"),
} serviceToStoredTweetStatuses(appConfig));
}
@Bean
public HandlerMapping handlerMapping() {
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
Map<String, Object> urlMap = Maps.newHashMapWithExpectedSize(2);
urlMap.put("/store/*", storeTweetsController());
urlMap.put("/tweets/*", addTweetsController());
mapping.setUrlMap(urlMap);
/*
* "/store" and "/tweets" are part of the servlet mapping and thus stripped
* by the mapping if using default settings.
*/
mapping.setAlwaysUseFullPath(true);
return mapping;
}
@Bean
public HandlerAdapter servletHandlerAdapter() {
return new SimpleServletHandlerAdapter();
}
/* (non-Javadoc) @Bean
* @see org.springframework.web.context.ServletConfigAware#setServletConfig(javax.servlet.ServletConfig) ServiceToStoredTweetStatuses serviceToStoredTweetStatuses(SpringAppConfig appConfig) {
*/ return new ServiceToStoredTweetStatuses(checkNotNull(appConfig.providerTypeToBlobStoreMap,
@Override "contexts"), checkNotNull(appConfig.container, "container"));
public void setServletConfig(ServletConfig servletConfig) { }
this.servletConfig = servletConfig;
} @Bean
public HandlerMapping handlerMapping(AddTweetsController add, StoreTweetsController store,
WebApplicationContext context) {
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setServletContext(context.getServletContext());
Map<String, Object> urlMap = Maps.newHashMapWithExpectedSize(2);
urlMap.put("/store/*", checkNotNull(store, "store"));
add.setServletContext(checkNotNull(context.getServletContext(), "servletContext"));
urlMap.put("/tweets/*", checkNotNull(add, "add"));
mapping.setUrlMap(urlMap);
/*
* "/store" and "/tweets" are part of the servlet mapping and thus stripped by the mapping if
* using default settings.
*/
mapping.setAlwaysUseFullPath(true);
return mapping;
}
@Bean
public HandlerAdapter servletHandlerAdapter() {
return new SimpleServletHandlerAdapter();
}
} }

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();
} }
} }