SlideShare a Scribd company logo
SpringSource and MongoDB


Chris Richardson

Author of POJOs in Action
Founder of CloudFoundry.com
Chris.Richardson@SpringSource.Com
@crichardson
Presentation Goal

  How SpringSource is
   making it easier for
     Java and Grails
   developers to build
  MongoDB applications

                      Slide 2
About Chris
        •    Grew up in England and live in Oakland, CA
        •    Over 25+ years of software development
             experience including 14 years of Java
        •    Speaker at JavaOne, SpringOne, NFJS,
             JavaPolis, Spring Experience, etc.
        •    Organize the Oakland JUG and the Groovy
             Grails meetup




                   http://www.theregister.co.uk/2009/08/19/springsource_cloud_foundry/



                                                                                         Slide 3
Agenda
   Introduction to Spring
   Spring Data and MongoDB
   Introduction to Grails
   Using Grails with MongoDB




                               Slide 4
The Spring framework
   Rapid evolution
 !    Spring 1.0 – March 2004
 !    Spring 2.0 – October 2006
 !    Spring 2.5 – December 2007
 !    Spring 3.0 – December 2009
 !    …
 !    Complete backward compatibility
   De facto standard programming
   model for enterprise Java
   Two million+ developers

                                        Slide 5
The Spring framework ecosystem
Framework                         Description
Spring framework                  The foundation
Spring.NET                        .NET port of the Spring framework
Spring Security (a.k.a. Acegi)    Extensible framework providing authentication,
                                  authorization and instance-level security
Spring Web Flow                   An excellent framework for building multi-page flows

Spring Web Services               Contract-first, document–centric SOAP web services

Spring Dynamic Modules for OSGI   Deploy Spring applications on OSGI
Spring Batch                      Powerful batch processing framework
Spring Integration                Implements enterprise integration patterns
Spring BlazeDS integration        Support for Adobe BlazeDS
Spring AMQP                       AMQP messaging, i.e. RabbitMQ
Spring Gemfire                    Simplify Gemfire application development
…

                                                                               Slide 6
Spring programming model
                       Dependency Injection:
                     resolves inter-component   Benefits:
                           dependencies,        • Improved developer
                          metadata-driven       productivity
                                                • Higher quality code
                                                • Portability across
                                                application servers




                            POJO
                                                    Aspect-Oriented
                                                    Programming:
Portable Service                                    modular
Abstractions:                                       implementation of
Transactions, data                                  cross cutting
access, …                                           concerns


                                                                  Slide 7
Portable service abstractions
  Portable service
  abstractions
  insulate developer         Business
                              Logic
  from low-level
  programming                Infrastructure code




  Less code                    Spring

  Simpler code                  Transactions
                                  Security
                                Data access


  Increased
                                     …




  productivity
  Portable code        Runtime Environment



                                                   Slide 8
Spring JDBC example
@Repository
class ActorDaoImpl implements ActorDao {
                                                          SimpleJdbcTemplate hides
@Autowired                                                the low-level, messy
private SimpleJdbcTemplate simpleJdbcTemplate;            details of using JDBC

public Actor findActor(String specialty, int age) {
  String sql = "select id, first_name, last_name from T_ACTOR" +
        " where specialty = ? and age = ?";

    RowMapper<Actor> mapper = new RowMapper<Actor>() {
       public Actor mapRow(ResultSet rs, int rowNum) throws SQLException {
         Actor actor = new Actor();
         actor.setId(rs.getLong("id"));
         actor.setFirstName(rs.getString("first_name"));
         actor.setLastName(rs.getString("last_name"));
         return actor;
       }
    };

    return simpleJdbcTemplate.queryForObject(sql, mapper, specialty, age);
}


                                                                                     Slide 9
Externalized database configuration
@Configuration
public class AppConfig {
  private @Value("#{jdbcProperties.url}") String jdbcUrl;
  private @Value("#{jdbcProperties.username}") String username;
  private @Value("#{jdbcProperties.password}") String password;

    @Bean
    public SimpleJdbcTemplate jdbcTemplate() {
      return new SimpleJdbcTemplate (dataSource());
    }

    @Bean
    public DataSource dataSource() {
      return new DriverManagerDataSource(jdbcUrl, username, password);
    }
}
                                                                 Reads DB
                                                                 configuration
<context:component-scan base-package="..."/>                     from file
<util:properties id="jdbcProperties" location="…/jdbc.properties"/>



                                                                                 Slide 10
Spring DataAccessException
   Base class for
exceptions thrown by                                    DataAccess
                                                         Exception

DAOs
    Consistent exception                Concurrency
                                          Failure
                                         Exception
                                                                       ...


handling across
Hibernate, JPA, JDBC,          Optimistic
                             LockingFailure

etc.                           Exception               Pessimistic
                                                      LockingFailure
                                                        Exception

     Unchecked exception
      Extensible exception                                       CannotSerialize

mapping:                                CannotAcquire
                                        LockException
                                                                  Transaction
                                                                   Exception

SqlExceptionTranslator

                                                                                   11
Agenda
   Introduction to the Spring framework
   Spring Data and MongoDB
   Introduction to Grails
   Using Grails with MongoDB




                                    Slide 12
Spring Data Project Goals
   Bring classic Spring value propositions
   to a wide range of NoSQL databases:
 !  Productivity
 !  Programming model consistency: E.g.
    <NoSQL>Template classes
 !  “Portability”
   Many entry points to use
 !    Auto-generated repository implementations
 !    Opinionated APIs (Think JdbcTemplate)
 !    Object Mapping (Java and GORM)
 !    Cross Store Persistence Programming model
 !    Productivity support in Roo and Grails
                                           Slide 13
MongoDB API usage patterns
   Create and store Mongo singleton
   Externalized server details
   Inserts/Updates
  !  Map application POJO " DBObject
  !  mongo.getDatabase(…).getCollection(…)
  !  Partial document updates
   Queries
  !  mongo.getDatabase(…).getCollection(…)
  !  Iterate through Cursor
  !  Map DBObject " application POJO

#  Higher-level than JDBC but still repetitive,
                       …

                                             Slide 14
Spring Data - MongoDB
   MongoTemplate
   Generic repository implementation
   Querydsl integration
   Cross-store persistence




                                       Slide 15
MongoTemplate
Simplifies data         MongoTemplate              POJO $ DBObject
access            databaseName                         mapping
Translates        userId
                  Password
exceptions
                  defaultCollectionName

                  writeConcern
                  writeResultChecking
                                                     <<interface>>
                  save()                             MongoConvertor
                  insert()                       write(Object, DBObject)
                  remove()                       read(Class, DBObject)
                  updateFirst()
                  findOne()
                  find()
                  …
                                               SimpleMongo
                                        uses     Converter
                           Mongo
                                                         MongoMapping
                     (Java Driver class)
                                                           Converter

                                                              Slide 16
Example entity
public class Restaurant {
 private String id;
 private String name;
 private List<MenuItem> menuItems;

 public Restaurant() {
 }                                         public class MenuItem {
                                            private String name;
 public Restaurant(String name) {           private double price;
   this.name = name;
   …                                       public MenuItem() {
 }                                         }

public String getName() { return name; }    public MenuItem(String name,
                                                               double price) {
                                              this.name = name;
 public void setName(String name) {
                                              this.price = price;
   this.name = name;
 }                                          }

 …getters and setters…                     …getters and setters…
                                                                      Slide 17
Example data access code
@Repository
public class RestaurantRepository {

 @Autowired
 private MongoTemplate mongoTemplate;

 public static final String RESTAURANTS_COLLECTION = "restaurants2";


 public void add(Restaurant restaurant) {
   mongoTemplate.save(RESTAURANTS_COLLECTION, restaurant);
 }

public List<Restaurant> findRestaurantsByName(String restaurantName) {
   return mongoTemplate.find(RESTAURANTS_COLLECTION,
         new Query(where("name").is(restaurantName)),
         Restaurant.class);
 }


                                                                   Slide 18
Mongo document
{
    "_id" : ObjectId("4d977f55d3fe3119c904e026"),
    "menuItems" : [
         {
                "name" : "Tandoori Portobello Mushrooms",
                "price" : 5.5
         },
         {
                "name" : "Duck Curry Kerala",
                "price" : 15
         }
        ],
    "name" : "Ajanta"
}


                                                     Slide 19
Spring MongoDB Example - Config
@Configuration public class MongoDbExampleConfig {
 private @Value("#{mongoDbProperties.databaseName}") String mongoDbDatabase;
 private @Value("#{mongoDbProperties.host}") String mongoDbHost;

@Bean public Mongo mongo() throws Exception {                              Singleton
 return new Mongo(mongoDbHost);
}

 @Bean public MongoTemplate mongoTemplate(Mongo mongo) {
   return new MongoTemplate(mongo, mongoDbDatabase);
 }…


                                 <beans>
                                 <context:annotation-config/>
              External Config
                                  <context:component-scan
                                     base-package="net.chrisrichardson.mongodb.example"/>

mongodb.properties:              <util:properties id="mongoDbProperties"
                                    location="mongodb.properties"/>
databaseName=demo1
                                 </beans>
host=192.168.253.150

                                                                               Slide 20
Spring MongoDB Example Test
public class MongoDbExampleTest {

 @Autowired private RestaurantRepository restaurantRepository;

 @Test public void test() {
  Restaurant ajanta = makeAjantaRestaurant();

     restaurantRepository.add(ajanta);

     List<Restaurant> results =
           restaurantRepository.findRestaurantsByName("Ajanta");

     assertRestaurantFound(ajanta, results);
 }

 private Restaurant makeAjantaRestaurant() {
   Restaurant ajanta = new Restaurant("Ajanta");
   ajanta.add(new MenuItem("Tandoori Portobello Mushrooms", 5.50));
   ajanta.add(new MenuItem("Duck Curry Kerala", 15.00));
   return ajanta;
 }
…
                                                                      Slide 21
Update example
@Repository
public class RestaurantRepository {
  public void addMenuItem(String restaurantId,
                          MenuItem newMenuItem) {
   DBObject dbo = new BasicDBObject();
   mongoTemplate.getConverter().write(newMenuItem, dbo);

    mongoTemplate.updateFirst(RESTAURANTS_COLLECTION,
      new Query(where("_id").is(new ObjectId(restaurantId))),
      new Update().push("menuItems", dbo));

}


         Atomic, in-place update of document

                                                       Slide 22
Callbacks – access driver API with
  exception translation
@Test
public void testDbCallback() {                     Exceptions are
  Restaurant ajanta = makeAjantaRestaurant();        translated
  restaurantRepository.add(ajanta);
  assertCollectionExists("restaurants2");
}

private Void assertCollectionExists(final String collectionName) {
  return mongoTemplate.execute(new DbCallback<Void>(){
   @Override
   public Void doInDB(DB db) {
     Set<String> collectionNames = db.getCollectionNames();
     Assert.assertTrue("Missing from " +
                  collectionNames,
                  collectionNames.contains(collectionName));
     return null;
   }});
}
                                                               Slide 23
Generic Mongo Repositories
   Generic Repositories support
 !  Basic CRUD methods
 !  Dynamic finders
 !  Pagination and sorting
   You define interface that extends
   Repository interface
   Spring Data generates Mongo-specific
   implementation at runtime


                                    Slide 24
Example Mongo Generic Repository
public class Person {
  private ObjectId id;
  private String firstname;
  private String lastname;
… getters and setters
}

interface PersonRepository
                     extends MongoRepository<Person, ObjectId> {
   List<Person> findByLastname(String lastName);
}

Person p = new Person("John", "Doe");
personRepository.save(p);

Person p2 = personRepository.findOne(p.getId());

List<Person> johnDoes = personRepository.findByLastname("Doe");
assertEquals(1, johnDoes.size());

                                                                   Slide 25
Example Mongo Repository config

<bean>

<mongo:repositories
 base-package="net.chrisrichardson.mongodb.example.mongorepository"
   mongo-template-ref="mongoTemplate" />

</beans>




     Scans classpath looking for
    subtypes of MongoRepository
        in the base package

                                                          Slide 26
Richer mapping                       Annotations define mapping:
                                       @Document, @Id, @Indexed,
                                       @PersistanceConstructor,
@Document                              @CompoundIndex, @DBRef,
public class Person {                  @GeoSpatialIndexed, @Value

 @Id                                   Map fields instead of properties "
 private ObjectId id;                  no getters or setters required
 private String firstname;
                                       Non-default constructor
 @Indexed
 private String lastname;              Index generation

  @PersistenceConstructor
  public Person(String firstname, String lastname) {
    this.firstname = firstname;
    this.lastname = lastname;
  }
….
}

                                                                 Slide 27
Richer mapping configuration
@Configuration
public class MongoExampleConfig extends AbstractMongoConfiguration
{
 …

    @Override
    public MongoTemplate mongoTemplate() throws Exception {
      return new MongoTemplate(mongo(),
                               mongoDbDatabase, null,
                               mappingMongoConverter());
    }

@Override
public String getMappingBasePackage() {
 return Person.class.getPackage().getName();
}

}
                                                              Slide 28
Support for the QueryDSL project
 Generated from                         Type-safe
 domain model class                     composable queries


QPerson person = QPerson.person;

Predicate predicate =
       person.homeAddress.street1.eq("1 High Street")
              .and(person.firstname.eq("John"))

List<Person> people = personRepository.findAll(predicate);

assertEquals(1, people.size());
assertPersonEquals(p, people.get(0));

                                                        Slide 29
Cross-store/polyglot persistence
                                Person person = new Person(…);
@Entity
public class Person {           entityManager.persist(person);
  // In Database
 @Id private Long id;           Person p2 = entityManager.find(…)
 private String firstname;
 private String lastname;

// In MongoDB
@RelatedDocument private Address address;



     { "_id" : ObjectId(”….."),
      "_entity_id" : NumberLong(1),
       "_entity_class" : "net.. Person",
     "_entity_field_name" : "address",
        "zip" : "94611", "street1" : "1 High Street", …}

                                                           Slide 30
Spring MongoDB – Future Ideas
   MongoTemplate
 !  Support common map-reduce operations
    from Mongo Cookbook
 !  GridFS integration
   Tighter integration with Spring MVC
   for activity monitoring
 !  See current example code on github




                                         Slide 31
Agenda
   Introduction to Spring
   Spring Data and MongoDB
   Introduction to Grails
   Using Grails with MongoDB




                               Slide 32
Grails




   Open-source web application framework
   Uses Groovy – dynamic programming language
   for the JVM
   Builds on mature frameworks such as Spring


                                           Slide 33
GORM = Grails Object Relational Mapping

   Uses convention over configuration
  !  Defaults for which classes to persist
  !  Defaults for their O/R mapping
   Leverages the meta-object protocol
  !  Adds persistence methods and properties to
     domain classes
  !  No equivalent of Hibernate Session
  !  Avoids the need for dependency injection
  !  Eliminates many DAO cookie-cutter methods




                                              Slide 34
Database access made easy
                                                       customer
 class Customer {                                      <<table>>

    String name                                     id <<pk>>
 }                                                  version
                                                    name



 Customer c = new Customer("John Doe")

 if (!c.save())
    fail "validation failed: ${c.errors}"            GORM adds
                                                     Methods and
 Customer c2 = Customer.get(c.id)                 properties to class
                                                      at runtime
 c2.delete()

 assertNull Customer.get(c.id)


 def customers = Customer.findAllByName(“Fred”)


                                                                   Slide 35
Relationships don’t have to be difficult

                                                customer
class Customer {                                <<table>>
   String name                               id <<pk>>
   static hasMany = [ accounts : Account]    version
}                                            name


class Account {
                                                 account
   static belongsTo = [customer: Customer]      <<table>>
   double balance
                                             id <<pk>>
}                                            version
                                             customer <<fk>>
 Customer c = <…>                            balance
 Account a = new Account(…)
 c.addToAccounts(a)

 assertSame c, a.customer
 assertTrue c.accounts.contains(a)




                                                         Slide 36
When the defaults aren’t right
class Customer {
   static transients = ["networth"]

    static mapping = {
      id column: 'customer_id'              crc_customer
                                              <<table>>
      table 'crc_customer'
      columns {                         customer_id <<pk>>
                                        version
         name column: 'customer_name'   customer_name
      }
    }


    def getNetworth() { …}
    …
}




                                                    Slide 37
Agenda
   Introduction to Spring
   Spring Data and MongoDB
   Introduction to Grails
   Using Grails with MongoDB




                               Slide 38
GORM for MongoDB
   Extends GORM to support MongoDB
   Announced Nov 2010
   Currently 1.0M5
   Builds on
 !  Spring Data for MongoDB
 !  Spring Data Mapping




                                 Slide 39
GORM/MongoDB example
grails uninstall-plugin hibernate
grails install-plugin mongodb

class Customer {
   String name                                                 Unchanged
   Address address
   static hasMany = [ accounts : Account]
   static embedded = ['address']
}                                            class Address {
                                               String street
class Account {                                String city
   static belongsTo = [customer: Customer]     String state
   double balance                              String zip
}                                            }
DataSource.groovy
mongo {
  host = "localhost"
}

                                                                Slide 40
GORM/MongoDB example

> db.customer.find()
{ "_id" : NumberLong(24), "address" : { "city" : "Oakland", "state" : "CA",
          "street" : "1 High Street", "zip" : "94619" }, "name" : "John Doe" }
{ "_id" : NumberLong(25), "address" : { "city" : "Oakland", "state" : "CA",
          "street" : "101 Broadway", "zip" : "94619" }, "name" : "Mary Jane" }

> db.account.find()
{ "_id" : NumberLong(1), "balance" : 60, "customer" : NumberLong(24),
  "name" : "Checking" }
{ "_id" : NumberLong(2), "balance" : 100, "customer" : NumberLong(24),
  "name" : "Savings" }
{ "_id" : NumberLong(3), "balance" : 0, "customer" : NumberLong(25),
  "name" : "Checking" }


       Domain class $ Collection
       Property $ Attribute
       Relationship $ "FK attribute"
                                                                        Slide 41
Cloud Foundry supports Mongo




    MongoDB is one of the provided services
" Deploy your MongoDB applications in
seconds

                                       Slide 42
Summary
  Polyglot persistence is here to stay
  Spring Data is here to help you
  GORM let’s you use the familiar and
  powerful GORM API with MongoDB
  Deploy your Mongo application on
  CloudFoundry.com
  More info at
 !  http://www.springframework.org/spring-data
 !  http://www.cloudfoundry.com/

                                             Slide 43
Next steps
                    Checkout Spring Data
                    Consider contributing


                    Deploy on CloudFoundry.com


             My contact information


             chris.richardson@springsource.com


             Twitter: @crichardson




                                            Slide 44

More Related Content

MongoDB for Java Devs with Spring Data - MongoPhilly 2011

  • 1. SpringSource and MongoDB Chris Richardson Author of POJOs in Action Founder of CloudFoundry.com Chris.Richardson@SpringSource.Com @crichardson
  • 2. Presentation Goal How SpringSource is making it easier for Java and Grails developers to build MongoDB applications Slide 2
  • 3. About Chris •  Grew up in England and live in Oakland, CA •  Over 25+ years of software development experience including 14 years of Java •  Speaker at JavaOne, SpringOne, NFJS, JavaPolis, Spring Experience, etc. •  Organize the Oakland JUG and the Groovy Grails meetup http://www.theregister.co.uk/2009/08/19/springsource_cloud_foundry/ Slide 3
  • 4. Agenda   Introduction to Spring   Spring Data and MongoDB   Introduction to Grails   Using Grails with MongoDB Slide 4
  • 5. The Spring framework   Rapid evolution !  Spring 1.0 – March 2004 !  Spring 2.0 – October 2006 !  Spring 2.5 – December 2007 !  Spring 3.0 – December 2009 !  … !  Complete backward compatibility   De facto standard programming model for enterprise Java   Two million+ developers Slide 5
  • 6. The Spring framework ecosystem Framework Description Spring framework The foundation Spring.NET .NET port of the Spring framework Spring Security (a.k.a. Acegi) Extensible framework providing authentication, authorization and instance-level security Spring Web Flow An excellent framework for building multi-page flows Spring Web Services Contract-first, document–centric SOAP web services Spring Dynamic Modules for OSGI Deploy Spring applications on OSGI Spring Batch Powerful batch processing framework Spring Integration Implements enterprise integration patterns Spring BlazeDS integration Support for Adobe BlazeDS Spring AMQP AMQP messaging, i.e. RabbitMQ Spring Gemfire Simplify Gemfire application development … Slide 6
  • 7. Spring programming model Dependency Injection: resolves inter-component Benefits: dependencies, • Improved developer metadata-driven productivity • Higher quality code • Portability across application servers POJO Aspect-Oriented Programming: Portable Service modular Abstractions: implementation of Transactions, data cross cutting access, … concerns Slide 7
  • 8. Portable service abstractions   Portable service abstractions insulate developer Business Logic from low-level programming Infrastructure code   Less code Spring   Simpler code Transactions Security Data access   Increased … productivity   Portable code Runtime Environment Slide 8
  • 9. Spring JDBC example @Repository class ActorDaoImpl implements ActorDao { SimpleJdbcTemplate hides @Autowired the low-level, messy private SimpleJdbcTemplate simpleJdbcTemplate; details of using JDBC public Actor findActor(String specialty, int age) { String sql = "select id, first_name, last_name from T_ACTOR" + " where specialty = ? and age = ?"; RowMapper<Actor> mapper = new RowMapper<Actor>() { public Actor mapRow(ResultSet rs, int rowNum) throws SQLException { Actor actor = new Actor(); actor.setId(rs.getLong("id")); actor.setFirstName(rs.getString("first_name")); actor.setLastName(rs.getString("last_name")); return actor; } }; return simpleJdbcTemplate.queryForObject(sql, mapper, specialty, age); } Slide 9
  • 10. Externalized database configuration @Configuration public class AppConfig { private @Value("#{jdbcProperties.url}") String jdbcUrl; private @Value("#{jdbcProperties.username}") String username; private @Value("#{jdbcProperties.password}") String password; @Bean public SimpleJdbcTemplate jdbcTemplate() { return new SimpleJdbcTemplate (dataSource()); } @Bean public DataSource dataSource() { return new DriverManagerDataSource(jdbcUrl, username, password); } } Reads DB configuration <context:component-scan base-package="..."/> from file <util:properties id="jdbcProperties" location="…/jdbc.properties"/> Slide 10
  • 11. Spring DataAccessException  Base class for exceptions thrown by DataAccess Exception DAOs  Consistent exception Concurrency Failure Exception ... handling across Hibernate, JPA, JDBC, Optimistic LockingFailure etc. Exception Pessimistic LockingFailure Exception  Unchecked exception  Extensible exception CannotSerialize mapping: CannotAcquire LockException Transaction Exception SqlExceptionTranslator 11
  • 12. Agenda   Introduction to the Spring framework   Spring Data and MongoDB   Introduction to Grails   Using Grails with MongoDB Slide 12
  • 13. Spring Data Project Goals   Bring classic Spring value propositions to a wide range of NoSQL databases: !  Productivity !  Programming model consistency: E.g. <NoSQL>Template classes !  “Portability”   Many entry points to use !  Auto-generated repository implementations !  Opinionated APIs (Think JdbcTemplate) !  Object Mapping (Java and GORM) !  Cross Store Persistence Programming model !  Productivity support in Roo and Grails Slide 13
  • 14. MongoDB API usage patterns   Create and store Mongo singleton   Externalized server details   Inserts/Updates !  Map application POJO " DBObject !  mongo.getDatabase(…).getCollection(…) !  Partial document updates   Queries !  mongo.getDatabase(…).getCollection(…) !  Iterate through Cursor !  Map DBObject " application POJO #  Higher-level than JDBC but still repetitive, … Slide 14
  • 15. Spring Data - MongoDB   MongoTemplate   Generic repository implementation   Querydsl integration   Cross-store persistence Slide 15
  • 16. MongoTemplate Simplifies data MongoTemplate POJO $ DBObject access databaseName mapping Translates userId Password exceptions defaultCollectionName writeConcern writeResultChecking <<interface>> save() MongoConvertor insert() write(Object, DBObject) remove() read(Class, DBObject) updateFirst() findOne() find() … SimpleMongo uses Converter Mongo MongoMapping (Java Driver class) Converter Slide 16
  • 17. Example entity public class Restaurant { private String id; private String name; private List<MenuItem> menuItems; public Restaurant() { } public class MenuItem { private String name; public Restaurant(String name) { private double price; this.name = name; … public MenuItem() { } } public String getName() { return name; } public MenuItem(String name, double price) { this.name = name; public void setName(String name) { this.price = price; this.name = name; } } …getters and setters… …getters and setters… Slide 17
  • 18. Example data access code @Repository public class RestaurantRepository { @Autowired private MongoTemplate mongoTemplate; public static final String RESTAURANTS_COLLECTION = "restaurants2"; public void add(Restaurant restaurant) { mongoTemplate.save(RESTAURANTS_COLLECTION, restaurant); } public List<Restaurant> findRestaurantsByName(String restaurantName) { return mongoTemplate.find(RESTAURANTS_COLLECTION, new Query(where("name").is(restaurantName)), Restaurant.class); } Slide 18
  • 19. Mongo document { "_id" : ObjectId("4d977f55d3fe3119c904e026"), "menuItems" : [ { "name" : "Tandoori Portobello Mushrooms", "price" : 5.5 }, { "name" : "Duck Curry Kerala", "price" : 15 } ], "name" : "Ajanta" } Slide 19
  • 20. Spring MongoDB Example - Config @Configuration public class MongoDbExampleConfig { private @Value("#{mongoDbProperties.databaseName}") String mongoDbDatabase; private @Value("#{mongoDbProperties.host}") String mongoDbHost; @Bean public Mongo mongo() throws Exception { Singleton return new Mongo(mongoDbHost); } @Bean public MongoTemplate mongoTemplate(Mongo mongo) { return new MongoTemplate(mongo, mongoDbDatabase); }… <beans> <context:annotation-config/> External Config <context:component-scan base-package="net.chrisrichardson.mongodb.example"/> mongodb.properties: <util:properties id="mongoDbProperties" location="mongodb.properties"/> databaseName=demo1 </beans> host=192.168.253.150 Slide 20
  • 21. Spring MongoDB Example Test public class MongoDbExampleTest { @Autowired private RestaurantRepository restaurantRepository; @Test public void test() { Restaurant ajanta = makeAjantaRestaurant(); restaurantRepository.add(ajanta); List<Restaurant> results = restaurantRepository.findRestaurantsByName("Ajanta"); assertRestaurantFound(ajanta, results); } private Restaurant makeAjantaRestaurant() { Restaurant ajanta = new Restaurant("Ajanta"); ajanta.add(new MenuItem("Tandoori Portobello Mushrooms", 5.50)); ajanta.add(new MenuItem("Duck Curry Kerala", 15.00)); return ajanta; } … Slide 21
  • 22. Update example @Repository public class RestaurantRepository { public void addMenuItem(String restaurantId, MenuItem newMenuItem) { DBObject dbo = new BasicDBObject(); mongoTemplate.getConverter().write(newMenuItem, dbo); mongoTemplate.updateFirst(RESTAURANTS_COLLECTION, new Query(where("_id").is(new ObjectId(restaurantId))), new Update().push("menuItems", dbo)); } Atomic, in-place update of document Slide 22
  • 23. Callbacks – access driver API with exception translation @Test public void testDbCallback() { Exceptions are Restaurant ajanta = makeAjantaRestaurant(); translated restaurantRepository.add(ajanta); assertCollectionExists("restaurants2"); } private Void assertCollectionExists(final String collectionName) { return mongoTemplate.execute(new DbCallback<Void>(){ @Override public Void doInDB(DB db) { Set<String> collectionNames = db.getCollectionNames(); Assert.assertTrue("Missing from " + collectionNames, collectionNames.contains(collectionName)); return null; }}); } Slide 23
  • 24. Generic Mongo Repositories   Generic Repositories support !  Basic CRUD methods !  Dynamic finders !  Pagination and sorting   You define interface that extends Repository interface   Spring Data generates Mongo-specific implementation at runtime Slide 24
  • 25. Example Mongo Generic Repository public class Person { private ObjectId id; private String firstname; private String lastname; … getters and setters } interface PersonRepository extends MongoRepository<Person, ObjectId> { List<Person> findByLastname(String lastName); } Person p = new Person("John", "Doe"); personRepository.save(p); Person p2 = personRepository.findOne(p.getId()); List<Person> johnDoes = personRepository.findByLastname("Doe"); assertEquals(1, johnDoes.size()); Slide 25
  • 26. Example Mongo Repository config <bean> <mongo:repositories base-package="net.chrisrichardson.mongodb.example.mongorepository" mongo-template-ref="mongoTemplate" /> </beans> Scans classpath looking for subtypes of MongoRepository in the base package Slide 26
  • 27. Richer mapping Annotations define mapping: @Document, @Id, @Indexed, @PersistanceConstructor, @Document @CompoundIndex, @DBRef, public class Person { @GeoSpatialIndexed, @Value @Id Map fields instead of properties " private ObjectId id; no getters or setters required private String firstname; Non-default constructor @Indexed private String lastname; Index generation @PersistenceConstructor public Person(String firstname, String lastname) { this.firstname = firstname; this.lastname = lastname; } …. } Slide 27
  • 28. Richer mapping configuration @Configuration public class MongoExampleConfig extends AbstractMongoConfiguration { … @Override public MongoTemplate mongoTemplate() throws Exception { return new MongoTemplate(mongo(), mongoDbDatabase, null, mappingMongoConverter()); } @Override public String getMappingBasePackage() { return Person.class.getPackage().getName(); } } Slide 28
  • 29. Support for the QueryDSL project Generated from Type-safe domain model class composable queries QPerson person = QPerson.person; Predicate predicate = person.homeAddress.street1.eq("1 High Street") .and(person.firstname.eq("John")) List<Person> people = personRepository.findAll(predicate); assertEquals(1, people.size()); assertPersonEquals(p, people.get(0)); Slide 29
  • 30. Cross-store/polyglot persistence Person person = new Person(…); @Entity public class Person { entityManager.persist(person); // In Database @Id private Long id; Person p2 = entityManager.find(…) private String firstname; private String lastname; // In MongoDB @RelatedDocument private Address address; { "_id" : ObjectId(”….."), "_entity_id" : NumberLong(1), "_entity_class" : "net.. Person", "_entity_field_name" : "address", "zip" : "94611", "street1" : "1 High Street", …} Slide 30
  • 31. Spring MongoDB – Future Ideas   MongoTemplate !  Support common map-reduce operations from Mongo Cookbook !  GridFS integration   Tighter integration with Spring MVC for activity monitoring !  See current example code on github Slide 31
  • 32. Agenda   Introduction to Spring   Spring Data and MongoDB   Introduction to Grails   Using Grails with MongoDB Slide 32
  • 33. Grails   Open-source web application framework   Uses Groovy – dynamic programming language for the JVM   Builds on mature frameworks such as Spring Slide 33
  • 34. GORM = Grails Object Relational Mapping   Uses convention over configuration !  Defaults for which classes to persist !  Defaults for their O/R mapping   Leverages the meta-object protocol !  Adds persistence methods and properties to domain classes !  No equivalent of Hibernate Session !  Avoids the need for dependency injection !  Eliminates many DAO cookie-cutter methods Slide 34
  • 35. Database access made easy customer class Customer { <<table>> String name id <<pk>> } version name Customer c = new Customer("John Doe") if (!c.save()) fail "validation failed: ${c.errors}" GORM adds Methods and Customer c2 = Customer.get(c.id) properties to class at runtime c2.delete() assertNull Customer.get(c.id) def customers = Customer.findAllByName(“Fred”) Slide 35
  • 36. Relationships don’t have to be difficult customer class Customer { <<table>> String name id <<pk>> static hasMany = [ accounts : Account] version } name class Account { account static belongsTo = [customer: Customer] <<table>> double balance id <<pk>> } version customer <<fk>> Customer c = <…> balance Account a = new Account(…) c.addToAccounts(a) assertSame c, a.customer assertTrue c.accounts.contains(a) Slide 36
  • 37. When the defaults aren’t right class Customer { static transients = ["networth"] static mapping = { id column: 'customer_id' crc_customer <<table>> table 'crc_customer' columns { customer_id <<pk>> version name column: 'customer_name' customer_name } } def getNetworth() { …} … } Slide 37
  • 38. Agenda   Introduction to Spring   Spring Data and MongoDB   Introduction to Grails   Using Grails with MongoDB Slide 38
  • 39. GORM for MongoDB   Extends GORM to support MongoDB   Announced Nov 2010   Currently 1.0M5   Builds on !  Spring Data for MongoDB !  Spring Data Mapping Slide 39
  • 40. GORM/MongoDB example grails uninstall-plugin hibernate grails install-plugin mongodb class Customer { String name Unchanged Address address static hasMany = [ accounts : Account] static embedded = ['address'] } class Address { String street class Account { String city static belongsTo = [customer: Customer] String state double balance String zip } } DataSource.groovy mongo { host = "localhost" } Slide 40
  • 41. GORM/MongoDB example > db.customer.find() { "_id" : NumberLong(24), "address" : { "city" : "Oakland", "state" : "CA", "street" : "1 High Street", "zip" : "94619" }, "name" : "John Doe" } { "_id" : NumberLong(25), "address" : { "city" : "Oakland", "state" : "CA", "street" : "101 Broadway", "zip" : "94619" }, "name" : "Mary Jane" } > db.account.find() { "_id" : NumberLong(1), "balance" : 60, "customer" : NumberLong(24), "name" : "Checking" } { "_id" : NumberLong(2), "balance" : 100, "customer" : NumberLong(24), "name" : "Savings" } { "_id" : NumberLong(3), "balance" : 0, "customer" : NumberLong(25), "name" : "Checking" }   Domain class $ Collection   Property $ Attribute   Relationship $ "FK attribute" Slide 41
  • 42. Cloud Foundry supports Mongo   MongoDB is one of the provided services " Deploy your MongoDB applications in seconds Slide 42
  • 43. Summary   Polyglot persistence is here to stay   Spring Data is here to help you   GORM let’s you use the familiar and powerful GORM API with MongoDB   Deploy your Mongo application on CloudFoundry.com   More info at !  http://www.springframework.org/spring-data !  http://www.cloudfoundry.com/ Slide 43
  • 44. Next steps Checkout Spring Data Consider contributing Deploy on CloudFoundry.com My contact information chris.richardson@springsource.com Twitter: @crichardson Slide 44