• Save
MongoDB for Java Devs with Spring Data - MongoPhilly 2011
 

MongoDB for Java Devs with Spring Data - MongoPhilly 2011

on

  • 15,435 views

 

Statistics

Views

Total Views
15,435
Views on SlideShare
15,434
Embed Views
1

Actions

Likes
22
Downloads
0
Comments
0

1 Embed 1

https://twitter.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

MongoDB for Java Devs with Spring Data - MongoPhilly 2011 MongoDB for Java Devs with Spring Data - MongoPhilly 2011 Presentation Transcript

  • SpringSource and MongoDBChris RichardsonAuthor of POJOs in ActionFounder of CloudFoundry.comChris.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 ecosystemFramework DescriptionSpring framework The foundationSpring.NET .NET port of the Spring frameworkSpring Security (a.k.a. Acegi) Extensible framework providing authentication, authorization and instance-level securitySpring Web Flow An excellent framework for building multi-page flowsSpring Web Services Contract-first, document–centric SOAP web servicesSpring Dynamic Modules for OSGI Deploy Spring applications on OSGISpring Batch Powerful batch processing frameworkSpring Integration Implements enterprise integration patternsSpring BlazeDS integration Support for Adobe BlazeDSSpring AMQP AMQP messaging, i.e. RabbitMQSpring 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 modularAbstractions: implementation ofTransactions, data cross cuttingaccess, … 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@Repositoryclass ActorDaoImpl implements ActorDao { SimpleJdbcTemplate hides@Autowired the low-level, messyprivate SimpleJdbcTemplate simpleJdbcTemplate; details of using JDBCpublic 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@Configurationpublic 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 forexceptions thrown by DataAccess ExceptionDAOs  Consistent exception Concurrency Failure Exception ...handling acrossHibernate, JPA, JDBC, Optimistic LockingFailureetc. Exception Pessimistic LockingFailure Exception  Unchecked exception  Extensible exception CannotSerializemapping: CannotAcquire LockException Transaction ExceptionSqlExceptionTranslator 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
  • MongoTemplateSimplifies data MongoTemplate POJO $ DBObjectaccess databaseName mappingTranslates userId Passwordexceptions 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 entitypublic 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@Repositorypublic 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 Testpublic 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@Repositorypublic 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@Testpublic 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 Repositorypublic 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@Configurationpublic class MongoExampleConfig extends AbstractMongoConfiguration{ … @Override public MongoTemplate mongoTemplate() throws Exception { return new MongoTemplate(mongo(), mongoDbDatabase, null, mappingMongoConverter()); }@Overridepublic String getMappingBasePackage() { return Person.class.getPackage().getName();}} Slide 28
  • Support for the QueryDSL project Generated from Type-safe domain model class composable queriesQPerson 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(…);@Entitypublic 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 customerclass Customer { <<table>> String name id <<pk>> static hasMany = [ accounts : Account] version} nameclass 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 rightclass 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 examplegrails uninstall-plugin hibernategrails install-plugin mongodbclass Customer { String name Unchanged Address address static hasMany = [ accounts : Account] static embedded = [address]} class Address { String streetclass Account { String city static belongsTo = [customer: Customer] String state double balance String zip} }DataSource.groovymongo { 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 inseconds 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