An Honest Look at Seam – Part 2: The Conversation

Wednesday, March 24th, 2010

This is the second part in a series of posts about the Seam Framework

The next part of Seam I want to look at is the Conversation. A conversation in Seam is one of the new contexts that seam brings to the table. It sits in between the Servlet Request and Session in terms of it’s life in the application. The goal of the conversation context is to fill in the gap scoping objects across a logical set of requests that represent a real user case without having to juggle everything in the session. It also allows you to have multiple “workspaces” of your application on different browser tabs, as each tab can have it’s own set of conversations.

Now, what do you think belongs in this conversation context? An easy win here are Stateful Session Beans. The references to these are a no-brainer for the conversation context as they represent a conversation with the EJB container. We can also put business objects that we are building up as part of a wizard into a conversation. In fact, that is exactly where I want to go, proposing that those objects should be your JPA entities. Here’s why. When you use Hibernate as the persistence mechanism or the JPA provider with Seam, you get some extra goodies for tying the persistence context to the conversation. This feature is best understood in contrast to the way most of us have to work in other frameworks.

In most any other web framework, you would have to look up your JPA entity on the first step of your wizard, and either pass it as a detached entity through the wizard, making a JPA merge call at the end to persist the change, or you can manage and merge the changes yourself. Either way, merges are messy, and either blind to data clobbering or complex to code. Also, the fact that your JPA entity is detached means you can’t traverse the object graph without either getting lazy load exceptions (we all love those) and/or having to re-lookup the entity for each page.

There are two things that Seam does to address this problem. The first is that it binds the entity manager to the conversation, and keeps it open for the life of conversation, across multiple requests and multiple transactions. (Seam still runs with a transaction per request model, but you will see how the conversation works with that by the end of the post). This means that you can keep references to your JPA entities across requests and they don’t get detached. This reduces traffic to the database because you aren’t looking up the data in the database over and over again with each request. You also don’t have to resort to the “Open Session in View” pattern in order to avoid lazy load issues in your view layer.

The second thing Seam does has to do with a special feature in Hibernate. Hibernate implements a additional flush mode for the entity manager beyond JPA’s AUTO and COMMIT, called MANUAL. What it does is tell the entity manager to not flush changes to the database until it is told to, even across transactions. Seam will enable (when you ask it to) the MANUAL flush mode of Hibernate on your conversation scoped entity manager, which means you can modify your entity on the first page of the wizard, carry those changes through, and not have them flush (and thus commit) until the conversation is ended. This is significant because if the conversation never completes, the changes the user made during the wizard are “rolled back” when Seam cleans up the abandoned conversation (which it does for you without you having to worry about it). You get this rollback without having to detach your entities or worry about the data from the wizard ending up in an inconsistent state.

Now, the one caveat to this is that you must use Hibernate to get the Manual flush piece. The other pieces (including the conversation scoped entity manager) are available no matter what JPA provider you use. With that in mind, write to the JPA expert group and tell them you want manual flush to get into the next revision of the spec!

In the next part, we will take a step back from the features and address a question that I have gotten a lot about Seam. “Seam seems to be really complex and big. How do I go about learning it?”

Previous Posts in the series
Part 1: How Seam Builds on Spring

Bookmark and Share

8 Responses to “An Honest Look at Seam – Part 2: The Conversation”

  1. Tweets that mention Matt Campbell's Blog » Blog Archive » An Honest Look at Seam – Part 2: The Conversation -- Topsy.com wrote:
    March 24th, 2010 at 4:54 pm |

    [...] This post was mentioned on Twitter by CityTech, mvanbergen. mvanbergen said: RT @citytech: An Honest Look at Seam – Part 2: The Conversation http://bit.ly/bHPKDf [...]

  2. Arbi Sookazian wrote:
    April 1st, 2010 at 2:24 pm |

    I emailed the EG for JPA and they rejected my case for adding Manual flushMode to the spec. Mike Keith mostly and probably for political reasons, it got a little nasty (of course) with Gavin King in the mix…

    Hopefully it will be added one day…

    SMPC + Hibnerate manual flush = application tx. You keep the persistence context open for the duration of the conversation, thereby avoiding LIEs…

  3. vesuvius wrote:
    April 2nd, 2010 at 4:31 pm |

    What about Adam Bean’s Gateways? (http://www.adam-bien.com/roller/abien/entry/building_perfect_anti_facades_almost)

    Do you think they are a decent replacement for manual flush? Transactions (that is, flushing to the database) can be switched off by default, and only switched on for certain methods.

  4. vesuvius wrote:
    April 3rd, 2010 at 7:41 pm |

    I’m sorry about misspelling Adam Bien’s name in my post above.

    Also, Mike Keith has expressed some of his feeling about FlushModeType.MANUAL here: http://www.eclipse.org/forums/index.php?t=msg&goto=376345&

    I’m not taking sides. I’m just posting the link because it might be interesting.

  5. mcampbell wrote:
    April 5th, 2010 at 10:00 am |

    This is very similar to the pattern suggested by Dan for those who don’t have hibernate for their JPA provider or who are using session beans. The combination of the Stateful session bean with the extended persistence context acheives very similar behavior. The main difference is that you have to manually call the save method. You can take this a step furthur and put your SFSB reference in a conversation scoped variable so that you can bring it along with you across requests.

  6. mcampbell wrote:
    April 5th, 2010 at 10:25 am |

    @vesuvius Mike’s comments are most interesting indeed, and I see his point as being valid. He knocks Seam for using transactions on each request, while still asking for manual flush. The reason Seam does this is that if you do 50 reads outside of a transaction, many databases will operate in auto-commit mode, starting and committing a transaction for each read. If you explicitly use a transaction, you avoid this overhead. Things like this that are done in the name of scalability can, like other performance related issues, not worth worrying about until you actually see an issue and need to make changes to mitigate it. The Gateway pattern you mentioned earlier follows Mr. Keith’s suggestions.

  7. Tweets that mention Matt Campbell's Blog » Blog Archive » An Honest Look at Seam – Part 2: The Conversation -- Topsy.com wrote:
    April 9th, 2010 at 4:06 am |

    [...] This post was mentioned on Twitter by Sai Geetha M N. Sai Geetha M N said: An Honest Look at Seam – Part 2: The Conversation: http://bit.ly/bieAOm via @addthis [...]

  8. vesuvius wrote:
    April 14th, 2010 at 10:14 am |

    If Seam doesn’t automatically join the persistence context to each transaction, then there won’t be any danger of the changes being flushed to the database at commit time.

    We can manually join the persistence context to the transaction, when we are ready to flush. This will be very similar to Adam Bien’s Gateways and to FlushModeType.MANUAL, and it will also work with any JPA provider, not just Hibernate. I have worked with TopLink Essentials before and I generally like it and I don’t wish to be forced to switch to Hibernate simply because Seam is not fully compliant with the standard.

    I realize that the database may start a local transaction for each SELECT statement and this will have some minor effect on performance, but that won’t be such a huge problem, after all. Most people issue separate non-transaction-bound SELECTs in their programs anyway. And as Mike Keith says, “reads may be performed outside a transaction”. So, it seems okay for Seam to provide an option that would switch off the AUTOMATIC joining of the persistence context to the transaction. We should be allowed to do it manually, whenever we want to.

    By the way, I’ve been using the Oracle database for many years, and what they say in the Seam books about transaction isolation isn’t true for Oracle. The default isolation mode, READ COMMITTED, allows for a SELECT statement to produce different results when executed more than once within ONE AND THE SAME transaction, if in the meantime some other session has committed its changes. The isolation mode that guarantees the exact same results is SERIALIZABLE but it’s a real scalability killer and I wouldn’t use it unless I have a very good reason.