Skip to main content

skip to main content

developerWorks  >  Java technology  >

A taste of "Bitter Java": The Round-Tripping antipattern

developerWorks

Return to article

Early one night, I was watching my two daughters pick up their toys. My two-year-old plodded faithfully through this task, picking up a single toy in the middle of the room, and carrying it to the toy box against the wall. My five-year-old tried my patience by watching TV. Just when I was about to turn off the TV, the show broke for a commercial. She sprang up from the couch, swept all of her toys into a basket, flew across the room, and then slung them all into the toy box at once. Amused at the scene, I turned back to my youngest, plodding faithfully through her task, one toy at a time.

Problem: Too many discrete communications

As a consultant, I observe too many applications that resemble my plodding younger daughter. Round-tripping involves an application that does some repetitive task over an expensive interface like a distributed boundary. This antipattern afflicts many different types of Java programs. Database applications often do filtering, joins, and computation in the application, forcing too many communications with the database server. Applets can do server-side validation by processing each field individually. Persistence frameworks can force data searches in the application instead of the database engine that would be many times more efficient. User interface frameworks often force a distributed communication for every element, such as an entry field or pick-lists.

Consider an EJB application. Figure 1 shows the model for an application that displays invoices. To solve the problem, a developer decides to use a JSP page that communicates directly with remote EJB entity beans. Keep in mind that articles and books warn against this approach, but many tools actually encourage this type of EJB development.


Figure 1. Model for Invoice application
Invoice model.

It might not be immediately apparent, but this design shows a classic round-tripping scenario. A good visual aid for detecting round-tripping is the sequence diagram, as shown in Figure 2. This sequence diagram describes the flow between the user interface and our invoice application. If we deploy the EJB container and the JSP container on separate boxes, then we'll have a round-tripping problem. Note that we have many communications between the JSP and the EJB model. With the sequence diagram, you can easily see the potential problem, but let's dive down into more detail.


Figure 2. This sequence diagram shows round-tripping.
Sequence diagram.

Consider a scenario in which a JSP page displays an invoice. The application fetches the invoice containing two fields and several composite items: two customers (the billing and ship-to address) and a list of items (each with a quantity and a product). The following table calculates the required number of round trips, which turns out to be 10 + 4N, where N is the number of products on the invoice.

ObjectContents# of round-tripsTotal # of round trips
Invoice Id
Date
Customers
Items
1 +
      1 +
            8 +
                  4N =



10+4N
Customer Name
ID
Addresses
1 +
      1 +
            6 =


8
Addresses
  (for 2 addresses)
Id
Street
City
2 +
      2 +
            2 =


6
Items
  (for N items)
Quantity
Products
1N +
      3N =

4N
Products
  (for N items)
ID
Name
Price
1N +
      1N +
            1N =


3N

That may not seem like a very high number, but let's do a little math. For a single invoice with 20 items, that translates to 10+4(20), or 90 round trips for 4.5 seconds. Keep in mind that we are considering only the communications costs. Ouch. Now, consider the case of choosing one of many invoices. As we suspected from our sequence diagram, the costs quickly become unmanageable. Fetch just 10 invoices, and we're waiting 45 seconds. Clearly, we've got to refactor.

Refactored solution: Use a facade

As you probably know, the secret to dealing with EJB entity beans is to batch many of the repeated operations together into a single command. For EJB components, the common way to accomplish this task is with a facade, which is simply an alternate interface. Like my older daughter's basket, a facade can combine many small trips, like product numbers or customer names, to a request for one larger composite object, like a whole invoice or a list of invoices. While the number of transferred bytes remains the same, the facade dramatically reduces the total number of round trips and the associated communications cost. With EJB implementations, you build a facade with a session bean that returns serialized objects.

Figure 3 shows our revised sequence diagram.


Figure 3. Sequence diagram with less round-tripping
Invoice model

At the Web application server, the JSP page makes a single request to the facade layer. On the server side, the facade code makes all of the individual calls to build a single invoice, which it serializes and returns to the client. At the enterprise server, the facade then locally queries the entity beans and builds a serialized object, which the facade serializes and returns to the requesting servlet. Figure 3 shows a facade in action. Notice that we shift the remote interface boundary so that we only have a single distributed communication to get the entire invoice. Of course, we could add an interface to return a collection of invoices.

Despite many excellent sources showing the danger of accessing entity beans directly from a client, the Round-Tripping antipattern ensnares many Java programmers. These tips can help you detect problems early and steer clear:

  • Investigate and use successful design patterns when dealing with distributed systems like EJB components. Though a framework may handle the details, you should still know distributed computing fundamentals.

  • Use sequence diagrams to detect and troubleshoot chatty interfaces over expensive boundaries.

  • Consolidate many isolated requests into logical groupings.

Of course, our ultimate goal is to eliminate unnecessary round trips. The facade strategy does so by making each round trip more productive. Other strategies can also help. Caches can eliminate round trips for data that's already been retrieved. Fetch-ahead strategies can retrieve multiple data rows per block, anticipating multiple usages. Regardless of your chosen strategy, the bottom line is that distributed communications are expensive. Make them count.

Return to article