Spring and Cloud Foundry: a Marriage Made in Heaven

Josh Long, Spring Developer Advocate
SpringSource, a division of VMware

Twitter: @starbuxman
Email: josh.long@springsource.com
About Josh Long

Spring Developer Advocate
twitter: @starbuxman
josh.long@springsource.com




                             NOT CONFIDENTIAL -- TELL EVERYONE   2
VMware is the Customer Proven Market Leader

 Company Overview
    • $3.77 billion in 2011 revenues
    • >$4.5 billion in cash and equivalents
    • 30%+ operating margins
    • 11,000 + employees worldwide
    • 5th largest infrastructure software
     company in the world
 Proven in the Trenches
    • 300,000+ VMware customers
    • 100% of Fortune 100
    • 100% of Fortune Global 100
    • 99% of Fortune 1000
    • 97% of Fortune Global 500




                                              Confidential
3
Spring Makes Building Applications Easy...




                          NOT CONFIDENTIAL -- TELL EVERYONE   4
Tell Spring About Your Objects




package org.springsource.examples.spring31.services;... @Configuration
@ComponentScan(“the.package.with.beans.in.it”)public class ServicesConfiguratio
{
...

}
}
}




                                                                          5
Tell Spring About Your Objects




public class Main {
  static public void main (String [] args) throws Throwable {
      ApplicationContext ac = new AnnotationConfigApplicationContext(
          org.springsource.examples.spring31.services.ServicesConfiguration.class);
      ...
  }
}




                                                                                6
Tell Spring About Your Objects
 package the.package.with.beans.in.it;

 @Service
 public class CustomerService {

     public Customer createCustomer(String firstName,
                                   String lastName,
                                   Date signupDate) {

     }

     ...

 }




                                                        7
I want Database Access ...




package org.springsource.examples.spring31.services;... @Configurationpublic class
ServicesConfiguration {
   @Bean public DataSource dataSource() throws Exception
{    SimpleDriverDataSource simpleDriverDataSource =
     new SimpleDriverDataSource();      ....  return simpleDriverDataSource; }
}
}
}




                                                                               8
I want Database Access ... with Hibernate 4 Support




package org.springsource.examples.spring31.services;... @Configurationpublic class
ServicesConfiguration { ... @Bean public SessionFactory sessionFactory() throw
Exception {       Properties props = new Properties();
     // ... show_sql, dialect, etc. return new LocalSessionFactoryBuilder( dataSourc
 .addAnnotatedClasses(Customer.class)            .addProperties(props)
.buildSessionFactory(); }
}
}
}




                                                                              9
I want Database Access ... with Hibernate 4 Support
 package the.package.with.beans.in.it;
 ...
 @Service
 public class CustomerService {

     @Inject
     private SessionFactory sessionFactory;

     public Customer createCustomer(String firstName,
                                   String lastName,
                                   Date signupDate) {
       Customer customer = new Customer();
       customer.setFirstName(firstName);
       customer.setLastName(lastName);
       customer.setSignupDate(signupDate);

           sessionFactory.getCurrentSession().save(customer);
           return customer;
     }

     ...

 }                                                              10
I want Declarative Transaction Management...




package org.springsource.examples.spring31.services;... @Configuration
@EnableTransactionManagementpublic class ServicesConfiguration {
  ...
  @Bean public PlatformTransactionManager transactionManager() throws Exc
{     return new HibernateTransactionManager(this.sessionFactory()); }
}
}
}
}




                                                                     11
I want Declarative Transaction Management...
 package the.package.with.beans.in.it;
 ...
 @Service
 public class CustomerService {

     @Inject
     private SessionFactory sessionFactory;

     @Transactional
     public Customer createCustomer(String firstName,
                                   String lastName,
                                   Date signupDate) {
       Customer customer = new Customer();
       customer.setFirstName(firstName);
       customer.setLastName(lastName);
       customer.setSignupDate(signupDate);

           sessionFactory.getCurrentSession().save(customer);
           return customer;
     }
     ...
 }
                                                                12
I want Declarative Cache Management...




package org.springsource.examples.spring31.services;... @Configuration
@EnableTransactionManagement
@EnableCachingpublic class ServicesConfiguration {
  ...
   @Bean public CacheManager cacheManager() {            SimpleCacheManager scm =
SimpleCacheManager();      Cache cache = new ConcurrentMapCache("customers");
scm.setCaches(Arrays.asList(cache));    return scm; }}
      SimpleCacheManager scm = new SimpleCacheManager();        Cache cache = new
ConcurrentMapCache("customers");      scm.setCaches(Arrays.asList(cache));      ret
      SimpleCacheManager scm = new SimpleCacheManager();        Cache cache = new
ConcurrentMapCache("customers");      scm.setCaches(Arrays.asList(cache));      ret
      SimpleCacheManager scm = new SimpleCacheManager();        Cache cache = new
ConcurrentMapCache("customers");      scm.setCaches(Arrays.asList(cache));      ret




                                                                              13
I want Declarative Cache Management...
 package the.package.with.beans.in.it;
 ...
 @Service
 public class CustomerService {

     @Inject
     private SessionFactory sessionFactory;

     @Transactional
     @Cacheable(“customers”)
     public Customer createCustomer(String firstName,
                                   String lastName,
                                   Date signupDate) {
       Customer customer = new Customer();
       customer.setFirstName(firstName);
       customer.setLastName(lastName);
       customer.setSignupDate(signupDate);

         sessionFactory.getCurrentSession().save(customer);
         return customer;
     }
 }
                                                              14
I want a RESTful Endpoint...
 package org.springsource.examples.spring31.web;..
 @Controllerpublic class CustomerController { @Inject private CustomerService
 customerService; @RequestMapping(value = "/customer/{id}",
                     produces = MediaType.APPLICATION_JSON_VALUE) public
 @ResponseBody Customer customerById(@PathVariable("id") Integer id) {   return
 customerService.getCustomerById(id); } ...
 }
 }
 }




                                                                          15
Cloud Foundry: Choice of Runtimes




                                    16
Frameworks and Runtimes Supported

 • Out of the Box
  • Java (.WAR files, on Tomcat. Spring’s an ideal choice here, of course..)
  • Scala (Lift, Play!)
  • Ruby (Rails, Sinatra, etc.)
  • Node.js
 • Ecosystem Partners
  • .NET (Uhuru, Tier3)
    • both from Seattle-native partners!
    • Runs standard .NET (no need to port your application)
  • Python (Stackato)
  • PHP (AppFog)
   • Haskell (1)
1) http://www.cakesolutions.net/teamblogs/2011/11/25/haskell-happstack-on-cloudfoundry/
   • Erlang (2)
2) https://github.com/cloudfoundry/vcap/pull/20




                                                                                          17
Deploying an Application




          CLI   Application name       Dir containing application (or, .WAR for Java)




        $ vmc push cf1 --path target 
              --url cer-cf1.cloudfoundry.com




                                   Application URL




                                                                                        18
Deploying an Application

 $ vmc push cf1 --path target 
       --url cer-cf1.cloudfoundry.com
 Detected a Java Web Application, is this correct?
    [Yn]:

 Memory Reservation [Default:512M] (64M, 128M, 256M,
    512M, 1G or 2G)
 Creating Application: OK
 Would you like to bind any services to 'cf1'? [yN]:

 Uploading Application:
   Checking for available resources: OK
   Packing application: OK
   Uploading (2K): OK
 Push Status: OK
 Starting Application: OK
                                                       19
Deploying an Application (with a Manifest)

 $ vmc push
 Would you like to deploy from the current directory?
    [Yn]: y
 Pushing application 'html5expenses'...
 Creating Application: OK
 Creating Service [expenses-mongo]: OK
 Binding Service [expenses-mongo]: OK
 Creating Service [expenses-postgresql]: OK
 Binding Service [expenses-postgresql]: OK
 Uploading Application:
   Checking for available resources: OK
   Processing resources: OK
   Packing application: OK
   Uploading (6K): OK
 Push Status: OK
 Staging Application 'html5expenses': OK             20
Deploying an Application (with a manifest.yml)

 ---
 applications:
   target:
       name: html5expenses
       url: ${name}.${target-base}
       framework:
        name: spring
        info:
          mem: 512M
          description: Java SpringSource Spring Application
          exec:
       mem: 512M
       instances: 1
       services:
        expenses-mongo:
          type: :mongodb
        expenses-postgresql:
          type: :postgresql




                                                              21
Flexible Application Topologies



                                        system load balancer




                     elastic pool


         redis                                                       mysql
                            front_end                   front_end




                                             rabbitMQ




                     elastic pool


                                                                    mongodb
                                         back_end




                                                                                   10
                                                                              22
Deployment with STS




                              QuickTimeª and a
                            H.264 decompressor
                      are needed to see this picture.




                                                        23
Cloud Foundry: Choice of Clouds




                                  24
Main Risk: Lock In




                     Welcome to the hotel californiaSuch a lovely
                     placeSuch a lovely facePlenty of room at the hotel
                     californiaAny time of year, you can find it here

                     Last thing I remember, I wasRunning for the doorI
                     had to find the passage backTo the place I was
                     before’relax,’ said the night man,We are
                     programmed to receive.You can checkout
                     any time you like,But you can never
                     leave!




                                 -the Eagles




                                                                          25
Open Source Advantage




26
Open Source Advantage




27
Cloud Foundry: Clouds


               AppFog.com
               • community lead for PHP
               • PaaS for PHP


               Joyent
               • community lead for Node.js



               ActiveState
               • community lead for Python, Perl
               • Providers of Stackato private PaaS




                                                      28
Cloud Foundry.org
      Foundry Community




                          29
Micro Cloud Foundry (beta)
Micro Cloud Foundry
Cloud Foundry: Services




                          31
Cloud Foundry: Services

 Services are one of the extensibility planes in Cloud Foundry
 • there are more services being contributed by the community daily!


 MySQL, Redis, MongoDB, RabbitMQ, PostgreSQL


 Services may be shared across applications


 Cloud Foundry abstracts the provisioning aspect of services through a
 uniform API hosted in the cloud controller


 It’s very easy to take an app and add a service to the app in a uniform way
 • Cassandra? COBOL / CICS, Oracle




                                                                                32
Cloud Foundry: Services

  $ vmc create-service mysql --name mysql1
  Creating Service: OK

  $ vmc services
  ============== System Services ==============
  +------------+---------+---------------------------------------+
  | Service    | Version | Description                           |
  +------------+---------+---------------------------------------+
  | mongodb    | 1.8     | MongoDB NoSQL store                   |
  | mysql      | 5.1     | MySQL database service                |
  | postgresql | 9.0     | PostgreSQL database service (vFabric) |
  | rabbitmq   | 2.4     | RabbitMQ messaging service            |
  | redis      | 2.2     | Redis key-value store service         |
  +------------+---------+---------------------------------------+

  =========== Provisioned Services ============

  +-------------+---------+
  | Name        | Service |
  +-------------+---------+
  | mysql1      | mysql   |
  +-------------+---------+



                                                                     33
the Original “Cloud Messaging” Solution




                                          34
Cloud Foundry: Services Creation and Binding



$VCAP_SERVICES: {"redis-2.2":
[{"name":"redis_sample","label":"redis-2.2","plan":"free","tags":
["redis","redis-2.2","key-value","nosql"],"credentials":
{"hostname":"172.30.48.40","host":"172.30.48.40","port":5023,"pa
ssword":"8e9a901f-987d-4544-9a9e-
ab0c143b5142","name":"de82c4bb-bd08-46c0-a850-
af6534f71ca3"}}],"mongodb-1.8":[{"name":"mongodb-
e7d29","label":"mongodb-1.8","plan":"free","tags”:………………….




                                                             35
Accessing Your Services

 Debugging and accessing the data locally
   • Caldecott --> Service tunneling. Access your Cloud Foundry service as if it was local.




                                                                                              36
Tunneling
gem install caldecott
vmc tunnel <mongodb>




                        37
Using your favorite tools




                            38
39
Spring on Cloud Foundry




                          40
Auto-Reconfiguration: Getting Started

 Deploy Spring apps to the cloud without changing a single line of code
 Cloud Foundry automatically re-configures bean definitions to bind to cloud
 services
 Works with Spring and Grails




                                                                            41
Auto-Reconfiguration: Relational DB

 Detects beans of type javax.sql.DataSource
 Connects to MySQL or PostgreSQL services
 • Specifies driver, url, username, password, validation query
 Creates Commons DBCP or Tomcat DataSource
 Replaces existing DataSource

import org.apache.commons.dbcp.BasicDataSource;
...
@Bean(destroyMethod = "close")public BasicDataSource dataSource(){
   BasicDataSource bds = new BasicDataSource();
bds.setUrl( "jdbc:h2:mem"); bds.setPassword(""); bds.setUsername("sa");
   bds.setDriverClass( Driver.class); return bds;}




                                                                   42
Auto-Reconfiguration: ORM


 Adjusts Hibernate Dialect
 Changes hibernate.dialect property to
 MySQLDialect (MyISAM) or PostgreSQLDialect
 • org.springframework.orm.jpa.AbstractEntityManagerFactoryBean
 • org.springframework.orm.hibernate3.AbstractSessionFactoryBean
  (Spring 2.5 and 3.0)
 • org.springframework.orm.hibernate3.SessionFactoryBuilderSupport
  (Spring 3.1)

@Bean public LocalContainerEntityManagerFactoryBean entityManager
{ LocalContainerEntityManagerFactoryBean lcem =
    new LocalContainerEntityManagerFactoryBean();
lcem.setDataSource( dataSource()); return lcem; }




                                                                     43
Auto-Reconfiguration: How It Works

 Cloud Foundry installs a BeanFactoryPostProcessor in your application
 context during staging
 • Adds jar to your application
 • Modifies web.xml to load BFPP
  • Adds context file to contextConfigLocation
     • web-app context-param
     • Spring MVC DispatcherServlet init-param
 Adds PostgreSQL and MySQL driver jars as needed for DataSource
 reconfiguration




                                                                          44
The Environment

 Asking Questions
 • You can introspect the environment variables (System.getenv(“VCAP_SERVICES”)),
  or...
 • import the CloudFoundry runtime API from Java!
  • (much simpler)


  <dependency>
    <groupId>org.cloudfoundry</groupId>
     <artifactId>cloudfoundry-runtime</artifactId>
     <version>0.8.1</version>
   </dependency>




                                                                                    45
The Spring Developer’s Perspective: The Environment
@Controller
public class HomeController {
 @RequestMapping(value = "/", method = RequestMethod.GET)
  public String home(Map<String, Object> model) { CloudEnvironment
cloudEnvironment = new CloudEnvironment(); if
(cloudEnvironment.getCloudApiUri() != null) {      model.put("host",
cloudEnvironment.getInstanceInfo().getHost());       model.put("port",
cloudEnvironment.getInstanceInfo().getPort()); } return "home"; }


}




                                                                         46
Giving Your Application Clues with the env command

env <appname>
     List application environment variables
env <appname>

env-add <appname> <variable[=]value>
env-add <appname> <variable[=]value>
     Add an environment variable to an application

env-del <appname> <variable>
env-del <appname> <variable>
    Delete an environment variable to an application



$ env-add html5expenses PAYMENT_GATEWAY=http://blah.com

       is the same as..

$ export PAYMENT_GATEWAY=http://blah.com




                                                          47
Introducing... the Cloud Namespace

 <cloud:> namespace for use in Spring app contexts
 Provides application-level control of bean service bindings
 Recommended for development of new cloud apps
 Use when:
 • You have multiple services of the same type
 • You have multiple connecting beans of the same type
  • e.g. DataSource, MongoDBFactory
 • You have custom bean configuration
  • e.g. DataSource pool size, connection properties




                                                                48
<cloud:service-scan>
 Scans all services bound to the application and creates a bean of an
  appropriate type for each
  • Same bean types as auto-reconfiguration
 Useful during early development phases
 Do NOT leave it in (encourages bad testability).
  • Spring 3.1 profiles are an elegant solution
<beans     ...
   xmlns:cloud="http://schema.cloudfoundry.org/spring"
     xsi:schemaLocation="http://schema.cloudfoundry.org/spring
   http://schema.cloudfoundry.org/spring/cloudfoundry-spring-0.8.xsd
     ...">

      <cloud:service-scan/>

</beans>



                                                                         49
<cloud:service-scan> Autowire Dependencies
 Created beans can be autowired as dependencies
 Use @Qualifier with service name if multiple services of same type bound
 to app


   @Autowired(required=false)
   private ConnectionFactory rabbitConnectionFactory;

   @Autowired
   private RedisConnectionFactory redisConnectionFactory;

   @Autowired
   @Qualifier("test_mysql_database")
   private DataSource mysqlDataSource;

   @Autowired(required=false)
   @Qualifier("test_postgres_database")
   private DataSource postgresDataSource;

                                                                         50
<cloud:data-source>
 Configures a DataSource bean
 • Commons DBCP or Tomcat DataSource
 Basic attributes:
 • id: defaults to service name
 • service-name: only needed if you have multiple relational database services bound to
  the app




   <cloud:data-source id="dataSource"/>

   <bean class="org.sf.orm.jpa.LocalContainerEntityManagerFactoryBean"
   id="entityManagerFactory">
       <property name="dataSource" ref="dataSource"/>
   </bean>



                                                                                          51
<cloud:data-source> Example




<cloud:data-source id="dataSource" service-name="mySQLSvc">
<cloud:pool pool-size="1-5"/>
<cloud:connection properties="charset=utf-8"/>
</cloud:data-source>


...

@Autowired
private DataSource dataSource ;




                                                              52
<cloud:properties>
 Exposes basic information about services that can be consumed with
 Spring’s property placeholder support
 Basic attributes:
 • id: the name of the properties bean
 Properties automatically available when deploying Spring 3.1 applications

<cloud:properties id="cloudProperties" />
<context:property-placeholder properties-ref="cloudProperties"/>
@Autowired private Environment environment;@Beanpublic ComboPooledDataSource dataSource() throws Exception { String user = this.environment.getProperty
      ("cloud.services.mysql.connection.username"); ComboPooledDataSource cpds = new ComboPooledDataSource(); cpds.setUser(user); return cpds; }




                                                                                                                                                          53
Spring 3.1 Environment Abstraction
 Bean definitions for a specific environment (Profiles)
 • e.g. development, testing, production
 • Possibly different deployment environments
 • Activate profiles by name
   • spring.profiles.active system property
   • Other means outside deployment unit
   • “default” profile activates if no other profiles specified
 Custom resolution of placeholders
 • Dependent on the actual environment
 • Ordered property sources
 Requires Spring 3.1 (or later)




                                                                  54
Isolating Cloud Foundry Configuration
 Switch between local, testing and Cloud Foundry deployments with Profiles
 “cloud” profile automatically activates on Cloud Foundry
 • usage of the cloud namespace should occur within the cloud profile block




                                                                              55
Isolating Cloud Foundry Configuration


<bean class="org.sf.orm.jpa.LocalContainerEntityManagerFactoryBean">
     <property name="dataSource" ref="dataSource"/>
</bean>
<beans profile="cloud">
      <cloud:data-source id="dataSource" />
</beans>

<beans profile="default">
      <bean class="org.a.commons.dbcp.BasicDataSource" id="dataSource">
           <property name="url" value="jdbc:mysql://localhost/my_db" />
      </bean>
</beans>




                                                                          56
Profile Support: How It Works
 Cloud Foundry installs a custom ApplicationContextInitializer in your app
 during staging
 • Modifies web.xml
  • Adds to contextInitializerClasses context-param
 Adds “cloud” as an active profile
 Adds a PropertySource to the Environment




                                                                              57
Java Configuration
 Alternative to <cloud:*> namespace
 • Spring Java Configuration
 • Non-Spring apps
 Programmatic creation of service connection factories
 • Using ServiceCreator and ServiceInfo classes
 Works well with CloudEnvironment
 Included in cloudfoundry-runtime lib




                                                          58
Java Configuration with Profiles


  @Configuration
  @Profile(“local”)
  public class LocalDataSourceConfiguration {

  @Bean public javax.sql.DataSource dataSource() { ... }

  }


  @Configuration
  @Profile(“cloud”)
  public class CloudDataSourceConfiguration {

  @Bean public javax.sql.DataSource dataSource() { ... }

  }




                                                           59
Using ServiceCreator


//Provides access to CF service and application env info
CloudEnvironment environment = new CloudEnvironment();

//Retrieve env info for bound service named "mysqlService"
RdbmsServiceInfo mysqlSvc =
     environment.getServiceInfo("mysqlService", RdbmsServiceInfo.class);

//create a DataSource bound to the service
RdbmsServiceCreator dataSourceCreator = new RdbmsServiceCreator();

DataSource dataSource = dataSourceCreator.createService(mysqlSvc);




                                                                           60
Using ServiceInfo



//Provides access to CF service and application env info
CloudEnvironment environment = new CloudEnvironment();

//Retrieve env info for bound service named "mongoService"
MongoServiceInfo mongoSvc =
    environment.getServiceInfo("mongoService", MongoServiceInfo.class);

//create a Mongo DB bound to the service
Mongo mongoDB = new Mongo(mongoSvc.getHost(), mongoSvc.getPort());




                                                                          61
Looking Forward

 Spring Insight for Cloud Foundry
 Better Integration with Public/Private Cloud Hybrid Scenarios




                                                                  62
is
               Hiring in Seattle!

              Software Engineers
       Site Reliability Engineers/DevOps
             Developer Advocates

     http://www.cloudfoundry.com/jobs
                      Confidential
63
CloudFoundry.com signup promo code: cloudtalk




             Questions?
           Say hi on Twitter:
@starbuxman @springsource @cloudfoundry
           NOT CONFIDENTIAL -- TELL EVERYONE

Spring and Cloud Foundry; a Marriage Made in Heaven

  • 1.
    Spring and CloudFoundry: a Marriage Made in Heaven Josh Long, Spring Developer Advocate SpringSource, a division of VMware Twitter: @starbuxman Email: josh.long@springsource.com
  • 2.
    About Josh Long SpringDeveloper Advocate twitter: @starbuxman josh.long@springsource.com NOT CONFIDENTIAL -- TELL EVERYONE 2
  • 3.
    VMware is theCustomer Proven Market Leader  Company Overview • $3.77 billion in 2011 revenues • >$4.5 billion in cash and equivalents • 30%+ operating margins • 11,000 + employees worldwide • 5th largest infrastructure software company in the world  Proven in the Trenches • 300,000+ VMware customers • 100% of Fortune 100 • 100% of Fortune Global 100 • 99% of Fortune 1000 • 97% of Fortune Global 500 Confidential 3
  • 4.
    Spring Makes BuildingApplications Easy... NOT CONFIDENTIAL -- TELL EVERYONE 4
  • 5.
    Tell Spring AboutYour Objects package org.springsource.examples.spring31.services;... @Configuration @ComponentScan(“the.package.with.beans.in.it”)public class ServicesConfiguratio { ... } } } 5
  • 6.
    Tell Spring AboutYour Objects public class Main { static public void main (String [] args) throws Throwable { ApplicationContext ac = new AnnotationConfigApplicationContext( org.springsource.examples.spring31.services.ServicesConfiguration.class); ... } } 6
  • 7.
    Tell Spring AboutYour Objects package the.package.with.beans.in.it; @Service public class CustomerService { public Customer createCustomer(String firstName, String lastName, Date signupDate) { } ... } 7
  • 8.
    I want DatabaseAccess ... package org.springsource.examples.spring31.services;... @Configurationpublic class ServicesConfiguration { @Bean public DataSource dataSource() throws Exception { SimpleDriverDataSource simpleDriverDataSource = new SimpleDriverDataSource(); .... return simpleDriverDataSource; } } } } 8
  • 9.
    I want DatabaseAccess ... with Hibernate 4 Support package org.springsource.examples.spring31.services;... @Configurationpublic class ServicesConfiguration { ... @Bean public SessionFactory sessionFactory() throw Exception { Properties props = new Properties(); // ... show_sql, dialect, etc. return new LocalSessionFactoryBuilder( dataSourc .addAnnotatedClasses(Customer.class) .addProperties(props) .buildSessionFactory(); } } } } 9
  • 10.
    I want DatabaseAccess ... with Hibernate 4 Support package the.package.with.beans.in.it; ... @Service public class CustomerService { @Inject private SessionFactory sessionFactory; public Customer createCustomer(String firstName, String lastName, Date signupDate) { Customer customer = new Customer(); customer.setFirstName(firstName); customer.setLastName(lastName); customer.setSignupDate(signupDate); sessionFactory.getCurrentSession().save(customer); return customer; } ... } 10
  • 11.
    I want DeclarativeTransaction Management... package org.springsource.examples.spring31.services;... @Configuration @EnableTransactionManagementpublic class ServicesConfiguration { ... @Bean public PlatformTransactionManager transactionManager() throws Exc { return new HibernateTransactionManager(this.sessionFactory()); } } } } } 11
  • 12.
    I want DeclarativeTransaction Management... package the.package.with.beans.in.it; ... @Service public class CustomerService { @Inject private SessionFactory sessionFactory; @Transactional public Customer createCustomer(String firstName, String lastName, Date signupDate) { Customer customer = new Customer(); customer.setFirstName(firstName); customer.setLastName(lastName); customer.setSignupDate(signupDate); sessionFactory.getCurrentSession().save(customer); return customer; } ... } 12
  • 13.
    I want DeclarativeCache Management... package org.springsource.examples.spring31.services;... @Configuration @EnableTransactionManagement @EnableCachingpublic class ServicesConfiguration { ... @Bean public CacheManager cacheManager() { SimpleCacheManager scm = SimpleCacheManager(); Cache cache = new ConcurrentMapCache("customers"); scm.setCaches(Arrays.asList(cache)); return scm; }} SimpleCacheManager scm = new SimpleCacheManager(); Cache cache = new ConcurrentMapCache("customers"); scm.setCaches(Arrays.asList(cache)); ret SimpleCacheManager scm = new SimpleCacheManager(); Cache cache = new ConcurrentMapCache("customers"); scm.setCaches(Arrays.asList(cache)); ret SimpleCacheManager scm = new SimpleCacheManager(); Cache cache = new ConcurrentMapCache("customers"); scm.setCaches(Arrays.asList(cache)); ret 13
  • 14.
    I want DeclarativeCache Management... package the.package.with.beans.in.it; ... @Service public class CustomerService { @Inject private SessionFactory sessionFactory; @Transactional @Cacheable(“customers”) public Customer createCustomer(String firstName, String lastName, Date signupDate) { Customer customer = new Customer(); customer.setFirstName(firstName); customer.setLastName(lastName); customer.setSignupDate(signupDate); sessionFactory.getCurrentSession().save(customer); return customer; } } 14
  • 15.
    I want aRESTful Endpoint... package org.springsource.examples.spring31.web;.. @Controllerpublic class CustomerController { @Inject private CustomerService customerService; @RequestMapping(value = "/customer/{id}", produces = MediaType.APPLICATION_JSON_VALUE) public @ResponseBody Customer customerById(@PathVariable("id") Integer id) { return customerService.getCustomerById(id); } ... } } } 15
  • 16.
    Cloud Foundry: Choiceof Runtimes 16
  • 17.
    Frameworks and RuntimesSupported • Out of the Box • Java (.WAR files, on Tomcat. Spring’s an ideal choice here, of course..) • Scala (Lift, Play!) • Ruby (Rails, Sinatra, etc.) • Node.js • Ecosystem Partners • .NET (Uhuru, Tier3) • both from Seattle-native partners! • Runs standard .NET (no need to port your application) • Python (Stackato) • PHP (AppFog) • Haskell (1) 1) http://www.cakesolutions.net/teamblogs/2011/11/25/haskell-happstack-on-cloudfoundry/ • Erlang (2) 2) https://github.com/cloudfoundry/vcap/pull/20 17
  • 18.
    Deploying an Application CLI Application name Dir containing application (or, .WAR for Java) $ vmc push cf1 --path target --url cer-cf1.cloudfoundry.com Application URL 18
  • 19.
    Deploying an Application $ vmc push cf1 --path target --url cer-cf1.cloudfoundry.com Detected a Java Web Application, is this correct? [Yn]: Memory Reservation [Default:512M] (64M, 128M, 256M, 512M, 1G or 2G) Creating Application: OK Would you like to bind any services to 'cf1'? [yN]: Uploading Application: Checking for available resources: OK Packing application: OK Uploading (2K): OK Push Status: OK Starting Application: OK 19
  • 20.
    Deploying an Application(with a Manifest) $ vmc push Would you like to deploy from the current directory? [Yn]: y Pushing application 'html5expenses'... Creating Application: OK Creating Service [expenses-mongo]: OK Binding Service [expenses-mongo]: OK Creating Service [expenses-postgresql]: OK Binding Service [expenses-postgresql]: OK Uploading Application: Checking for available resources: OK Processing resources: OK Packing application: OK Uploading (6K): OK Push Status: OK Staging Application 'html5expenses': OK 20
  • 21.
    Deploying an Application(with a manifest.yml) --- applications: target: name: html5expenses url: ${name}.${target-base} framework: name: spring info: mem: 512M description: Java SpringSource Spring Application exec: mem: 512M instances: 1 services: expenses-mongo: type: :mongodb expenses-postgresql: type: :postgresql 21
  • 22.
    Flexible Application Topologies system load balancer elastic pool redis mysql front_end front_end rabbitMQ elastic pool mongodb back_end 10 22
  • 23.
    Deployment with STS QuickTimeª and a H.264 decompressor are needed to see this picture. 23
  • 24.
  • 25.
    Main Risk: LockIn Welcome to the hotel californiaSuch a lovely placeSuch a lovely facePlenty of room at the hotel californiaAny time of year, you can find it here Last thing I remember, I wasRunning for the doorI had to find the passage backTo the place I was before’relax,’ said the night man,We are programmed to receive.You can checkout any time you like,But you can never leave! -the Eagles 25
  • 26.
  • 27.
  • 28.
    Cloud Foundry: Clouds  AppFog.com • community lead for PHP • PaaS for PHP  Joyent • community lead for Node.js  ActiveState • community lead for Python, Perl • Providers of Stackato private PaaS 28
  • 29.
    Cloud Foundry.org Foundry Community 29
  • 30.
    Micro Cloud Foundry(beta) Micro Cloud Foundry
  • 31.
  • 32.
    Cloud Foundry: Services Services are one of the extensibility planes in Cloud Foundry • there are more services being contributed by the community daily!  MySQL, Redis, MongoDB, RabbitMQ, PostgreSQL  Services may be shared across applications  Cloud Foundry abstracts the provisioning aspect of services through a uniform API hosted in the cloud controller  It’s very easy to take an app and add a service to the app in a uniform way • Cassandra? COBOL / CICS, Oracle 32
  • 33.
    Cloud Foundry: Services $ vmc create-service mysql --name mysql1 Creating Service: OK $ vmc services ============== System Services ============== +------------+---------+---------------------------------------+ | Service | Version | Description | +------------+---------+---------------------------------------+ | mongodb | 1.8 | MongoDB NoSQL store | | mysql | 5.1 | MySQL database service | | postgresql | 9.0 | PostgreSQL database service (vFabric) | | rabbitmq | 2.4 | RabbitMQ messaging service | | redis | 2.2 | Redis key-value store service | +------------+---------+---------------------------------------+ =========== Provisioned Services ============ +-------------+---------+ | Name | Service | +-------------+---------+ | mysql1 | mysql | +-------------+---------+ 33
  • 34.
    the Original “CloudMessaging” Solution 34
  • 35.
    Cloud Foundry: ServicesCreation and Binding $VCAP_SERVICES: {"redis-2.2": [{"name":"redis_sample","label":"redis-2.2","plan":"free","tags": ["redis","redis-2.2","key-value","nosql"],"credentials": {"hostname":"172.30.48.40","host":"172.30.48.40","port":5023,"pa ssword":"8e9a901f-987d-4544-9a9e- ab0c143b5142","name":"de82c4bb-bd08-46c0-a850- af6534f71ca3"}}],"mongodb-1.8":[{"name":"mongodb- e7d29","label":"mongodb-1.8","plan":"free","tags”:…………………. 35
  • 36.
    Accessing Your Services Debugging and accessing the data locally • Caldecott --> Service tunneling. Access your Cloud Foundry service as if it was local. 36
  • 37.
  • 38.
  • 39.
  • 40.
    Spring on CloudFoundry 40
  • 41.
    Auto-Reconfiguration: Getting Started Deploy Spring apps to the cloud without changing a single line of code  Cloud Foundry automatically re-configures bean definitions to bind to cloud services  Works with Spring and Grails 41
  • 42.
    Auto-Reconfiguration: Relational DB Detects beans of type javax.sql.DataSource  Connects to MySQL or PostgreSQL services • Specifies driver, url, username, password, validation query  Creates Commons DBCP or Tomcat DataSource  Replaces existing DataSource import org.apache.commons.dbcp.BasicDataSource; ... @Bean(destroyMethod = "close")public BasicDataSource dataSource(){ BasicDataSource bds = new BasicDataSource(); bds.setUrl( "jdbc:h2:mem"); bds.setPassword(""); bds.setUsername("sa"); bds.setDriverClass( Driver.class); return bds;} 42
  • 43.
    Auto-Reconfiguration: ORM  AdjustsHibernate Dialect  Changes hibernate.dialect property to MySQLDialect (MyISAM) or PostgreSQLDialect • org.springframework.orm.jpa.AbstractEntityManagerFactoryBean • org.springframework.orm.hibernate3.AbstractSessionFactoryBean (Spring 2.5 and 3.0) • org.springframework.orm.hibernate3.SessionFactoryBuilderSupport (Spring 3.1) @Bean public LocalContainerEntityManagerFactoryBean entityManager { LocalContainerEntityManagerFactoryBean lcem = new LocalContainerEntityManagerFactoryBean(); lcem.setDataSource( dataSource()); return lcem; } 43
  • 44.
    Auto-Reconfiguration: How ItWorks  Cloud Foundry installs a BeanFactoryPostProcessor in your application context during staging • Adds jar to your application • Modifies web.xml to load BFPP • Adds context file to contextConfigLocation • web-app context-param • Spring MVC DispatcherServlet init-param  Adds PostgreSQL and MySQL driver jars as needed for DataSource reconfiguration 44
  • 45.
    The Environment  AskingQuestions • You can introspect the environment variables (System.getenv(“VCAP_SERVICES”)), or... • import the CloudFoundry runtime API from Java! • (much simpler) <dependency> <groupId>org.cloudfoundry</groupId> <artifactId>cloudfoundry-runtime</artifactId> <version>0.8.1</version> </dependency> 45
  • 46.
    The Spring Developer’sPerspective: The Environment @Controller public class HomeController { @RequestMapping(value = "/", method = RequestMethod.GET) public String home(Map<String, Object> model) { CloudEnvironment cloudEnvironment = new CloudEnvironment(); if (cloudEnvironment.getCloudApiUri() != null) { model.put("host", cloudEnvironment.getInstanceInfo().getHost()); model.put("port", cloudEnvironment.getInstanceInfo().getPort()); } return "home"; } } 46
  • 47.
    Giving Your ApplicationClues with the env command env <appname> List application environment variables env <appname> env-add <appname> <variable[=]value> env-add <appname> <variable[=]value> Add an environment variable to an application env-del <appname> <variable> env-del <appname> <variable> Delete an environment variable to an application $ env-add html5expenses PAYMENT_GATEWAY=http://blah.com is the same as.. $ export PAYMENT_GATEWAY=http://blah.com 47
  • 48.
    Introducing... the CloudNamespace  <cloud:> namespace for use in Spring app contexts  Provides application-level control of bean service bindings  Recommended for development of new cloud apps  Use when: • You have multiple services of the same type • You have multiple connecting beans of the same type • e.g. DataSource, MongoDBFactory • You have custom bean configuration • e.g. DataSource pool size, connection properties 48
  • 49.
    <cloud:service-scan>  Scans allservices bound to the application and creates a bean of an appropriate type for each • Same bean types as auto-reconfiguration  Useful during early development phases  Do NOT leave it in (encourages bad testability). • Spring 3.1 profiles are an elegant solution <beans ... xmlns:cloud="http://schema.cloudfoundry.org/spring" xsi:schemaLocation="http://schema.cloudfoundry.org/spring http://schema.cloudfoundry.org/spring/cloudfoundry-spring-0.8.xsd ..."> <cloud:service-scan/> </beans> 49
  • 50.
    <cloud:service-scan> Autowire Dependencies Created beans can be autowired as dependencies  Use @Qualifier with service name if multiple services of same type bound to app @Autowired(required=false) private ConnectionFactory rabbitConnectionFactory; @Autowired private RedisConnectionFactory redisConnectionFactory; @Autowired @Qualifier("test_mysql_database") private DataSource mysqlDataSource; @Autowired(required=false) @Qualifier("test_postgres_database") private DataSource postgresDataSource; 50
  • 51.
    <cloud:data-source>  Configures aDataSource bean • Commons DBCP or Tomcat DataSource  Basic attributes: • id: defaults to service name • service-name: only needed if you have multiple relational database services bound to the app <cloud:data-source id="dataSource"/> <bean class="org.sf.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory"> <property name="dataSource" ref="dataSource"/> </bean> 51
  • 52.
    <cloud:data-source> Example <cloud:data-source id="dataSource"service-name="mySQLSvc"> <cloud:pool pool-size="1-5"/> <cloud:connection properties="charset=utf-8"/> </cloud:data-source> ... @Autowired private DataSource dataSource ; 52
  • 53.
    <cloud:properties>  Exposes basicinformation about services that can be consumed with Spring’s property placeholder support  Basic attributes: • id: the name of the properties bean  Properties automatically available when deploying Spring 3.1 applications <cloud:properties id="cloudProperties" /> <context:property-placeholder properties-ref="cloudProperties"/> @Autowired private Environment environment;@Beanpublic ComboPooledDataSource dataSource() throws Exception { String user = this.environment.getProperty ("cloud.services.mysql.connection.username"); ComboPooledDataSource cpds = new ComboPooledDataSource(); cpds.setUser(user); return cpds; } 53
  • 54.
    Spring 3.1 EnvironmentAbstraction  Bean definitions for a specific environment (Profiles) • e.g. development, testing, production • Possibly different deployment environments • Activate profiles by name • spring.profiles.active system property • Other means outside deployment unit • “default” profile activates if no other profiles specified  Custom resolution of placeholders • Dependent on the actual environment • Ordered property sources  Requires Spring 3.1 (or later) 54
  • 55.
    Isolating Cloud FoundryConfiguration  Switch between local, testing and Cloud Foundry deployments with Profiles  “cloud” profile automatically activates on Cloud Foundry • usage of the cloud namespace should occur within the cloud profile block 55
  • 56.
    Isolating Cloud FoundryConfiguration <bean class="org.sf.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource"/> </bean> <beans profile="cloud"> <cloud:data-source id="dataSource" /> </beans> <beans profile="default"> <bean class="org.a.commons.dbcp.BasicDataSource" id="dataSource"> <property name="url" value="jdbc:mysql://localhost/my_db" /> </bean> </beans> 56
  • 57.
    Profile Support: HowIt Works  Cloud Foundry installs a custom ApplicationContextInitializer in your app during staging • Modifies web.xml • Adds to contextInitializerClasses context-param  Adds “cloud” as an active profile  Adds a PropertySource to the Environment 57
  • 58.
    Java Configuration  Alternativeto <cloud:*> namespace • Spring Java Configuration • Non-Spring apps  Programmatic creation of service connection factories • Using ServiceCreator and ServiceInfo classes  Works well with CloudEnvironment  Included in cloudfoundry-runtime lib 58
  • 59.
    Java Configuration withProfiles @Configuration @Profile(“local”) public class LocalDataSourceConfiguration { @Bean public javax.sql.DataSource dataSource() { ... } } @Configuration @Profile(“cloud”) public class CloudDataSourceConfiguration { @Bean public javax.sql.DataSource dataSource() { ... } } 59
  • 60.
    Using ServiceCreator //Provides accessto CF service and application env info CloudEnvironment environment = new CloudEnvironment(); //Retrieve env info for bound service named "mysqlService" RdbmsServiceInfo mysqlSvc = environment.getServiceInfo("mysqlService", RdbmsServiceInfo.class); //create a DataSource bound to the service RdbmsServiceCreator dataSourceCreator = new RdbmsServiceCreator(); DataSource dataSource = dataSourceCreator.createService(mysqlSvc); 60
  • 61.
    Using ServiceInfo //Provides accessto CF service and application env info CloudEnvironment environment = new CloudEnvironment(); //Retrieve env info for bound service named "mongoService" MongoServiceInfo mongoSvc = environment.getServiceInfo("mongoService", MongoServiceInfo.class); //create a Mongo DB bound to the service Mongo mongoDB = new Mongo(mongoSvc.getHost(), mongoSvc.getPort()); 61
  • 62.
    Looking Forward  SpringInsight for Cloud Foundry  Better Integration with Public/Private Cloud Hybrid Scenarios 62
  • 63.
    is Hiring in Seattle! Software Engineers Site Reliability Engineers/DevOps Developer Advocates http://www.cloudfoundry.com/jobs Confidential 63
  • 64.
    CloudFoundry.com signup promocode: cloudtalk Questions? Say hi on Twitter: @starbuxman @springsource @cloudfoundry NOT CONFIDENTIAL -- TELL EVERYONE

Editor's Notes

  • #3 Hello, thank you or having me. Im pleased to have the opportunity to introduce you today to Spring and the SpringSource Tool Suite My anem is Josh Long. I serve as the developer advocate for the Spring framework. I’ve used it in earnest and advocated it for many years now. i’m an author on 3 books on the technology, as well as a comitter to many of the Spring projects. Additionally, I take community activism very seriously and do my best to participate in the community. Sometimes this means answering question on Twitter, or in the forums, or helping contribute to the InfoQ.com and Artima.com communities
  • #20 This is what happens when you run the command.
  • #21 This is what happens when you run the command.
  • #22 This is what happens when you run the command.
  • #23 - the nice part about CF is that you can scale each of these parts out independently: need 4 MySQL instances and 2 web servers? No problem. - its easy to create complex topologies
  • #24 - we can provide a Roo shell script that sets up a simple domain model and web application so that you don’t spend time building the Roo application in the demo. - note that you can deploy to a public cloud (perhaps, CloudFoundry.com), or to any other CloudFoundry project cloud local or otherwise - note that you don’t need to do anything to the DS in the default case: CF will introspect the Spring framework configuration and auto-stage the DS.
  • #43 Mention replacement vs adjustment - other properties not preserved. Emphasize any impl and format of bean def
  • #45 explain BFPP - before beans are created after bean defs processed
  • #49 Auto-reconfig is good but some limitations and meant to get you up and running quickly
  • #50 Mention all cloud namespace elements create same bean types as auto-reconfig and thus have same classpath reqs similar to component scanning in Spring
  • #54 Go beyond what we offer with easy access to or an obcure
  • #59 Refer back to Ramnivas’ early JSON env example
  • #62 This allows more flexibility in picking which bean to create, setting properties, etc. Doesn’t require Spring Data. Doesn’t require Spring (since could just use cloud properties injection instead of lookup from CloudEnvironment)