Good issues have good titles
Door Gert-Jan van de Streek / sep 2012 / 1 Min
Door Robin van Breukelen / / 3 min
A year ago we started on the new MoreApp platform. Its predecessor was more of a proof of concept that was sold to some customers. It was time to build a stable, better performing and more user-friendly application that would be ready for the next phase of the product. Since then, we’ve had to make some (technological) choices, and I’d like to take a moment to review some of them so that you might benefit from it, should you ever be in a situation that we were in a year ago.
One of the most fundamental choices we’ve made is the way we store our data. Our product lets users create their own forms. So the underlying data model can vary quite a bit from form to form. In combination with that, we didn’t want to have to hassle with large schema updates that were bound to come since the product would be under heavy development. To support this, we went for a schema-free database. There was already some knowledge in the team on MongoDB so we gave that a try and we haven’t had to look back since. MongoDB gives us the ability to store data in any schema we want, it’s very fast and most importantly: we understand the way it works because of the free trainings that are offered at MongoDB University.
We started out with a simple setup: our Java application would connect through the MongoDB Java driver to our database. This worked well for some time but eventually the verbosity of the Java driver drove us nuts. We would have code like this:
DBObject customerIdMatchObject = BasicDBObjectBuilder.start().add("$in", Arrays.asList(customerId != null ? customerId.toString() : null)).get();
DBObject query = BasicDBObjectBuilder.start()
.add("username", new BasicDBObject("$regex", username)
.append("$options", "i"))
.add("$or", Arrays.asList(
BasicDBObjectBuilder.start("roles.CUSTOMER_USER", customerIdMatchObject).get(),
BasicDBObjectBuilder.start("roles.CUSTOMER_ADMIN", customerIdMatchObject).get()
)).get();
return findOneUser(query);
You can imagine that using the BasicDBObject more complex queries got very unreadable very fast, while the actual query really wasn’t that hard to read. Also, we couldn’t easily copy a query that would happen in the application and paste it in the Mongo shell. So, we ended up using Jongo, this allowed us to write much friendlier queries that were nearly synonymous to the Mongo shell, such as:
User user = usersCollection.findOne("{ username : " +
"{$regex : #, $options : #}, " +
"$or: [ " +
" { roles.CUSTOMER_USER : { $in : #} }, " +
" { roles.CUSTOMER_ADMIN : { $in : # } }" +
"]" +
"}",
username,
"i",
Arrays.asList(customerId != null ? customerId.toString() : null),
Arrays.asList(customerId != null ? customerId.toString() : null)).as(User.class);
return findOneUser(user);
Above code is the same piece as before, but it’s much more readable, and this can be pasted into the Mongo shell, substitute some values and Bob’s your uncle.
Another thing we’ve had to decide on was e-mails. Sending an e-mail isn’t that hard if you keep it basic. The first version of our product used its own SMTP server, which worked ok, but our users got the ability to create their own e-mail templates and marketing wanted to send periodic e-mails as well. So the requirements changed and we revised this solution. We tried Google Mail for a while, but it has pretty strong restrictions (you can pay off these restrictions undoubtedly) so we looked on and eventually came across Mandrill. Mandrill is the e-mail sending platform that is used by MailChimp. It offers friendly pricing (12,000 e-mails monthly for free), seamless integration with MailChimp and great reporting. By using Mandrill we’ve really eliminated some potential headaches. If we want to, we can resend e-mails and we can be sure that if we’ve delivered that API call to Mandrill, the mail was sent. An extra bonus was the MailChimp integration, our marketing department can now edit our mail templates as they see fit without having to rely on developers.
So we’ve made some choices that we’re still very happy with, but we’ve also had some “not so hot choices”, one particular I’d like to cover is PDF generation.
If you Google for Java PDF generation you’ll definitely come across iText. It can create some pretty amazing PDFs. In our case however, the PDFs are made through a template editor by our users. iText has something called the XmlWorder that can take HTML and convert it to a PDF, one big caveat though, its CSS compliance is somewhat.. lacking, needless to say: we hit the boundaries of what is possible quickly enough. At first we tried to work around it, but we came to the conclusion that iText would not bring to the table what our users were asking of us.
The alternative we now use is WKHTMLTOPDF and it works very nice, another alternative to consider is DomPDF, it’s PHP based though.
Of course there are many choices we’ve made during our journey, I might cover those in another article some time.
|
Door Robin van Breukelen / okt 2024
Dan denken we dat dit ook wat voor jou is.