In the first part of this four-part series, we'll figure out what data binding is, and what the advantages are, and how to start using it, compared to other methods of processing XML data in a Java application. This section examines why data binding is used and how constraints are modeled to allow XML documents to be converted into Java objects. It also covers the inputs and outputs used to generate data-binding classes.
Do you want to use XML in your Java application? So good, go aboard this boat with thousands of others. As you delve into XML, you may find that the DOM and SAX APIs (see Resources) are nothing but bluffing. You might think there must be some simple way to get an XML document and access it through a Java application, right? Instead of using a callback or a complex tree structure, you use a method like SetOwner (stringowner) and int getnumorders (), right? If you've ever considered a problem along this line of thought, data binding is the solution you're looking for.
Analyze various options
Today all kinds of XML and XML are rampant (XSL, RDF, namespaces, RSS, XML Schema, XSLT ...). , you might think there are many ways to access XML data in Java applications now. Surprisingly, there are only three ways to access XML data, if you're really curious. Yes-there are only three methods, one of which appears recently with a new Java API.
This should be the case: a small selection makes it easier to choose the right approach for you.
Callback
Callbacks work as an event-driven model. When parsing an XML document, some events-such as the start of the document and the start of character data in an element-trigger the callback method. You can implement the Java code for these events by using the data needed to perform the logic. It is not intuitive to understand this approach; it often takes a developer a while to comprehend and master the use of the callback model. SAX, a simple API for XML, is the de facto standard for this method of XML usage.
Tree
More common and popular is the API, which gets an XML document and then creates the tree structure of the data. The XML document becomes the tree Head and acts as a container. It has several children, such as the root element. The root element has its additional children, and so on, until you (in a sense) get a picture of the XML data. Since almost every college student has worked on a tree structure at some stage, this can be used as a very intuitive way of representing XML data.
The most popular API for the tree representation of XML documents is the recommended standard for the consortium, the Document Object Model (DOM). An updated api,jdom (which is not an acronym) has recently been popularized and popular. (although this project was built by me and Jason Hunter, I have to tell the truth.) In addition, DOM and JDOM are basic requirements for Spinnaker scenario design, Spinnaker is a new XML parser that is being developed as part of the Apache XML solution.
Although the tree-like APIs appear to be easier to use than event-driven SAX, they are not always appropriate. Very large documents may require a large amount of memory (especially when using DOM), and when a transformation (XSLT) is performed on a tree structure, the system may stop running or even crash completely. Although newer APIs, such as JDOM, can handle these problems, they will still be a problem if you have to deal with extremely large amounts of data. Also, sometimes developers prefer to model the data in an XML document as a simple Java object with a read-write method with a value instead of a tree-like model. For example, a developer would prefer not to access a child node named Skunumber and set the text value of that node, but only to invoke Setskunumber ("Mysku") and continue.
The newest approach to accessing XML data in Java code relies on a new set of Java methods and associated APIs, which are still under development. Data binding is a "Java specification requirement" built by Sun (JSR-031, see Resources) designed to make it easier for Java objects to bind to XML documents, so that one format can be easily converted to another format, and vice versa. A binding refers to a Java object with a read-write method that affects the underlying XML document and is mapped directly to the element and the name of the feature in the XML document. When you enter some of the details in the next section of this series of articles, this statement makes more sense, but at the moment, suffice it to say that this allows the XML document feature name to change its value through a method called SetName (), as I indicated above.
Data Binding
This type of access is being popularized and is especially useful when storing configuration information in an XML document. Many developers find it very easy to access the required parameters directly, without using a more complex tree structure. Although this access is not useful for document conversion or messaging, it is extremely convenient for simple data processing. It is the third approach that we are interested in using XML in this article and in this series of articles.
(Of course, any method will then lead to a new set of terms, so look at the terminology explanations to understand the new jargon.) )
Can any XML document be converted to a Java object? Or are there only certain types of XML documents? Good question! You will most likely want to convert a document that satisfies a set of constraints to a Java object. This is similar to the method that defines the Java interface: you ensure that only objects that are adapted to the interface are instantiated and used, allowing assumptions about how to manipulate the object. Similarly, you only allow XML objects that meet a set of constraints to be converted to Java objects, which enables you to use the objects you create in the way you want.
constraint data
Before you look at the code, you need to answer a few questions about how to represent XML data. This is one of the most challenging aspects of data binding. Create a new class for each document, or create an instance of an existing class? Which existing class do you want to use? And most importantly, is the document you are working on suitable for conversion to Java objects?
That's a lot of questions, but you'll find all the answers here. Consider these issues as a series of decision points, a series of choices. First, you must determine whether you can create Java objects from the XML document (as discussed earlier). If you can, decide whether the conversion should occur as a new Java class or just as an instance of an existing class. Finally, if you chose an existing class, which class would you like to use? The result is a variety of decision trees.
If we look at one of the sample XML documents shown in Listing 1 and then deal with these issues, the decision tree is more clear. This sample document represents the configuration of a service (specifically, a Web container) in Enhydra application Server.
Listing 1. An XML document to configure the Web container in Enhydra <?xml version= "1.0"? >
<webserviceconfiguration version= "1.0" name= "My Web Container"
<port number= "protocol=" "http" protected= "false"/"
<document root= "/usr/local/enhydra/html" index= "*.html,*.xml" error= "error.html"/>
</webServiceConfiguration>
This configuration document contains information about the version and name of the service itself, as well as several nested projects, each representing some additional information about the Web container service. It gives details about the port (including port number, protocol, and Security), as well as document service information (including the document root, the default extension for index pages, and the error page). All of this together is all the information you need to configure a new Web container service.
With this example in mind, you can begin to answer the various questions that the data represents.
Is it suitable for conversion?
Absolutely fit! Just take a look at the XML document in Listing 1 and you'll find that it represents an object (the overall configuration object) with several features or variables. Some of these variables are other objects (ports and documents) that have their own characteristics. In fact, this is an excellent example of an XML document that is suitable for conversion to a Java object. To further ensure that this object is available, I'll show you a way to constrain the data in the document later. But first let's go down the decision tree.
Convert to class or instance?
After addressing the suitability issue, it is now time to decide whether to change each XML configuration document into a new Java class, or simply to change it to a newer instance of an existing class. In other words, whether the new code should be generated or the existing code should be used. In this way, this becomes a simple reusability problem. It is easier and wiser to generate a new instance of an existing class for each XML document. If you must try to create a new Java class from each document, the resulting classes may not be compatible--that is, two identical documents can result in two different Java classes!
Without this potentially confusing method, you can take a set of XML constraints (represented by a DTD or XML schema that will be described below) and generate a Java class (or classes, as needed) based on those constraints. This generated class will represent any XML document that conforms to these constraints, and each of these XML documents will be extracted into an instance of the generated class. In this case, you can define constraints for the document that represents the Web service configuration. These constraints will be mapped to a Java class, which we will call webserviceconfiguration. You can then obtain any XML document that represents a specific Web service configuration, and assume that the document conforms to our constraints by creating an instance of the previously generated class. This allows applications to use different XML documents as objects of the same type, as long as the data in those documents is valid for the purpose of the object's design.
New class or existing class?
Now you have the conditions to answer the next question: you want to create an existing class, an instance of the Webserviceconfiguration class. All that remains to be clarified is how this class is built beforehand. So, now focus your attention on the question of how to get a set of constraints, implement them in XML, and ensure that documents conform to these constraints? One more question is, how do you generate a reusable Java class from these constraints?
Using document constraints
Now that you know that this document will be converted to a Java instance, this creates another problem: consider the need to somehow guarantee that the document can be properly extracted into a selected Java class. Missing variables or incorrect data types can cause errors during the unpack-or even a Run-time exception when the client accesses a container with a configuration error.
At best, before the actual unpack process begins, the author of the document can guarantee that the configuration document is "legitimate" for the class they choose to represent the data. The XML people who read the solution might turn their eyes and whisper, "Well, of course you will use XML document constraints." "Confirm that the legitimacy of the data to the selected class can be done by referencing the DTD (document type definition) or XML schema.
By using a set of constraints that are represented by an external DTD or scenario file, the document author can test the configuration data on the interface of the data. In other words, you can build your application so that it can check the data contained in the XML instance document against the data you want, and the data you want is specified in the external file of the document constraint. This allows you to create an interface for the data.
Making decisions between using a DTD scheme or using an XML schema is a fairly straightforward choice: because the Java language is highly typed, we want to support typing in XML documents. For example, the data interface should be able to validate that the port number of the Web container is provided with an integer rather than a string, which causes an error when the service starts. DTD does not support type checking, so we should definitely choose an XML scheme. Although the XML scheme is somewhat uncertain in the normative domain, it has stabilized to a large extent and is expected to be finalized during the year. We can write data constraints in an XML scenario, and then use this scenario to validate possible instance documents to ensure that the unpack can be done on those instance documents. The following XML scenario represents the data interface for our web container service.
Listing 2. XML schema that represents the data interface for a Web container configuration document <?xml version= "1.0"? >
<schema targetnamespace= "http://www.enhydra.org" xmlns= http://www.w3.org/1999/xmlSchema "xmlns:enhydra=" http:// Www.enhydra.org ">
<complextype name= "Serviceconfiguration"
<attribute name= "Name" type= "string"/>
<attribute name= "version" type= "float"/>
</complexType>
<element name= "serviceconfiguration" type= "Serviceconfiguration"
<complextype name= "webserviceconfiguration" basetype= "serviceconfiguration" derivedby= "extension"
<element name= "Port" >
<complexType>
<attribute name= "Protocol" type= "string"/>
<attribute name= "number" type= "integer"/>
<attribute name= "protected" type= "string"/>
</complexType>
</element>
<element name= "Document"
<complexType>
<attribute name= "root" type= "string"/>
<attribute name= "Index" type= "string"/>
<attribute name= "Error" type= "string"/>
</complexType>
</element>
</complexType>
<element name= "webserviceconfiguration" type= "Webserviceconfiguration"
</schema>
The XML schema in Listing 2 defines several different data objects that together represent the configuration object for a Web service. First, a core service configuration (serviceconfiguration) is defined, which contains the version and name. This can be used as a basic object for all services, such as load balancing services, EJB containers, and, of course, our web services. Then, as an extension of this basic service, the Web service configuration (webserviceconfiguration) is defined. Note that after Java is molded, the scenario has established a model for the data interface. We add the additional Web service properties port and document to the version and name basic properties. These properties are objects of their own, with their own properties (protocol, root, error, and so on).
In the definition of this scenario, the feature represents a simple Java type, usually the original (primitive) type. In this way, name and version become the Java original type of type String and float respectively. Elements such as port and document become Java objects, they can have their own attributes, or they are represented by features. This shows a recursive phenomenon: the element becomes a new object, and each of its properties is checked. If the attribute is a feature, create a simple Java original member variable for the object, and if the property is an element, create a new object and add it as a member variable, and then start the same process on the new object until all the classes have been created.
From radish ... Well... XML gets Java
Once you have created an XML schema, you need to extract the necessary information from this scenario to determine which Java classes should be created. The first step in this process is to look at the XML schema and determine exactly what the output should be. For a simple Serviceconfiguration object, two Java raw properties are defined: Name and version. For such a simple object, it is not difficult to determine the required interface. Simply capitalize the first letter of the name of the defined type and add these Java properties to the interface, as shown in Listing 3.
Listing 3. Java code public interface generated from an XML schema for the Serviceconfiguration interface
serviceconfiguration {
public void Setversion (float version);
public float getversion ();
public void SetName (String name);
Public String getName ();
}
This is quite understandable; the interface in Listing 3 provides read and write methods for attributes defined in XML scenarios. In addition, you will need to generate an implementation class to define the individual member variables for this interface and implement each method in this interface. This method of separating the interface from the implementation allows us to make a variety of implementations for specific needs. For example, a particular service might need to perform calculations, not just the values received from the Write method. It's a bit premature to think about that more complicated situation now, but I'll mention it again in a later article. Generally, however, you can still determine what the implementation class should look like, as shown in Listing 4.
Listing 4. Java code public class generated from an XML schema for serviceconfiguration implementation
Serviceconfigurationimpl implements Serviceconfiguration {
private String name;
private float version;
public void Setversion (float version) {
This.version = version;
}
public float getversion () {
return version;
}
public void SetName (String name) {
THIS.name = name;
}
Public String GetName () {
return name;
}
}
The same principle applies to other objects defined in the XML schema. You can view other Java classes below (because they should all be generated):
Porttype.java
Porttypeimpl.java
Documenttype.java
Documenttypeimpl.java
Webserviceconfiguration.java
Webserviceconfigurationimpl.java
Summarize
So far, you should be familiar with all aspects of data binding. I have outlined the reasons why you should use data binding, especially in the context of configuration information, and outline some of the basic concepts you need to know to implement this approach.