mirror of https://github.com/apache/jclouds.git
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:
parent
69b247cbf4
commit
3087cce540
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue