Ajax for Java developers: Java object serialization for AjaxFive ways to serialize data in Ajax applications |
Level: Intermediate Philip McCarthy (philmccarthy@gmail.com), Software Development Consultant, Independent Consultant 04 Oct 2005 If you're doing Java™ Web development using Asynchronous JavaScript and XML (Ajax), then delivering data from the server to the client is probably your top concern. In this second article in the Ajax for Java developers series, Philip McCarthy walks you through five approaches to Java object serialization and gives you all the information you need to choose the data format and technology best suited to your application. In the first article in this series, I introduced you to the building blocks of Ajax:
This time, I'll continue discussing the development fundamentals of Ajax, but I'm focusing on what matters most for many Java Web developers: producing data for the client. Most Java developers have applied the Model-View-Controller (MVC) pattern to their Web applications. In a traditional Web application, the view component is composed of JSPs, or perhaps another presentation technology such as Velocity templates. These presentation components update the user interface by dynamically producing a whole new page of HTML to replace what the user was previously looking at. In the case of a Java Web application with an Ajax UI, however, the JavaScript client code has ultimate responsibility for updating what the user sees, based on data received in response to an This article focuses on the techniques you can use to generate data-centric views of your Java objects. I'll demonstrate a variety of methods you can use to turn your JavaBeans into XML documents, and you'll learn the pros and cons of each. You'll also see why XML is not always the way to go: transferring plain text can be an expedient choice for simple Ajax requests. Finally, I'll introduce you to JavaScript Object Notation (JSON). JSON allows data to be transmitted in the form of serialized JavaScript object graphs that are extremely easy to work with in client-side code. I'll employ one example application and several use cases to illustrate the technology features and techniques discussed here. Figure 1 shows the extremely simple data model that illustrates the example use cases. The model represents a customer's account at an online store. The customer has a collection of previous orders, and each order consists of several items. Figure 1. A simple object model Although
Producing XML from Java classes There are plenty of reasons to deliver Ajax responses as XML: every Ajax-capable browser has methods for navigating XML documents, and there are many server-side technologies for working with XML data. It's easy to define the contract between your Ajax client and server by producing a schema to describe the types of documents that will be exchanged, and if you take a service-oriented approach to your server-side architecture, using XML allows non-Ajax clients to consume your data feeds as well. I'll consider three of the ways you can produce XML data from your Java objects and discuss the pros and cons of each.
First of all, you could generate XML programatically from your object graph. This approach can be as simple as implementing a In the example code for the previous article in this series, I implemented Listing 1. JDOM implementation of toXml() for the Order class
You can see here how simple it is to create elements, set attributes, and add element content using JDOM. Recursive calls to composited JavaBeans' Once your JavaBeans all implement a Listing 2. Generating an XML response from a JDOM element
JDOM again makes life very simple here. You just need to wrap a Listing 3. Sample XML document representing a customer
Downsides of roll-your-own serialization Interestingly, the code in Listing 3 shows one of the major drawbacks of having JavaBeans serialize themselves to XML. Suppose this document was used to present an Order History view to the customer. In that case, it's unlikely that you would want to display the full description of every item in every past order, or tell the user his or her name. But if the application has a From a design perspective, this is a classic problem of the data model being coupled to view generation. Each bean can only serialize itself in one way, and the one-size-fits-all approach means that Ajax interactions end up exchanging data they don't need to, making the client code work harder to locate information it does require from the document, as well as increasing bandwidth consumption and XML parsing time on the client side. The other consequence of this coupling is that the XML grammar cannot evolve independently of the Java classes. For instance, making a change to the schema of the customer document could impact several Java classes that would then have to be modified and recompiled. I'll address these concerns later on, but first, let's look at a solution to the scalability issues of the roll-your-own serialization approach: XML binding frameworks.
In recent years, several Java APIs have been developed to simplify the process of binding XML documents to Java object graph representations. Most provide both XML marshaling and unmarshaling; that is, they perform two-way conversions between Java object graphs and XML. These frameworks encapsulate all the work of handling XML, meaning that application code only has to deal with plain Java objects. They tend to provide useful ancillary functions as well, such as document validation. Broadly, these frameworks take two different approaches: code generation and object-to-XML mapping. I'll explain both. Binding frameworks that employ code generation include XMLBeans, JAXB, Zeus, and JBind. Castor can also employ this technique. The starting point for any of these frameworks is an XML schema that describes the data types of your documents. Using tools provided by the framework, you then generate Java classes that represent these schema-defined types. Finally, you write your application using these generated classes to represent your model data and serialize them to XML through some convenient mechanism provided by the framework. The code generation approach is a good one if your application employs a large XML grammar. The scaling problem of writing custom XML-serialization methods across tens of classes vanishes. On the other hand, you no longer get to define your own JavaBeans. The framework-generated Java classes typically follow the XML's structures very closely, which can result in them being rather unwieldy to code against. Also, the generated classes become dumb data containers because you can't generally add behavior to them. Broadly speaking, you need to make compromises in your application code to play nicely with the schema-generated types. Another pitfall is that a change in the schema causes changes to the generated classes, which in turn has a knock-on effect to any code you've written around them. XML binding frameworks of this type are most useful in data unmarshaling (i.e., consuming XML documents and converting them into Java objects). Unless you have a huge data model and would benefit from having classes generated for you, code-generation-based frameworks are probably overkill for an Ajax application. Frameworks that employ mapping include Castor and Apache Commons Betwixt. Mapping is generally a more flexible and lightweight solution than code generation. First, you code your JavaBeans as you usually would, including any behavior and whatever convenience methods you like. Then, at run time, you call on the framework's introspection-based marshaler, and it produces an XML document based on the types, names, and values of your objects' members. By defining mapping files for your classes, you can override the default binding strategy and advise the marshaler how you'd like your classes to be represented in XML. This approach is a good compromise between scalability and flexibility. You get to write your Java classes the way you like them, and the marshaler saves you from dealing with XML. However, although the mapping definition files are simple to write and scale reasonably well, the mapping rules can only change the standard binding behavior so much, and some degree of coupling between the structure of your objects and their XML representation will always remain. Ultimately, you may have to compromise either your Java representations or your XML format for the mapping approach to work. Dennis Sosnoski has written in depth on the subject of XML data binding APIs of both the code-generation and code-mapping flavors. I'd recommend his excellent articles on Castor and on the code-generation frameworks if you want to investigate this area further (see Resources for links). On the whole, the code-generation approach trades off too much flexibility and convenience to be useful for the typical Ajax application. On the other hand, the mapping-based frameworks may serve you well, as long as you can tailor their mapping strategies enough to produce the XML you want from your objects. All of the XML binding APIs share a major drawback with the manual serialization technique: the coupling of model and view. Being limited to a single XML representation of each object type means it is likely that there will always be some redundant data traveling across the network. A more serious problem is that the client code cannot obtain a specialized view when the situation demands it and may have an awkward time trying to deal with the compromised one-size-fits-all view of a given object graph. In traditional Web application development, page templating systems are used to cleanly separate view generation from controller logic and model data. It's an approach that can help in an Ajax scenario as well.
Any general-purpose page templating technology can be employed to generate XML, allowing Ajax apps to create arbitrary XML response documents from their data models. An added bonus is that templates can be written using simple and expressive markup languages, as opposed to lines and lines of Java code. Listing 4 is a JSP page that takes a Listing 4. A JSP page that produces an order history document
This concise template outputs only the data needed for an Order History view, and not the irrelevant stuff such as each item's description. It would be just as easy to create custom XML for a Product Search view, which included the full description and stock level for each item. The flipside of the coin is that I now need to create a new JSP for every different view I require, as opposed to just assembling the required object graph and serializing it. From a design perspective, many would argue this is a good thing anyway because it means formally thinking about the types of document the server will produce. Also, because I'm now working with a generic templating environment and not an XML-specific API, it's my responsibility to make sure tags are balanced, element and attribute order is correct, and any XML entities (for instance
So far, all the techniques I've covered produce a server response in the form of an XML document. There are a few issues with XML, however. One of these issues is related to latency. Browsers do not parse XML documents and create DOM models instantly, and this can reduce the feeling of "snappiness" needed by some Ajax components, especially when parsing large documents on slower machines. An example is "live search," where search results are fetched from the server and displayed to the users as they type in their search terms. It's important for a live search component to respond quickly to input, but at the same time it needs to parse server responses rapidly and continuously. Latency is an important consideration, but the biggest reason to avoid XML is the awkward client-side DOM API. Listing 5 shows the hoops you commonly have to jump through to get at a value via the DOM, in a cross-browser-compatible way. Listing 5. Navigating an XML response document in JavaScript
Things become even more complex when there's whitespace between elements, because invariably every element's Nevertheless, it's worth thinking about the alternatives. In addition to
Listing 6. Using a regular expression with XMLHttpRequest's responseText object
Using
Under the hood, JavaScript objects for the most part are composed of associative arrays, numerically indexed arrays, strings, numbers, or nested combinations of these types. Because all types can be declared literally in JavaScript, it's possible to statically define an object graph in single statement. Listing 7 declares an object using JSON syntax and shows how it can be accessed. Curly braces denote an associative array (that is, an object), with its key-value pairs separated by commas. Square brackets denote a numerically indexed array. Listing 7. Declaring a simple object literally in JavaScript, using JSON
So JSON is an interesting language feature, but what does it have to do with Ajax? The punchline is that you can use JSON to send a JavaScript object graph over the network in an Ajax server's response. This means an escape from XML navigation on the client through the clunky DOM API -- you just need to evaluate the JSON response, and you instantly have an accessible JavaScript object graph. First, however, you need to turn your JavaBeans into JSON. Producing JSON from Java classes The same pros and cons that apply to different XML generation techniques also apply to producing JSON. Arguably, there is a case for using presentation templating technologies again. However, using JSON is philosophically closer to passing serialized objects between application tiers than to creating a view of the application state. I'm going to show you how to use the Listing 8. toJSONObject() method implementation for the Order class
As you can see, the Listing 9 shows how to serialize a Listing 9. Generating a serialized JSON response from a JSONObject
As you can see, there's really nothing to it. The Listing 10. JSON representation of a Customer bean
The final step in the process is turning the JSON data into JavaScript objects on the client. This can be accomplished with a simple call to Listing 11. Evaluating a JSON response
Comparing Listing 11 with Listing 5 illustrates the advantages to the client of using JSON. If your Ajax project involves navigating lots of complex server responses on the client, JSON may well appeal to you. Putting JSON and JSON does have its drawbacks. Using the JSON approach illustrated here, there's no way to tailor objects' serialization on a per-request basis, so unneeded fields may often be sent across the network. Additionally, adding
Comparing serialization techniques You've now seen five different techniques for transferring server-side Java state to an Ajax client. I've discussed roll-your-own hand-coded XML serialization, XML binding via code generation, XML binding via a mapping mechanism, template-based XML generation, and finally hand-coded serialization to JSON. Each has its own advantages and disadvantages and is best suited to different application architectures. In an attempt to summarize the benefits and drawbacks of each approach, Table 1 assigns rough scores in six categories:
The data compiled in Table 1 isn't intended to imply that any of the serialization technologies is better than the others. After all, the relative importance of each of the six categories depends on the specifics of your project. For instance, if you'll be working with hundreds of data types, you want scalability, so code generation is probably your best bet. If you need to generate several different views of the same data model, page templating is the way to go. If you're working on a small-scale project and want to reduce the quantity of JavaScript code you'll have to write, consider JSON. Hopefully this article has given you the information you need to choose a serialization technology that is suited to your application. See the Resources section to learn more about the technologies discussed here. You should also keep an eye out for the next article in this series, where I'll show you how to write a Java Ajax application using Direct Web Remoting (DWR). The DWR framework allows you to call methods on your Java classes directly from JavaScript code. In other words, it takes care of the work of data serialization for you so that you can use Ajax at an even higher level of abstraction.
Learn
Get products and technologies
Discuss
|
출처: http://www-128.ibm.com/developerworks/java/library/j-ajax2/
'WEB > AJAX' 카테고리의 다른 글
| AJAX 개발자용 자료(1) - 소개 (0) | 2007/06/06 |
|---|---|
| Ajax for Java developers: Ajax with Direct Web Remoting (0) | 2007/06/06 |
| Ajax for Java developers: Java object serialization for Ajax (0) | 2007/06/06 |
| Ajax for Java developers: Build dynamic Java applications (0) | 2007/06/06 |
| Ajax for Java developers: Build dynamic Java applications (0) | 2007/06/06 |
| Mastering Ajax, Part 2: Make asynchronous requests with JavaScript and Ajax (0) | 2007/06/06 |




최근에 달린 댓글
링크
최근에 받은 트랙백
태그목록