In the previous section of this series, I demonstrated how to remove an XML document and convert it to a Java representation. The key to this transformation is the XML schema that the XML document conforms to. The pattern ensures not only mandatory constraints. It also allows the use of Schemamapper to generate Java classes, so that XML documents can be wrapped into one instance of those classes. In other words, not only does the system require an XML document, the Java class in which the document will become its instance must not only exist, but it must also be in the system's classpath.
Packing class
The situation is slightly different when packaging Java instances. First, the Unmarshaller class does not store information about the XML schema that is used in the Java instance that is created. Therefore, an instance of a Java class created from an XML document is not fundamentally different from any other Java class. Initially, this seems to be a problem. Does the Java class have to take more action to return an instance to XML? The answer is "yes". However, this is a good thing: classes that are extracted from XML are completely independent of the XML document. This has several advantages:
Java instances can be wrapped into different XML documents.
Packaged code does not depend on looking for an XML schema or XML document.
Using reflection and other Java methods on this Java instance does not produce unexpected fields or methods.
The first two points may be obvious, and the 3rd may not be. Reflection is being used more and more widely in Java applications to handle a variety of different types of objects at run time. Fields and methods are typically checked to determine how objects are used. If you want to create additional methods, such as ToXML (), or additional fields, such as XmlSchema, the class returns these methods to the application that examines it. The end result is that other application code may incorrectly use information specifically designed to package and reconcile data. Outside of the data-bound environment, these methods and fields (or variables) are likely to be misused. They even give application information about network resources, such as XML schemas, that should not be disclosed.
It is for these reasons that it is necessary to admit that it is slightly more difficult to package Java as XML than to package it with the original XML schema. However, because of this difficulty, the generated Java instance is independent of the XML document or schema. If all of this confuses you, consider this problem by returning the unpacked Java objects and packaged XML documents to other application developers without giving any specific usage directives to them. In fact, they don't even know if the data is XML or Java; they see the data format just the format you provide.
This is an important principle to keep in mind--isolate data retrieval methods. That makes it easier to follow the basic guidelines for keeping data as private as possible. For example, information about how to get data from an XML document is not suitable for distribution to other application developers, especially in different companies (such as in merchant-merchant applications).
In-depth study
I've talked about some preliminary concepts and now it's time to study the code. First, you need to add an entry point to package the Java objects into an XML document. As with the Unmarshaller class, it is easiest for other programs to use packaged code from a static method. If there is no option to pass in the Java object, as discussed here, this approach works. At the same time, it is important to follow good programming practices, to construct objects internally using this static method, and to invoke non-static methods. This static method is the "front door" for packaging Java objects. In addition to removing objects for packaging, the static method should also be able to output XML documents.
Here, you need to avoid a common error, which is to allow XML documents to be exported as String or File. These two output methods assume that the objects are packaged into some permanent storage and that they exist on the physical hard disk. Although objects are often passed through the network stream, such as passing to another application. Or it can be given to the XSLT processor, which transforms the XML into other forms. In either case, either String or File does not completely solve the problem. In fact, you should select a more secure route and allow you to provide outputstream for writing. This stream can encapsulate FileOutputStream to write local files, network connections, or pipelines to another program (such as the XSLT processor just mentioned). Once you have identified this argument, you can consider the entry point of the Marshaller class.
Listing 1. Static entry point /**
* <p>
* This method is the public entry point for marshalling an object into
* an XML instance document.
* </p>
*
* @param obj <code>Object</code> to convert to XML.
* @param out <code>OutputStream</code> to write XML to.
* @throws <code>IOException</code> when errors in output occur.
*/
public static void marshall(Object obj, OutputStream out) throws IOException {
Marshaller marshaller = new Marshaller();
marshaller.writeXMLRepresentation(obj, out);
}
It looks simple, doesn't it? Very good. In addition to this and other snippets in the article, you can download the full Marshaller class and view the HTML-formatted class.
Once an instance of the Marshaller class is created internally, the variable supplied to the static method is passed to the dynamic version of the same method. Because I already have the supplied stream write the result, I do not need to return the value. After the front door was built, it was time to study the rest of the house.