all that jazz

james' blog about scala and all that jazz

JPA 2.0 - Early Review

A few days ago, JSR-317, the specification request for JPA 2.0, released an early draft review of the specification. Today I had the chance to skim through it to see what new things it had to offer.

Something I commented on in an earlier blog post was how they might implement deleting orphan members of an association. Would they follow TopLink's private collection mapping, or use Hibernate's additional delete orphan cascade type? It turns out, they chose neither... or rather, they met half way. The EDR specifies the addition of a boolean orphanRemoval attribute on the @OneToMany and @OneToOne annotations. So the terminology follows the Hibernate orphan terminology, however hibernate uses a DELETE_ORPHAN cascade type. The method though is more similar to TopLink, which has private ownership as a property of a collection mapping.

I don't think that I like this way of doing it. I don't think it's consistent, if I want a new entity to be persisted just by adding it to a collection, then I specify cascade=PERSIST. But if I want an existing entity to be deleted just by removing it from a collection, then I specify orphanRemoval=true. Cascading persistence to members added to collections and removing orphaned elements are both similar operations, in that they indirectly change the life cycle state of an entity, that occur at flush time, in a cascade like manner. I think it would be more consistent to say cascade=ORPHAN_REMOVE. The expert group has made a note in the EDR asking for input on which strategy they should use.

Fair Trade Coffee in the Sydney CBD

I've chosen the title of this blog post very deliberately because I want people who are looking for fair trade coffee in the Sydney CBD to be able to find something when they search Google for it.

Fair Trade Logo

I started working in the city a week ago, and one of my first tasks has been to find a coffee shop that sells fair trade coffee. Of course, there are the big chains, including Starbucks, which incidentally is participating in fair trade fortnight in May, and Jamaica Blue, with its fair trade blend. But neither of those is really that close to my office, and I've never really liked the coffee from the big chains as much as I do from the small cafes. So I did a search in Google to see what I could find.

I was quite disappointed. I couldn't find any lists of cafes anywhere, apart from the Oxfam website, and the Fair Trade Association website. And the only cafes in the CBD they had were Starbucks and Jamaica Blue.

After searching a little harder, I found the voodoo coffee company, which supplies a number of cafes in the Sydney CBD, and they have a fair trade blend. I've emailed them asking them which stores they sell fair trade coffee to, but I read that on occasion, Pulse Cafe on Kent Street (right near my work) has sold the fair trade blend.

Does anyone know of any other cafes in the Sydney CBD that sell fair trade coffee?

Update

I tried out Pulse this morning, and found that they only sell fair trade coffee. Not only that, but the coffee was really good, and only $2.50. So my mission is accomplished. However feel free to add comments of other fair trade coffee places you know of so we can make a comprehensive list.

JSR-666 Extension: Significant whitespace

In many software development teams that I've worked on, code reviews are done by printing out the code to be reviewed. This is in turn read and scribbled on with red ink by developers suffering from a delusion that their coding standard is better than mine. An example of some such code:

public boolean equals(Object o)
{
   try
   {
      if (Calendar.getInstance().get(Calendar.MONTH) == 1
            && Calendar.getInstance().get(Calendar.DATE) == 29)
      {
         return true;
      }
      else
      {
         Thread.sleep(10000);
         return new Random().nextBoolean();
      }
   }
   catch (Throwable t)
   {
      // Something must have gone wrong, try again
      return new Random().nextBoolean();
   }
}

When reading the above code, the obvious problem that jumps out is that it contains no less than ten curly braces. When printed for a code review, this is a waste of valuable ink. The squids of the world have been working overtime to provide the ink needed to print out all the code that needs to be reviewed, it is about time we gave them a break. I'd therefore like to propose to the JSR-666 expert group an extension that curly braces be replaced with significant whitespace.

The previous code example would become:

public boolean equals(Object o)
   try
      if (Calendar.getInstance().get(Calendar.MONTH) == 1
            && Calendar.getInstance().get(Calendar.DATE) == 29)
         return true;
      else
         Thread.sleep(10000);
         return new Random().nextBoolean();
   catch (Throwable t)
      // Something must have gone wrong, try again
      return new Random().nextBoolean();

A fine piece of code that would pass any code review.

This feature will also solve a number of other problems, for example, it will eliminate the age old argument over whether braces belong on a newline or not. It will also force developers to write neatly structured code.

This feature will not require any JVM changes, but will require compiler changes. Existing code may need to be changed, however, if the existing code was well formatted to begin with, it should suffice to simply run the following command in vim:

:%s/\{|\}//g

JPA 2.0 - New features - Part 1

In my previous blog post I wrote about asking the JPA presenter at the Sun Tech Days if JPA will support collections of basic types. I've now done some research of my own and found that most of the features that I miss most in JPA, compared to Hibernate, will be in JPA.

Let me start by saying that the first version of the Java Persistence API is excellent. Standardising three major competing vendors of ORM technologies, Hibernate, JDO and Toplink, into one standard would have been by no means an easy task. It certainly would have been an easy way out for the expert group to produce an API that included only the features they could agree on, but did not include many of the fundamental features of an ORM framework. I feel however that all the core aspects of ORM concepts have been addressed, the things that were left out were not essential. This is where JPA 2.0 comes in. Now that JPA has gained industry acceptance, it is time to fill the standard out, include all those nice to have features and clean it up around the edges.

The JPA 2.0 specification has yet to be proposed as a JSR, so nothing that I'm about to mention is definitely going to be in there. All of the information I'm providing is based on presentations that I've read given by the people who will be involved in specifying JPA 2.0.

Collections of basic and embedded types

This is the feature that I most miss whenever I use JPA. I can understand why it may not have been seen as essential to be included in JPA initially, collections of basic types is not strictly an object oriented concept, because basic types are not objects. Nevertheless, in practice it is data structure frequently used both in relational databases and in object oriented models.

An example might be tags in a blog. A tag would not be considered an object, it is simply a keyword used to index blog entries. The same tag may be applied to multiple blog entries, but if it were removed from all of these blog entries, it would no longer exist in any form. The concept of a tag is therefore not an object, and hence it would not make sense to map tags as entities in themselves. Rather, each blog entry would have a set of Strings. Using hibernate extensions, this is currently how it's done:

@CollectionOfElements
private Set tags;

This can similarly be mapped in TopLink using @BasicCollection.

Unidirectional one to many

A feature that follows on from collections of basic types, and would also be very helpful in collections of entities, is unidirectional one to many associations. JPA currently only supports one to many associations as the inverse end of a many to one association, so the owning side of the association is the many side, and never the one side. What this means, is if you have a BlogEntry entity, and it has a list of Comment entities, you can't add or remove comments from the blog by operating on the comment list, you have to do it by setting or nullifying the blog property on each comment.

For example, the following code can't be used to add or remove comments from the blog entry:

blogEntry.getComments().add(comment1);
blogEntry.getComments().remove(comment2);

Rather, it has to be done as follows:

comment1.setBlogEntry(blogEntry);
comment2.setBlogEntry(null);

This is definitely the easier feature to map to databases, as relationships in a database are always owned by the many table. The many table will have a column, say blog_entry_id, that is a foreign key to the primary key of the blog_entry table. However, this is not how we like to view things in an object oriented world. A blog entry is composed of, among other things, comments. Without a blog entry instance, a comment instance does not conceptually exist, nor does it make sense to ever use the comment outside of the context of using the blog entry. In this situation, the sensible mapping is to have the blog entry as the owning side, with no reference from the comment to the blog entry. Comments then only ever get accessed through accessing the entry first, and get created and removed from the blog entry via operating on the comment list.

A related question I have that is not clear from my research is whether JPA 2.0 will support Hibernate's delete orphan cascade type, or TopLink's private ownership feature, or something different. Both achieve the same goal but through quite different methods.

Indexed lists

A further feature that follows on from the above two is indexed lists. Seeing as JPA can only support the many side being the owner of an association, the many side also has to be where order is lists is managed. This means adding a property to our Comment entity, we'll call it index. If it's a bidirectional relationship, the order of the returned list can be set by specifying index as the property to order the comments by. Now, if I wanted to move the fifth comment to the top of the comment list, if the one side was the owning side, it would be as simple as:

comments.add(0, comments.remove(4));

However, because the owning side is the many side, it has to be done like this:

for (int i = 0; i < 4; i++)
{
    comments.get(i).setIndex(i + 1);
}
comments.get(4).setIndex(0);
comments.add(0, comments.remove(4));

Note that the last line there is not absolutely necessary, but keeps the comments list is sync with the index properties, should the list want to be continued to be used.

If JPA 2.0 can support unidirectional one to many associations, it will need to also be able to manage the index of the list on the one side, meaning that it will persist any changes made to the list order to the database, so that the first example above will be all that's needed to move the fifth comment to the top of the list.

Sun on JPA

A few weeks ago I attended the Sun Tech Days in Sydney. I was pretty impressed with the breakfast they provided. In fact, all the food was great. The whole place had a really geeky feel to it, and I really liked that too. However, the presentations left me feeling that the whole thing was a waste of time. To be fair, some of the presentations were good. It was excellent to hear James Gosling. But the majority of the presentations I went to were terrible.

I don't think my standards are too high in having this gripe, at one level, Sun provided me with free food and a day where I could mix with like minded people, I shouldn't be complaining. But it just frustrated me so much because Sun could have done so much more for not only me, but also themselves at this event. The whole event is one gigantic sales pitch, and I'm ok with that. I want Sun to get me excited about their products, I want Sun to get me excited about Java development, I want Sun to pitch their best sales pitch at me, do their best to make me want to drop everything that is not Sun, and follow them. Not that I would necessarily do that, but I at least want Sun to sell themselves to me if I go to an event like this. But I think they failed to do that. I'm going to use one particular session, the session on JPA, as an example of how they missed the mark, but most of the sessions I felt were the same.

My expectations from the JPA session were that Sun would sell me JPA. I love Hibernate, I use it for all my database access, I know how it works intimately, and I am very quick to recommend it as the best tool for ORM to every man and his dog. The big problem for me is that part of my reason for loving it is based in my ignorance, I've only briefly touched JPA, and I've never used Toplink or JDO, they could all be miles ahead of Hibernate, but I wouldn't know. This is why I went to JPA session. I wanted to be given reasons why I should try it, I wanted to be given insights into the future of JPA that will make it the best ORM API to use. So when the session ended up being JPA101 - This is how to map an entity with annotations, this is how to do inheritance, this is how to write a query in JPAQL, you can imagine my disappointment.

I'm not sure who Sun is expecting to come to their tech days. But I'll take a guess at the sort of people that do come. For a start, they are people that take an interest in modern Java frameworks, if they weren't, they wouldn't be at the days. They are developers, if they aren't developers then they definitely wouldn't be interested in JPA101 anyway. And they're people that take the initiative to do research and learn about new technologies themselves, otherwise they wouldn't have found out about the tech days to start with. So, I would expect the people described above to have all had experience with at least one of the leading ORM tools. A JPA101 would have been way too simple for almost the entire audience.

In want of more meat on JPA, I asked a question about the future of JPA. "Is it likely that in the future JPA will support collections of basic types, eg Strings, Integers, Dates?". I was shocked by the presenters response. It wasn't that he didn't know the answer to the question, he didn't understand the question. After asking me to repeat the question, he said "well, it does support it". I said no it doesn't, and someone else in the audience piped up and agreed with me, adding that you could map collections of basic types using TopLink or Hibernate extensions. To which the presenter replied "there's your answer". The presenter had no idea. Anyone with real world experience in an ORM tool would have encountered a time when they would have wanted a collection of basic types, and an expert in JPA would know that JPA doesn't support this. I wanted to know why it doesn't support it, maybe there's a good reason, maybe they felt there were difficulties in how to specify it and so left it for the next release. This guy clearly was not an expert in JPA, and clearly had never used JPA in the real world. I doubt if he had any experience beyond learning enough to give the presentation, it's likely that someone else wrote the presentation and he just went off that persons notes.

So I was very disappointed overall with the Sun Tech Days. It was marketed at professionals, but most of the sessions were targeted at newbies. I hope there's someone at Sun that understands JPA, if they can't get that person to give a presentation, maybe they should look into getting local respected industry professionals to give the presentations, that would be a lot more helpful. Until Sun does that, I don't think I'll return.

About

Hi! My name is James Roper, and I am a software developer with a particular interest in open source development and trying new things. I program in Scala, Java, Go, PHP, Python and Javascript, and I work for Lightbend as the architect of Kalix. I also have a full life outside the world of IT, enjoy playing a variety of musical instruments and sports, and currently I live in Canberra.