CloudFoundry and a "normal" WAR - How to bind to a datasource on CloudFoundry
so here's an interesting one; really want to use "cloud" and i have existing non-Spring WAR. how can we bind to a datasource in a "flexible" way that doesn't require too much coding or rebuilding as a Spring App?
1. import a package from Spring (it looks like we're adding Spring, but there's really no influence, just one class)
org.springframework.maven.milestone Spring Maven Milestone Repository http://repo.spring.io/milestone org.springframework.cloud cloudfoundry-connector 0.9.5 org.springframework.cloud spring-service-connector 0.9.5
2. provide a way to bind to a CloudFoundry datasource
package io.pivotal.poc.simple.service;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.cloud.CloudException;
import org.springframework.cloud.config.java.AbstractCloudConfig;
public class CloudConfiguration extends AbstractCloudConfig {
private static final Logger logger = Logger.getLogger(CloudConfiguration.class);
public CloudConfiguration() {
BeanFactory factory = new DefaultListableBeanFactory();
try {
this.setBeanFactory(factory);
}
catch (CloudException e) {
logger.warn("no cloud",e);//TODO clean up message
}
}
public DataSource inventoryDataSource() {
ServiceConnectionFactory connectionFactory = connectionFactory();
if (connectionFactory != null) {
return new ServiceConnectionFactory().dataSource("twitter-pgsql");//TODO clean up hard coding
}//end if
return null;
}
}
3. provide the datasource as a servlet context attribute
package io.pivotal.poc.simple.listener;
import io.pivotal.poc.simple.service.CloudConfiguration;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.log4j.Logger;
@WebListener
public class DatasourceListener implements ServletContextListener {
private static final Logger logger = Logger.getLogger(DatasourceListener.class);
private CloudConfiguration cloudConfiguration = new CloudConfiguration();
public static final String DATASOURCE_ATTRIBUTE = "dataSource";
@Override
public void contextInitialized(ServletContextEvent sce) {
if (!bindCloudDataSource(sce)) {
logger.warn("not running in the cloud");;
bindLocalDataSource(sce);
}//end if
}
@Override
public void contextDestroyed(ServletContextEvent sce) { }
//creates a "local" (in-memory) binding for testing purposes
private void bindLocalDataSource(ServletContextEvent sce) {
//create a database
BasicDataSource factory = new BasicDataSource();
factory.setDriverClassName("org.h2.Driver");//TODO - remove hardcoding
factory.setUrl("jdbc:h2:mem:a");
factory.setUsername("sa");
factory.setPassword("");
//set
sce.getServletContext().setAttribute(DATASOURCE_ATTRIBUTE, factory);
}
//runs the cloud configuration component
private boolean bindCloudDataSource(ServletContextEvent sce) {
DataSource dataSource = cloudConfiguration.inventoryDataSource();
if (dataSource != null) {
sce.getServletContext().setAttribute(DATASOURCE_ATTRIBUTE, dataSource);
return true;
}//end if
return false;
}
}
3. you're done
a couple of assumptions;
- not using a Dependency Injection container (at all)
- using servlets/etc to pull a datasource object from the servlet context
caveat; this is very crude and will be refined as it gets tested out
No comments:
Post a Comment