jump to navigation

From J2EE to Django: Observations from Porting a Web App 8 July 2009

Posted by manniwood in Django, J2EE, Java.
trackback

I ported a database-backed web application from Java Servlets to Python/Django, and I’m so very happy that I did. I was nearing the end of work on a medium-sized web app when one of my programmers left for greener pastures. I decided that I could make up for the missing programmer by porting our J2EE app to Python, and then finish adding the final features to the Python port. The assumption was that Python would make me so much more productive that I’d finish faster even including the porting time.

It turns out I was right.

If you’ve taken to reading my blog at all, you’ll know that I love RDBMSs, and that my application designs use the RDBMs as the final arbiter of what the application’s data model is. So really, I wasn’t translating a huge amount of code for my port, because I could leave the database alone.

Of course, because I think the database is king, I opted out of using Django’s ORM on top of my carefully designed database. Instead, I ported iBATIS (which I was using in my J2EE version) to Pybatis, and used that for all of my database access needs.

I originally wanted to make Django’s templating system work with Pybatis (and maybe I still will some day), but I could not find an easy way to make Django’s templating system run well outside of Django, and I wanted Pybatis to be able to run in Python apps that were not neccesarily Django-based. So, I turned to the Jinja 2 templating engine, and liked it so much that I am now using it in both Pybatis and my Django app.

You may wonder what parts of Django this leaves behind, but, in my opinion, the parts of Django that I’m using are the parts that I had no desire to write. I love the way Django maps urls to functions, for instance.

I love the way Django renders templates to the browser. There’s no complicated forwarding from servlet to JSP as there is in Java-land; just a method call to the template engine, which you can hand whatever data structures you need for page rendering. It may sound like a small difference, but somehow, in practice, it’s a big difference. Like many things Java, Servlets and JSPs feel over-architected after using Django.

I also love using mod_wsgi and Apache with Django. It feels like a more natural fit than Apache with Tomcat. My production environment is Linux, so Apache is therefore process-based and not threaded. I prefer processes over threads as a general rule (I agree with Eric Raymond that threads are a performance hack; you can’t always avoid threads, but it’s nice when you can). So getting threaded Tomcat (or any other Servlet container) to talk to process-forked Apache always struck me as a bit of a mismatch.

With Django, there’s no mismatch: through mod_wsgi, each Apache process contains its own Python interpreter, and each Python interpreter contains a single copy of the web app. All kinds of good things come from this. For instance, my Python code does not have to be thread safe: each Apache process handles one request at a time, and each Apache process contains exactly one instance of the web app, so there’s no contention for resources. (Except on the database, but databases are designed to deal with that.)

With this setup, you don’t need connection pooling. Because Apache processes handle one request at a time, and because each process contains its own copy of the web app, each web app instance only needs to be configured with a single connection to the database. You just write your code to use The Connection, and the rest is taken care of for you by Apache’s pre-forking goodness. You just need to configure your database to handle as many open connections as your Apache setup will fork.

So not only does all this feel cleaner and simpler (though perhaps a tad more resource hungry—there are always tradeoffs), it’s also got horizontal scaling built in!

Well, mostly. There’s the problem of sessions. Apparently, Django can be configured to persist session data to shared memory, so that it doesn’t matter which Apache process responds to a user’s request, it has access to that user’s session. I decided to write my own session implementation that persists all session data in the database. (I don’t imagine this would work with large traffic volume, but for our product’s projected traffic volumes, this was fortunately an approach we could take.) That way, it wouldn’t matter if a user established a session on one Apache process and then returned to another Apache process on a different machine in our server farm: with sessions being stored in the database, they would be findable by any Apache process on any machine.

All in all, I’ve been very happy with the switch from J2EE to Django. Although there aren’t always Python equivalent to Java libraries I got used to using, I also found that porting to Python only the parts of Java libraries that I used took very little time.

The realities of the market are such that my next project may be a J2EE project: it’s still the most popular stack, so the opportunity to use Python is not always there. But if I’m in a position to choose, I’ll choose Python. If I’m in a position to offer a recommendation, I’ll recommend Python if I think the library support is there, and the project can benefit from that choice.

Comments»

1. Mwanji Ezana - 8 July 2009

Anything is a lot better than working with raw servlets and JSP! But even the modern Java web frameworks feel much more complex than the dynamic language ones. Even Grails brings in huge amounts of plumbing to present a simple API.

In terms of pure templating, the best Java library I’ve found is Jamon (jamon.org). It has a bunch of the cool features from Django templating like inheritance and the basic invocation API looks like Jinja’s. But it adds in a lot of nifty type-safety. It’s totally unknown, yet so much better than JSP, Velocity, etc.

I’ve been using Jamon, JPA and a servlet to make a sort of custom framework that’s shaping up pretty nicely.

2. Baishampayan Ghose - 11 July 2009

You needn’t have written your own session engine. You could have just set SESSION_ENGINE to ‘django.contrib.sessions.backends.cached_db’ in your settings.py

That uses a write-through cache which persists in the DB and is quite fast.

More here – http://docs.djangoproject.com/en/dev/topics/http/sessions/#configuring-the-session-engine

manniwood - 11 July 2009

Very good point! The only reason why I wrote my own is because I don’t like Django’s ORM (nothing against Django — I don’t like any ORM). Mine uses the same Pybatis configuration/setup as the rest of my webapp. But, for the majority of people using Django’s ORM, your approach would be the way to go.

3. brett - 11 July 2009

JSP is horrible, that’s why I use freemarker or velocity instead. Freemarker is nicer than velocity IMO since like django templates you can do blah then you can output “begin blah end”. With django you can do this with placeholders. Define a placeholder then in another template, override it and fill out the placeholder.

I will never get over the fact that java is statically typed thus I will always prefer it in that sense although I like the easy by which I can write apps in django. But if they get too complex and you start needing to refactor or you need multiple databases, then django actually becomes burdensome. Want I would like is a django framework app but in java. That would be cool because I love how django does things, I’m just not a fan of python.

4. brett - 11 July 2009

…and I should add that hibernate is more advanced than django’s ORM in terms of caching per object or per query for example. But if you use jython then you can use hibernate and django.

5. Reid - 11 July 2009

Django is funny like that. I feel like most of it’s code is in the templates and the ORM, and they’re the pieces of it that people complain about the most and opt to not use the most. All you’re left with after that is the URL conf and middleware stuff which is really easy to write and could live in a much smaller framework.

6. matt - 16 July 2009

The one question I have is, why would you write your own data mapper when a perfectly good one, SqlAlchemy, already exists in the python ecosystem.

manniwood - 16 July 2009

My blog SQL Generation is a Templating Problem, Not a Code Generation Problem mostly answers your question: I liked iBATIS’ way of doing things through templates, not code-generation, so I ported iBATIS to Pybatis, stripping it down even further. I realise SqlAlchemy can be used in a non-ORM way, but it’s too heavy-weight for my tastes.

7. Everything Is an Edge Case: Lessons from Frameworks that I Applied to Django « Manni Wood - 16 July 2009

[...] to Django 16 July 2009 Posted by manniwood in Uncategorized. trackback Commenters on my From J2EE to Django: Observations from Porting a Web App have noted that I don’t use a lot of Django’s capabilities: I wrote my own SQL [...]

8. John O'Hanley - 18 July 2009

Re: ‘the database is king’

The same phrase is used here:
http://www.javapractices.com/topic/TopicAction.do?Id=211

manniwood - 18 July 2009

Fantastic blog entry. It says exactly what I think about 1) the importance of having the data model in the database and 2) how databases should be designed on the assumption that more than one app/process/client will access them, and protect against garbage data entries accordingly.

9. When Was the Last Time You Switched RDBMSs? « Manni Wood - 22 July 2009

[...] fact, if I compare my latest front-end switch to the only back-end switch I’ve ever done, I’d have to say that they were both [...]

10. J2EE Still Rules the Roost « Manni Wood - 19 August 2009

[...] I must say, at the startup where I currently work, switching from J2EE to PythonDjango definitely made a difference with getting our product [...]

11. Stephan Schmidt - 22 September 2009

Good post. Some remarks:

“[...] just a method call to the template engine, which you can hand whatever data structures you need for page rendering.”

Like Freemarker and Velocity in Java. With Jersey and Freemarker your very near your Python setup I’d guess. Take this as a tip for “my next project may be a J2EE project”.

I blocked about the code size of Java vs. Python (2x – 4x).

http://codemonkeyism.com/comparing-java-and-python-is-java-10x-more-verbose-than-python-loc-a-modest-empiric-approach/

Could you share some data on your Java to Django project? (LOC in Java and LOC in Python/Django). Would be great to have more numbers.

Cheers
Stephan

12. Stephan Schmidt - 22 September 2009

Sorry for my typos on your blog :-( Morning and no coffee yet.

your => you’re
blocked => I’ve blogged