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