This article
Transfer from IBM DeveloperWorks China website
From text to bytecode
The third part of this data binding series demonstrates how to use the method specified in JSR-031: Data Binding, Sun Data Binding Specification Application, convert XML elements and properties to Java objects. This part mainly describes the Java instance from the XML representation of the data to the application code to be easy to use. The third part is the use of new tools by canceling the nesting elements in the XML document to form a Java object, test, and use some actual examples. The goal of this series is to demonstrate how to convert an XML element into a Java object, and then you can use the Java Language Accessor and Mutator methods to directly process XML data. The first part compares the data binding and other methods of processing XML data in the Java application, analyzing design decisions, and also defines the XML mode of the sample web service configuration document. The second part illustrates how to generate an interface and implementation from an XML schema, so that the XML document that meets the XML mode can be converted into an example of these generated classes. In the third part (four parts), the explanation of the basic knowledge will be completed, and how to carefully design code is described to perform the cancelor group, and the cancellation group will complete the process of converting XML into Java objects. After the cancellation group is executed, you can use the test class (included) to check if all parts are properly combined. Each part of this series is based on other parts, so if you haven't seen the first and second part yet, you may not understand some of this article. If you want to review the special vocabulary, please refer to the term interpretation side bar. Using the XML schema defined for WebServiceConfiguration (see Update Versions) and the interfaces in the second section, the XML document that will be created for configuring data. Any XML document that matches the mode can be composed of Java objects. These objects should be an instance of classes generated using the SchemAmApper class. Of course, the final result is data binding.
Making an XML instance document creates an XML document that matches the mode - is usually called an XML instance - it is very simple. The documentation must only provide data values that match the constraints defined in the mode, as shown in Listing 1. Listing 1. XML instance document in accordance with XML mode
XML Version = "1.0"?>
The example in Listing 1 completely shows an instance of WebServiceConfiguration. The instance documentation includes two namespace declarations. The first is the default namespace declaration, please refer to http://www.enhydra.org. This means that all elements that have no prefix will be assigned to this namespace. Although, in this example, it is not necessary to declare the default namespace, it also gives some identities of the document. This default namespace helps to distinguish the document from other XML documents with similar or equivalent element names. Another namespace defined to the XSI prefix, so all elements with this prefix are allocated to this namespace. It (http://www.w3.org/1999/xmlschema/instance) references the URI of the "XML Mode Instance Specification". This specification defines how XML documents refer to the XML schema that meets the document. Finally, the SchemAlocation property references XML mode. The first variable of this attribute is a namespace that is bound (example default namespace, which includes each element in the document). The second variable is separated from the first variable with the first variable, reference the actual location of the XML mode. In this example, the mode configuration.xsd is a local file that is in the same directory with the document. You can also reference the mode of any location on the network by using the URL. In the default namespace, additional properties (because they don't have prefix) define version (1.1) and names. Next, declare the PORT object in the mode and define its data: the port number is 80, the protocol is HTTP. After correctly canceling the Java code, the document becomes an instance of the WebServiceConfigurationImpl class. Then, the Java code can use the interface WebServiceConfiguration designed in this series to use the data in the basic XML document. (Note that verification may be performed in the application, as outlined in the mode verification side bar.) Mode Verify the new XML syntax analyzer, such as the current release of the Apache Xerces Script, Allow the XML instance documentation Perform mode verification. Verify allows you to make sure that the XML document is in line with the XML schema that is referenced. Please contact your grammar analyzer supplier or refer to the document to determine if the syntax analyzer supports mode verification, its verification range, and how to open verification. Before opening the front door official start, you need to provide an entry point to cancel the group XML document, which is an input to the method of returning a Java object. (Because you will recall, the result of the cancellation in this example is just a Java object.) Then, the object can be converted into an appropriate interface, in fact, you have generated the interface (in the second part of this series). For example schemaMAPper classes, it is most meaningful to incorporate URLs. This provides more options because the file name can be used as input, not only the file name. After knowing this, the next step creates a JDOM document object (org.jdom.document) from the URL and processes the document. Check the code for executing the action in Listing 2. Listing 2. Map the character string into the type specified by Java / **
. * * This method is the public entry point for unmarshalling an object from * an XML instance document * ** @param instanceURL URL for the instance document * @return Object -. The created Java Object, or * null if problems occur in a .. way that does not * generate an Exception * @throws IOException when errors in binding occur * / public static Object unmarshall (URL instanceURL) throws IOException {// Read in the documentSAXBuilder builder = new SAXBuilder (); try {Document doc = builder.build (instanceURL); Element rootElement = doc.getRootElement (); Unmarshaller unmarshaller = new Unmarshaller (); return unmarshaller.getJavaRepresentation (rootElement);} catch (JDOMException e) {throw new IOException (e.getMessage ()); }} The method in Listing 2 is static, allowing it to call it directly without instance of instances. This method can be static because there is no need to share between multiple calls to the unmarshall method. Once the XML is processed, the root element of the document is transmitted to the internal method of performing the conversion from XML to Java object.
Conversion data I don't plan to explain the complete code used in the cancellation group. You can view the full source code list, which basically does not need to be explained. However, in the entry point example, there are some things worth emphasizing. If a new instance of an appropriate class is created, the value of the XML document will be used to call the Mutator method (all name setXXX). Of course, this will enable XML data to be available everywhere in the Java method of the instance. Listing 3 shows the code segment that handles this lookup method and subsequent calls.
Listing 3. The entry point of the UNMARSHALLER class
// For each attribute, get its name and call mutatorList attributes = rootElement.getAttributes (); Method [] methods = objectClass.getMethods (); for (Iterator i = attributes.iterator (); i.hasNext ();) { Attribute att = (attribute) i.next (); // Only Want Attributes for this namespace if (! Att.getnamespace (). Equals (ns)) && (). Equals (namespace.namespace). )) {Continue;} // determine method to call string methodname = new stringbuffer () .append ("set") .append (bindingutils.initialcaps (att.getname ())) .tostring (); // Find the method To Call, And ITS Parameter Type FOR (INT J = 0; J Find the properties of the root element, and determines the applicable method for each attribute. Then, it is to process the actual java.lang.reflect.Method object .xml property The value is determined, and is transmitted as the method to the method. However, there is a need to solve a mapping problem; all the data in the XML document is extracted as String, but it must be an appropriate Java type when passing. Listing 4 Add a method to DataMapping Auxiliary class to meet the needs of the conversion. Listing 4 mapping the character string into a Java-specific type
/ *** * This will take the String value supplied and convert it * to an Object of the type specified in paramType. * ** @param value String value to convert. * @Param paramType Class with type to convert to. * @ . return Object - value in correct type * / public static Object getParameter (String value, Class paramType) {Object ob = null; String type = paramType.getName (); if (type.equals ( "java.lang.String") ) {ob = value;} else f (("INT")) || ("java.lang.integer")))) {ob = integer.valueof (value);} else ((Type.equals ("" ("java.lang.long")))))) {ob = long.valueof (value);} else f ((Type.equals ("float" ))) || ("java.lang.float"))))) {ob = float.valueof (value);} else f (("Double.Equals (" double ") || (Type.equals "java.lang.double")))) {ob = double.valueof (value);} else ((Type.equals ("Boolean")) || (Type.equals ("java.lang.boolean"))) {OB = Boolean.valueof (value);} return;} In Listing 4, the value is incorporated as String, and is also passed into a method of converting the class and processing type conversion to be converted. Of course, there is not much data type included here. More types (such as java.util.date) can be added to support more complex data mappings. Once the data is converted into an appropriate type, you can use the reflection to call the Accessor method and you can pass the converted data type. This allows all attributes and values in the XML document to be stored in the Java instance as a result.
The rest of the recursive object tree will be the generating nested object (such as the PortType object in the WebServiceConfiguration object). Finally, pass the nested object to the Accessor method, and then the top object of the member variable value and the object reference will be fed to the call. This way has generated an object tree, with the primary object being the trunk of the tree. Each nested object has formed branches of trees that must be filled. These branches can have their own branches, with nested objects that must be filled. It can be seen that this tree may become very complicated.
If you don't know how many times in the same manner, recursive is almost always the best choice for operation. If you are a UNMARSHALLER class, you will need to recurs in the complete process of binding XML to Java. Once all attributes are read and assigned to the created Java instance, you need to remove each nested element and then perform the cancellation group again. The processing of the XML document is completed by iteration of the sub-elements provided by iteration, as shown in Listing 5. Each of these sub-elements will be another object, which means that the unpacking process must be restarted as the root element. Listing 5. Using recursive processing nested elements // now do complelement.getchildren (); for (Iterator i = Elements.ITerator (); I.hasnext (); {ELEMENT ELEMENT = (Element) i. NEXT (); // ONLY WANT Elements for this namespaceif ((! Element.getNameSpace (). Equals (ns)) && () & (! element.getnamespace (). Equals (namespace.namespace)) {Continue;} // determine method to callString methodName = newStringBuffer () append ( "set") append (BindingUtils.initialCaps (element.getName ())) toString ();... // Find the method to call, and its parameter typefor (int j = 0; J Note: You may notice that I have made a hypothesis in the cancelor group in Listing 5, that is, the member variable is always represented by the XML property, and the nested object is represented by the XML element. Then, these elements may have their own properties and nested elements. My assumption is the only set limit and is reasonable. This means that the process does not have to view the referenced XML mode and determine the characteristic is indicated by the element, or by the attribute. This will also make the grouping process easier and will appear in this series of next articles. If all this is not difficult, only the properties are used as variables, the elements are used as objects, and they do not have to consider nested and recursive. The code in Listing 5 seems to be very similar to the previous code, and its main difference is a few lines that emphasize in red. This code is acquired by deforming the nesting element, rather than using the DATAMAPPING secondary class to convert text values to Java data types. Then, the returned object is supplied to the appropriate Mutator method (for example, setport), and iterate continues. Once the recursive from the underlying to the top layer, the created Java object will return to the calling application. Soon! Data binding is complete. By using the running UNMARSHALLER class, it is actually used, it finally uses the data binding tool. Access XML is as simple as accessing JavaBean by using XML mode, XML documents, and some simple Java code. Generate class First, make sure that Java classes have been generated from the XML mode, as shown in Listing 6. Listing 6. Generate Java classes from sample mode / Projects / dev / binding> export classpath = / projects / dev / jdom / lib / xerces.jar / projects / dev / binding> export classpath = $ classpath: /projects/dev/jdom/build/jdom.jar/projects/ dev / binding> export CLASSPATH = $ CLASSPATH: / projects / dev / binding / projects / dev / binding> java org.enhydra.xml.binding.SchemaMapper xml / configuration.xsd / projects / dev / binding> javac -d *. .java With UNMARSHALLER, if you have generated a class from the XML mode, you can continue. As a simple test that ensures that the class is working, you can use the functionality of the class test data in Listing 7 (or download this class). Listing 7. Data Binding Test Class Import Java.io.file; Import org.enhydra.xml.binding.unmarshaller; Public class testmapper {public static void main (string [] args) {system.out.println ("start unmarshalling ..."; try {file file = new file (" XML / EXAMPLE.XML "); Object O = unmarshaller.unmarshall (file.tourl ()); System.out.Println (" Object Class: " O.getClass (). getname ()); system.out.println ( "Casting to WebServiceConfiguration ..."); WebServiceConfiguration config = (WebServiceConfiguration) o; System.out.println; System.out.println ( "Name:" config.getName ()) ( "Successful cast."); System.out.println ("Version:" config.getversion ()); System.out.println ("Port Number:" Config.getPort (). Getnumber ()); System.out.Println ("Port protocol : " config.getPort (). getProtocol ());} catch (exception e) {E.PrintStackTrace ();}}} Compile and run the data binding test class to view the results, as shown in Listing 8. Listing 8. Test unmarshaller / Projects / dev / binding> javac -d TestMapper.java/projects/dev/binding> java TestMapperStarting unmarshalling ... Object class:. WebServiceConfigurationImplCasting to WebServiceConfiguration ... Successful cast.Name: Unsecured Web ListenerVersion: 1.1Port Number: 80Port Protocol: http Starting the web service as a more practical example, let us review the Web service example already mentioned in several articles. Suppose there are some Java classes that can be programmable (called WebService), which simply uses the data binding to get the configuration information of the class. Now, reading and launching a new web listener from an XML document (or even) is very easy - this does not require any XML-specific API knowledge, as shown in Listing 9. Cance the configuration data to form a Java object, then use the standard Java Accessor method (usually getxxx () format) to configure a new web service. Listing 9. XML to Web Listening Program // AssuMe We Have (Iterator I = Urls.iterator (); I.hasNext ();) {WebServiceConfiguration Config = Unmarshaller.unmarshal ((URL) i.next ()); WebService NewService = New WebService NewService.setName (config.getname ()); // set up port informationnewservice.setport (). getnumber ()); newservice.setProtocol (config.getPort (). getProtocol ()); // Set up document rootnewservice.setdocroot (). GetRoot ()); newservice.setd (). GetError ()); newservice.start ();} is then simple, even the primary developers are also Can write a Java program that uses this simple XML document and its data, and he even doesn't know that you are using XML! For more use of XML data binding code, please pay attention to the new version of the ENHYDRA application server so that the data binding classes discussed here (and will continue discussions in the next article) in the future release. After completing the code of UNMARSHALLER, you can discuss the final details. With the continuous development of the API, we saw the SchemAPper class before we saw the SchemAPper class, which generated Java interface and implementation from the XML mode. This code uses the Jdom API to a large extent (mainly because it is very convenient, it is what I have written!). However, 30 days is only enough to carry out a hockey season, for the API, such as JDOM, it is almost a lifetime. Since the last article, there have been several changes have taken effect in the JDOM API, and most of them reflect some updated method names. For more information on changes and reason, please visit the JDOM website (see Resources), you can join the JDOM-interest mailing list on that site. However, in order to help you use the latest and best versions, the SchemApper class appears on the Internet again and has been updated to use the latest version of JDOM (directly from CVS). You can also download the source code. It is highly recommended to get the latest JDOM from CVS and use the updated version of the code. (More changes may still still be changed before the fourth part.) JSR-031, data binding API, is still in the Java community. In this process, it may also do some changes. Although it is not yet mature, many Java developers using XML still use it so far because it is a very useful function. Conclusion You can use data binding code by using new details in this section. With the UNMARSHALLER class, you can easily use the XML document in the Java code without having to directly use the XML API, such as DOM, SAX or JDOM. Although the sample is recommended to use the data binding processing profile, you may already have other ideas that use data binding in the application. You can also use data binding code to perform message delivery, data storage, and display, and so on.