Saturday, January 21, 2012

JPA and Vaadin JPAContainer

I've been finalizing the completely rewritten chapter about Vaadin JPAContainer this week. I still need to check that everything really important is included.

I don't have almost any previous experience with JPA, which is kind of good thing when you write documentation about something. That way, you personally know all the questions a beginner would have.

JPA and ORM in general seem pretty important technologies. Whatever your application is, you most probably need some data storage. Using ordinary files is possible, but not near as handy as proper databases. However, stuffing complex class structures through the square holes of database tables was a hell before the ORM technologies emerged. XML databases and NoSQL were much nicer for structured storage.

Some years ago I did some experiments with related technologies, such as JAXB and Hibernate, but using them was a bit too much effort at that time. Using Hibernate with Vaadin really required a Container implementation, but there wasn't one at that time. Well, JPA is quite close to Hibernate, and Hibernate is currently one of the JPA implementations.

Vaadin JPAContainer makes things really easy.
// Create a persistent person container
JPAContainer<Person> persons =
JPAContainerFactory.make(Person.class, "book-examples");

// You can add entities to the container as well
persons.addEntity(new Person("Marie-Louise Meilleur", 117));

// Bind it to a component
Table personTable = new Table("The Persistent People", persons);
personTable.setVisibleColumns(new String[]{"id","name","age"});
layout.addComponent(personTable);
So, just one command to get a container bound to data in a database table. JPAContainer is, however, just for binding user interface components directly to data. You can use it to add or edit the data, but using pure JPA is much nicer, easier, and more flexible for that.
EntityManager em = JPAContainerFactory.
createEntityManagerForPersistenceUnit("book-examples");
em.getTransaction().begin();
em.createQuery("DELETE FROM Person p").executeUpdate();
em.persist(new Person("Jeanne Calment", 122));
em.persist(new Person("Sarah Knauss", 119));
em.persist(new Person("Lucy Hannah", 117));
em.getTransaction().commit();
Well ok, here we got the entity manager from the JPAContainerFactory, which makes that a bit easier than normally.

JPAContainer is a commercial product. That shouldn't be a problem if you're coding for a company that can pay the license. For free software, you can use the AGPL license. I've always felt that this sort of dual-licensing scheme is most difficult for "potential startups" where you experiment with a business idea, but do not yet have a company to back it up financially. You do not normally have the money to invest in licenses at that point, and a company might not want to invest much in such experiments either.

There are of course alternatives for JPAContainer. Using pure JPA is quite OK approach as well, combined with BeanItemContainer in Vaadin. There's also SQLContainer. It is also something I don't know about, as I didn't write the chapter myself. I would need to review and reorganize it in next weeks though, and possibly rewrite at some point.

Well, I did make a couple of mistakes while writing the JPAContainer chapter. The first one was trying to just update a really complex design documentation written by someone else, in a topic I knew nothing about. Writing is always a learning experience and it's not sensible to try to write about something very complex that you don't have a clue about. Sometimes, it's best to start from scratch. Unfortunately, I didn't do that when I started, but just over a week before the release.

Another issue is learning by doing. I usually start writing documentation by experimenting how it works, making some example code. This time, as I was in a hurry, I tried to skip that phase. I only started it as the last effort when I was totally stuck, some 4 weeks of struggle behind and 2 work days before the release date. Just in those couple of days, all pieces fell into place and I finally understood how everything works.

No comments: