mongodb munich 2012: mongodb for official documents in bavaria

36
MongoDB@Bayern Migration from RDBMS, Problems, Unit-Testing

Upload: mongodb

Post on 21-Jun-2015

514 views

Category:

Technology


0 download

DESCRIPTION

Christian Brensing, Senior Developer, State of Bavaria The Bavarian government runs a document template application (RTF or ODF with Groovy, Python, Ruby or Tcl as scripting language) serving different government offices. Having complex and hierarchical data structures to organize the templates, MongoDB was selected to replace the Oracle-based persistence layer. In this talk you will hear about the improvements we have achieved with the migration to MongoDB, problems we had to solve underway and unit testing of the persistence layer in order to keep our quality level.

TRANSCRIPT

Page 1: MongoDB Munich 2012: MongoDB for official documents in Bavaria

MongoDB@BayernMigration from RDBMS, Problems, Unit-Testing

Page 2: MongoDB Munich 2012: MongoDB for official documents in Bavaria

Christian Brensing

Bayerisches Landesamt für Statistik und Datenverarbeitung

IuK / Rechenzentrum Süd

Page 3: MongoDB Munich 2012: MongoDB for official documents in Bavaria

• Template-Processor (~ JSP)

• ODF and RTF

• PDF / PostScript postprocessing

• Groovy, Python, Ruby, Tcl

• In Production using RDBMS since 2008

• Central HR system (SAP) uses BayText to create output

Page 4: MongoDB Munich 2012: MongoDB for official documents in Bavaria

Client for developing the templates (BayText-IDE)

Page 5: MongoDB Munich 2012: MongoDB for official documents in Bavaria

ODF-Template using Ruby

Page 6: MongoDB Munich 2012: MongoDB for official documents in Bavaria

Generated document

Page 7: MongoDB Munich 2012: MongoDB for official documents in Bavaria

2 MillionGenerated documents per year

Page 8: MongoDB Munich 2012: MongoDB for official documents in Bavaria

Tiny dataset50,000 records and 10 GB BLOB

Page 9: MongoDB Munich 2012: MongoDB for official documents in Bavaria

a small system after all

Page 10: MongoDB Munich 2012: MongoDB for official documents in Bavaria

So why migrate?

Page 11: MongoDB Munich 2012: MongoDB for official documents in Bavaria

Because we can

Page 12: MongoDB Munich 2012: MongoDB for official documents in Bavaria

developers.pop()Smaller teams

Page 13: MongoDB Munich 2012: MongoDB for official documents in Bavaria

Easy to learnRead one book and you're done

Page 14: MongoDB Munich 2012: MongoDB for official documents in Bavaria

Simple mapping

Page 15: MongoDB Munich 2012: MongoDB for official documents in Bavaria

nodes

groups

templates

document_usages

folder_configurations

codes

permissions

requests

documents

folders

structures template_tags

roles

roles_roles

bundles

componentsdynafields

scripts

Page 16: MongoDB Munich 2012: MongoDB for official documents in Bavaria

nodes

roles

properties

GridFS

Page 17: MongoDB Munich 2012: MongoDB for official documents in Bavaria

{! "_id" : ObjectId(),! "_type" : "Document",! "updated_at" : ISODate("2007-12-06T10:04:00.543Z"),! "updated_by" : "maggie",! "version" : 1,! "path" : "foo.bar.Document",! "description" : "",! "language" : "ruby",! "format" : "odf",! "autoload_uplevel" : -1,! "requests" : [! {! "name" : "Test",! "description" : "foo", ! "xml" : zlib("<?xml ...?>")! }, ! ... ! ],! "structure" : [! { ! "alias" : "some alias",! "component_path" : "foo.bar.Document$Document",! "parent", -1 ! },! ... ! ], ! } ! "tags" : ["foo", "bar", "baz"]!}

Page 18: MongoDB Munich 2012: MongoDB for official documents in Bavaria

public class RoleReadConverter implements Converter<DBObject, Role> {! @Override! public Role convert(DBObject source) {! Role role = new Role();! role.setName((String) source.get("name"));! ...! return role;! }!}!!!public class RoleWriteConverter implements Converter<Role, DBObject> {! @Override! public DBObject convert(Role source) {! return new BasicDBObject()! .append("name", role.getName())! .append(...);! }!}!!!// Convert a DBObject to an Entity!conversionService.convert(collection.findOne(...));

Easy mapping using Spring-ConversionService

Page 19: MongoDB Munich 2012: MongoDB for official documents in Bavaria

Performanceup to 10x

Page 20: MongoDB Munich 2012: MongoDB for official documents in Bavaria

ORM no moreThe MongoDB driver is all you need

Page 21: MongoDB Munich 2012: MongoDB for official documents in Bavaria

Obstacles?

Page 22: MongoDB Munich 2012: MongoDB for official documents in Bavaria

Mentality

Page 23: MongoDB Munich 2012: MongoDB for official documents in Bavaria

Referential IntegrityMulti-Document-Update on denormalized schema

Page 24: MongoDB Munich 2012: MongoDB for official documents in Bavaria

{! "_id" : ObjectId(),! "_type" : "Folder", ! "updated_at" : ISODate("2007-12-06T10:04:00.543Z"),! "updated_by" : "maggie",! "version" : 1,! "path" : "foo.bar.Folder",! "description" : "bla",! "bundles" : [! ... ! ]! "document_usages" : [! {! "name" : "foo",! "description" : "bla", ! "exec_order" : 5, ! "print_copies" : 2,! "type": "FAIR_COPY",! "document_path" : "a.b.Document",! "bundle" : "bar"! },! ...!}

Linking documents via a path instead of ObjectId

Page 25: MongoDB Munich 2012: MongoDB for official documents in Bavaria

But paths are mutable!All references must be updated

Page 26: MongoDB Munich 2012: MongoDB for official documents in Bavaria

Approach

• Pseudo-Transaction with an update locking mechanism in a custom oplog collection

• Periodical repair jobs finishing failed operations • Extended interpretation of eventual consistency

Page 27: MongoDB Munich 2012: MongoDB for official documents in Bavaria

Unit-TestsContinuous Integration

Page 28: MongoDB Munich 2012: MongoDB for official documents in Bavaria

F.I.R.S.T.

Page 29: MongoDB Munich 2012: MongoDB for official documents in Bavaria

IsolatedTests are using a unique DB per JVM

Page 30: MongoDB Munich 2012: MongoDB for official documents in Bavaria

@Configuration!@Profile("test")!public class TestSpringConfiguration extends SpringConfiguration {! @Override! public void init() {! setTestProperties();! ! super.init();! ! // Delete test db! db().dropDatabase();! }! ! private void setTestProperties() {! String dbname = env.getProperty("db.name", "baytext_test_" + getSimpleUsername());! String host = env.getProperty("db.host", "mongodb-dev.db.rz-sued.bybn.de");! String port = env.getProperty("db.port", "27016");! ! cmProperties.setProperty("servers", String.format("%s:%s", host, port));! cmProperties.setProperty("name", dbname);! }!! // OS-Username without prefix (e.g. maggie instead of lfstad-maggie)! private static String getSimpleUsername() {! String username = SystemUtils.USER_NAME;! int indexOfDash = username.indexOf('-');! return indexOfDash != -1 ? username.substring(indexOfDash + 1) : username;! }!}

Test-ApplicationContext

Page 31: MongoDB Munich 2012: MongoDB for official documents in Bavaria

RepeatableCollections are dropped before each test method

Page 32: MongoDB Munich 2012: MongoDB for official documents in Bavaria

public class MongoTestExcecutionListener extends AbstractTestExecutionListener {! @Override! public void beforeTestMethod(TestContext testContext) throws Exception {! purgeCollections();! }! ! private void purgeCollections() {! DB db = MongoDBHolder.getDB();! for (String collectionName : db.getCollectionNames()) {! if (collectionName.startsWith("fs.") || collectionName.startsWith("system.")) {! continue;! }! DBCollection collection = db.getCollection(collectionName);! if (!collection.isCapped()) {! collection.drop();! }! }! }!}

Spring-TestExecutionListener

Page 33: MongoDB Munich 2012: MongoDB for official documents in Bavaria

@RunWith(SpringJUnit4ClassRunner.class)!@ActiveProfiles({"test"})!@ContextConfiguration(classes = TestSpringConfiguration.class)!@TestExecutionListeners({! DependencyInjectionTestExecutionListener.class,! DirtiesContextTestExecutionListener.class,! MongoTestExcecutionListener.class!})!public abstract class MongoTestSupport {!}!!!!public class DocumentRepositoryTest extends MongoTestSupport {!}!

Test base class

Page 34: MongoDB Munich 2012: MongoDB for official documents in Bavaria

95% Coverage

Page 35: MongoDB Munich 2012: MongoDB for official documents in Bavaria

Summary

• Developing the data layer is fun again • Reduced complexity • Flat learning curve compared to SQL/ORM • use_mongo() unless transactions_required

Page 36: MongoDB Munich 2012: MongoDB for official documents in Bavaria

Thank you!