How to get rid of Transfer Objects with EJB3 JPA? (Hint: Deprecate the Stateless Architecture!)

Diego Parrilla recently wrote in his blog: “Yes, we still need Transfer Objects with EJB3 JPA”. I think he raised a lot of interesting and valid pionts on the issues we face using EJB3 entity bean POJOs in the web tier. However, I think the answer is also simple: Use a web framework that is designed for the ORM backend! I understand that it is not entirely feasible since many developers have no control over what web framework they choose. But if you do, using a stateful framework like JBoss Seam would completely eliminate the need of DTOs and save you A LOT of trouble.

One of the biggest complaints Diego had was that the web tier cannot lazy load associated objects once the transaction is finished in the business tier. And that forces him to eager load everything and causes a lot of management / performance problems. In fact, this is also one of the most common complaints we heard from Spring / Hibernate users. The problem is that business tier is “stateless” and it closes the database transaction after it passes the object off to the web tier — hence preventing lazy loading in the web tier.

The extended persistence context in EJB3 is designed to solve this problem (yes, the “experts” did think of this :)). With the extended persistence context, the ORM POJO’s lifecycle is extended beyond the business layer transaction. So, you can lazy load anything as long as you do not destroy the context. But it is only useful when used in a EJB3 stateful session bean, which holds the context. JBoss Seam supports EJB3 stateful session bean as one of its basic constructs, and therefore supports lazy loading in web tier out-of-the-box.


Check it out!

6 Responses to “How to get rid of Transfer Objects with EJB3 JPA? (Hint: Deprecate the Stateless Architecture!)”

  1. Diego Parrilla Says:

    I think SEAM can help, but I guess it does not fit with the projects I’m working because:

    1) we want to split physically the EJBs running in JBOSS and the Web app running in TOMCAT. Why? We have identified that AJAX applications increase dramatically the number of hits to the Servlet container (obvious) but most of these request returns Read Only data, hence easy cacheable to avoid unnecesary requests to the middlelayer and the database. So the ratio of JVM running TOMCAT and JVM running JBOSS can be 3 to 1 or 5 to 1 (in my projects, of course, this is not a rule of thumb). Also, we push the use of JMS as resource contention manager in the middle layer: web developers does not need to know about JMS inners.

    2) Stateful architectures are not evil, but they are harder to scale than Stateless architecture. I’m not quite sure of this assertion nowadays, but I like to be conservative when building highly scalable architectures.

    Please correct me if I’m wrong with some of my opinions.
    Thank very much for your feedback.

  2. Michael Yuan Says:

    Hi Diego,

    Yes I understand that there are many factors you need to evaluate when choosing an architecture. But performance should not be a problem here. :)

    1. You can always run Ajax servlets in separate Tomcat servers, but at the same time, you can generate all dynamic web pages in a JBoss container. Of course, I am not familiar your architecture (e.g., I do not know how much caching / DB saving you need from Ajax servlets). So, maybe DTO is an okay trade-off in your situation. :)

    2. “Modern” stateful architecture is is built on the same clustering technology as the HTTP session clustering. So, it should be at least as scalable as stateless + HTTP session. :)

  3. Gavin Says:

    Exactly right, Michael, this problem was definitely anticipated and fixed by EJB3 and Seam. The solution is an extended persistence context with conversational scope.

    By the way, the new release of Seam (due out this month) is optimized for use in an Ajax-based environment with many fine-grained, concurrent, asynchronous requests in the same session/conversation. In this kind of environment you absolutely *need* a stateful (and threadsafe) middle tier to avoid database traffic on every fine-grained request. (Traditional web application architectures not only suck at state management, they also suck at concurrency management.)

  4. Michael Yuan Says:

    Thanks Gavin. I really look forward to Seam 1.1!

  5. Toddius Zho Says:

    What if you want the same Business Object to also handle stateless Web Services? Would your answer be to use SEAM to back the Web Service as well, and now make them *stateful* Web Services?

    I don’t understand how SEAM can afford to maintain conversational state for thousands of concurrent users. If we are lazy-loading, how does a Conversation magically save me a round-trip to the database when traversing to a finer granularity? If the data was already out-of-the-database and held by the Conversation, then how can one still call that lazy-loading? Just because the web tier didn’t get it yet?

    Where do we incur most of the expense? Getting data out of the table in the first place? Or the later transformation into something the web tier can use?

    What if my application is almost all read-only, yet highly personalized for the logged in user? Virtually none of the information is shareable! immutable != shareable. Middle-tier caching now *hinders* my application, not help it.

  6. Michael Yuan Says:

    Hi Toddius,

    I probably need to write another blog entry to properly address you questions. But here are some short answers: The key thing about Seam is that it offers “flexibility”. Seam does provide support for stateless components and eager loading of data. So, if that is what you decide best for your application, you can use it with Seam. However, what if you *also* want to lazy load some data? Seam helps you do it correctly and efficiently.

    You are right that lazy loading requires more round trips to the database, but without lazy loading, you might end up loading a big chunk of your entire database in one entity object if you have a complex schema. So, the performances pros and cons are all relative, you have to judge it for your own application.

    On the other hand, Seam’s stateful approach *reduces* database round trips by only flushing changes to the database at the end of each conversation. That is certainly useful if you read/write your DB a lot.

    You also asked “What if my application is almost all read-only, yet highly personalized for the logged in user?”. Now how do you develop such apps in the past? Do you push all stateful data into HTTP session? Seam manages the exact same amount of stateful data. So there is no performance / scalability loss. On the contrary, since Seam guard against memory leaks associated with long life HTTP sessions, you have significantly lower risk for memory leak in such applications with Seam.

    cheers
    Michael

Leave a Reply