You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by aj...@apache.org on 2005/08/12 11:28:58 UTC

svn commit: r232246 - /webservices/axis/trunk/java/xdocs/OMTutorial.html

Author: ajith
Date: Fri Aug 12 02:28:36 2005
New Revision: 232246

URL: http://svn.apache.org/viewcvs?rev=232246&view=rev
Log:
Proofread and corrected some grammatical/code errors

Modified:
    webservices/axis/trunk/java/xdocs/OMTutorial.html

Modified: webservices/axis/trunk/java/xdocs/OMTutorial.html
URL: http://svn.apache.org/viewcvs/webservices/axis/trunk/java/xdocs/OMTutorial.html?rev=232246&r1=232245&r2=232246&view=diff
==============================================================================
--- webservices/axis/trunk/java/xdocs/OMTutorial.html (original)
+++ webservices/axis/trunk/java/xdocs/OMTutorial.html Fri Aug 12 02:28:36 2005
@@ -34,7 +34,8 @@
 OM was deliberately made API centric. It allows the implementations to take place independently and swapped without affecting the program later.</p>
 
 <h3>Features of OM</h3>
-<p>OM is a lightweight, differed built XML info set representation based on StAX (JSR 173), which is the standard streaming pull parser API. The object model can be manipulated as flexibly as any other object model (Such as jdom), but underneath the objects will be created only when they are absolutely required. This leads to much less memory intensive programming.
+<p>OM is a lightweight, differed built XML info set representation based on StAX (<a href="http://www.jcp.org/aboutJava/communityprocess/first/jsr173/">JSR 173</a>), which is the standard streaming pull parser API. The object model can be manipulated as flexibly as any other object model (Such as
+<a href="http://www.jdom.org/">JDOM</a>), but underneath the objects will be created only when they are absolutely required. This leads to much less memory intensive programming.
 Following is a short feature overview of OM.</p>
 
 <ul>
@@ -44,10 +45,12 @@
 </ul>
 <!-- Special section -->
 <p class="special">
-<table width="100%">
+&nbsp;<table width="100%">
 			 <tr>
-			 		 <td><img src="images/OM005.gif" alt="Rememeber this"/></td>
-					 <td class="special-td">OM is tightly bound to StAX API. To work with OM a StAX compliant parser and the API must be present in the classpath. <td>
+			 		 <td>
+                     <img src="images/OM005.gif" alt="Rememeber this" width="35" height="57"/></td>
+					 <td class="special-td">OM is tightly bound to StAX API. To work with OM a StAX compliant parser and the API 
+                     <i>must</i> be present in the classpath. <td>
 			 </tr>
 </table>
 </p>
@@ -55,7 +58,7 @@
 <p>The Following image shows how OM API is viewed by the user</p>
 <!-- Image -->
 <p align="center" class="img">
-<img src="images/archi006.jpg" alt="OM Structure" class="img"/>
+<img src="images/archi006.jpg" alt="OM Structure" class="img" width="490" height="282"/>
 </p>
 <p align="center" class="img-title">Figure 1</p>
 <!--  End of Image -->
@@ -64,7 +67,8 @@
 <h3> A bit about caching</h3>
 <p>Since OM is a differed built Object model, It incorporates the concept of caching. 
 Caching refers to the creation of the objects while parsing the pull stream. 
-The reason why this is so important is because caching can be turned off in certain situations. In this situation
+The reason why this is so important is because caching can be turned off in certain situations. 
+if so
 the  parser proceeds without building the object structure. User can extract the raw pull stream from OM and use 
 that instead of the OM and in this case it is sometimes beneficial to switch off caching.
 The advanced operations section explains more on accessing the raw pull stream and switching the caching on and off.
@@ -87,16 +91,17 @@
 <h2>Section 2 - Working with OM</h2> 
 <h3>Obtaining the OM binary</h3>
 <p>OM is not a separate product but part of Axis2. However since Axis2 has a modular build structure
-It is possible to obtain a "OM only" jar. 
+It is possible to obtain an "OM only" jar. 
 <p>
 The easiest way to obtain the OM binary is to download the Axis2 binary distribution. The lib directory will
-contain the axis2-xml-0.91.jar. However more adventures users can build the OM from source. The next section describes how
+contain the axis2-xml-0.91.jar. However more adventurous users can build the OM from source. The next section describes how
 to build OM from source.</p>
 <p>Detailed information on getting source from Axis2 SVN repository can be found <a href="svn.html" target="_blank">here</a>.</p>
 <p>After the source download OM-binary can be built. 
   For both Windows and Linux move to the project directory and execute the command "maven jar". All other necessary jars will be automatically downloaded.
-  When the build finishes successfully, the axis2-xml-0.91.jar can be found in the newly created "targets" directory</p>
-<p>Once the OM-binary is obtained by any of the mentioned means,it should be included in the class path for any of the OM based programs to work. The subsequent parts of this tutorial assume that this build step is complete and the Axis-0.91.jar is correctly in the classpath along with the StAX API jar file and a StAX implementation.
+  When the build finishes successfully, the axis2-xml-0.91.jar can be found in the newly created "targets" directory 
+in the XML module.</p>
+<p>Once the OM-binary is obtained by any of the mentioned means , it should be included in the class path for any of the OM based programs to work. The subsequent parts of this tutorial assume that this build step is complete and the Axis-0.91.jar is correctly in the classpath along with the StAX API jar file and a StAX implementation.
 </p>
 <h3>Creation</h3>
 <p>Creation is the first and foremost action in using an Object representation. This part explains how OM can be built from an existing document or just programmatically.
@@ -111,14 +116,13 @@
 The recommended way to create OM objects programmatically is to use the factory. OMAbstractFactory.getOMFactory() will return the proper factory and the creator methods for each type should be called. Currently OM has two builders, namely the OM builder and the SOAP model builder. These builders provide the necessary information to the XML info set model to build itself.  </p>
 <!-- Image -->
 <p class="img">
-<img src="images/archi007.jpg" alt="OM Structure 2" class="img"/>
+<img src="images/archi007.jpg" alt="OM Structure 2" class="img" width="420" height="246"/>
 </p>
 <p class="img-title">Figure 2</p>
 <!--  End of Image -->
 
 <p>A simple example is shown below.</p>
-<pre class="code">
-//create a factory
+<pre class="code">//create a factory
 OMFactory factory = OMAbstractFactory.getOMFactory();
 //use the factory to create two namespace objects
 OMNamespace ns1 = factory.createOMNamespace("bar","x");
@@ -130,8 +134,11 @@
 </pre>
 <div align="left"><b>Code listing 2.2</b></div>
 <p>The reason to have a set of factory.createXXX methods is to cater for different implementations but keep the programmers code intact. Its highly recommend to use the factory for creating OM objects as this will ease the switching of different OM implementations.
-Several differences exist between a programmatically created OMNode and a conventionally built OMNode. The most important difference is that the former will have no builder object enclosed where as the latter always carries a reference to its builder. As stated earlier in this tutorial, since the object model is built as and when required, each and every OMNode should have a reference to its builder. If this information is not available, it is due to the Object being created without a builder.  In other words programmatically built OMNodes do not have a reference to a builder. This difference becomes evident when the user tries to get a non caching pull parser from the OMElement. This will be discussed in more detail in the advanced operations section.
-In order to understand the requirement of the builder reference in each and every OMNode, consider the following scenario. Assume that the parent element is built but the children elements are not. If the parent is asked to iterate through its children, this information is not readily available to the parent element and it should build its children first before attempting to iterate them. In order to provide a reference of the builder, each and every node of an OM structure should carry the reference to its builder. Each and every OMNode carries a flag that states its build status.
+Several differences exist between a programmatically created OMNode and a conventionally built OMNode. The most important difference is that the former will have no builder object enclosed where as the latter always carries a reference to its builder. As stated earlier in this tutorial, since the object model is built as and when required, each and every OMNode 
+should have a reference to its builder. If this information is not available, it 
+is due to the Object being created without a builder. This difference becomes evident when the user tries to get a non caching pull parser from the OMElement. This will be discussed in more detail in the advanced operations section.</p>
+
+<p>In order to understand the requirement of the builder reference in each and every OMNode, consider the following scenario. Assume that the parent element is built but the children elements are not. If the parent is asked to iterate through its children, this information is not readily available to the parent element and it should build its children first before attempting to iterate them. In order to provide a reference of the builder, each and every node of an OM structure should carry the reference to its builder. Each and every OMNode carries a flag that states its build status.
 Apart from this restriction there are no other constraints that keep the programmer away from mixing up programmatically made OMNode objects with OMNode objects built from builders.</p>
 
 <p>The SOAP Object hierarchy is made in the most natural way for a programmer. An inspection of the API will show that it is quite close to the SAAJ API but with no bindings to DOM or any other model. The SOAP classes extend basic OM classes (such as the element) hence one can access a SOAP document either with the abstraction of SOAP or drill down to the underlying XML Object model with a simple casting.</p>
@@ -139,14 +146,12 @@
 Need an image here -->
 <h3>Addition of Nodes</h3>
 <p>Addition and removal methods are primarily defined in the OMElement interface. The following are the most important in adding nodes.</p>
-<pre class="code">
-public void addChild(OMNode omNode);
+<pre class="code">public void addChild(OMNode omNode);
 public void addAttribute(OMAttribute attr);
 </pre>
 <div align="left"><b>Code listing 2.3</b></div>
 <p>This code segment shows how the addition takes place. Note that it is related to the code segment shown in the creation section.</p>
-<pre class="code" >
-//set the children
+<pre class="code" >//set the children
 elt11.addChild(elt21);
 elt12.addChild(elt22);
 root.addChild(elt11);
@@ -162,18 +167,17 @@
 OMNamespace is the class that represents a namespace with intentionally removed setter methods. This makes the OMNamespace immutable and allows the underlying implementation to share the objects without any difficulty.
 Following are the important methods available in OMElement to handle namespaces.</p>
 
-<pre class="code">
-public OMNamespace declareNamespace(String uri, String prefix);
+<pre class="code">public OMNamespace declareNamespace(String uri, String prefix);
 public OMNamespace declareNamespace(OMNamespace namespace);
 public OMNamespace findNamespace(String uri, String prefix) throws OMException;
 </pre>
 <div align="left"><b>Code listing 2.5</b></div>
 <p>The declareNamespacexx methods are fairly straightforward. They add a namespace to namespace declarations section. Note that a namespace declaration that has already being added will not be added twice. 
-FindNamespaces is a very handy method to locate a namespace object higher up the object tree. It searches for a matching namespace in its own declarations section and jumps to the parent if it's not found. The search progresses up the tree until a matching namespace is found or the root has been reached.</p>

+FindNamespace is a very handy method to locate a namespace object higher up the object tree. It searches for a matching namespace in its own declarations section and jumps to the parent if it's not found. The search progresses up the tree until a matching namespace is found or the root has been reached.</p>
+
 <p>During the serialization a directly created namespace from the factory will only be added to the declarations when that prefix is encountered by the serializer. More of the serialization matters will be discussed in the serializer section.</p>
 <p>The following simple code segment shows how the namespaces are dealt with in OM</p>
-<pre class="code" >
-OMFactory factory = OMAbstractFactory.getOMFactory();
+<pre class="code" >OMFactory factory = OMAbstractFactory.getOMFactory();
 OMNamespace ns1 = factory.createOMNamespace("bar","x");
 OMElement root = factory.createOMElement("root",ns1);
 OMNamespace ns2 = root.declareNamespace("bar1","y");
@@ -186,8 +190,7 @@
 </pre>
 <div align="left"><b>Code listing 2.6</b></div>
 <p>Serilization of the root element produces the following XML </p>
-<pre class="xml">
-&lt;x:root xmlns:x="bar" xmlns:y="bar1"&gt;
+<pre class="xml">&lt;x:root xmlns:x="bar" xmlns:y="bar1"&gt;
   &lt;x:foo&gt;
 	&lt;y:yuck&gt;blah&lt;/y:yuck&gt;
   &lt;/x:foo&gt;
@@ -196,8 +199,7 @@
 <h3>Traversing</h3>
 <p>Traversing the object structure can be done in the usual way by using the list of children. Note however that the child nodes are returned as an iterator. The Iterator supports the 'OM way' of accessing elements and is more convenient than a list for sequential access.
 The following code sample shows how the children can be accessed. The children are of the type OMNode that can either be OMText or OMElement.</p>
-<pre class="code" >
-Iterator children = root.getChildren();
+<pre class="code" >Iterator children = root.getChildren();
 While(children.hasNext()){
 	OMNode node = (OMNode)children.next();
 }
@@ -207,9 +209,10 @@
 A more selective set can be chosen by using the getChildrenWithName(QName) methods. The getChildWithName(Qname) method returns the first child that matches the given QName and getChildrenWithName(QName) returns a collection containing all the matching children. The advantage of these iterators is that they won't build the whole object structure at once, until its required.</p>
 <!-- Special section -->
 <p class="special">
-<table width="100%">
+&nbsp;<table width="100%">
 			 <tr>
-			 		 <td><img src="images/OM005.gif" alt="Rememeber this"/></td>
+			 		 <td>
+                     <img src="images/OM005.gif" alt="Rememeber this" width="35" height="57"/></td>
 					 <td class="special-td">
 					 All iterator implementations internally stay one step ahead of their apparent location to provide the correct value for the hasNext() method. This hidden advancement can build elements that are not intended to be built at all. Hence these iterators are recommended only when caching is not a concern. <td>
 			 </tr>
@@ -219,7 +222,8 @@
 
 <p>OM can be serialized either as the pure object model or the pull event stream. The serialization uses a XMLStreamWriter object to write out the output and hence the same serialization mechanism can be used to write different types of outputs (such as text, binary, etc.,).</p>
 <p>A caching flag is provided by OM to control the building of the in-memory OM.
-The OMNode has a method serialize(XMLStreamWriter,cache).  When the cache flag is reset the serializer does not cache the stream. Hence the object model will not be built if the cache flag is not set. </p>
+The OMNode has two methods, serializeWithCache and serialize  When serialize is 
+called the cache flag is reset and the serializer does not cache the stream. Hence the object model will not be built if the cache flag is not set. </p>
 <p>The serializer serializes namespaces in the following way.</p>
 <ol>
 <li>When a namespace that is in the scope but not yet declared is encountered, then it will be declared.</li>
@@ -231,18 +235,19 @@
 <p>Here is an example that shows how to write the output to the console, with reference to the earlier code sample (Code listing  2.1 ) that created a SOAP envelope.<p/>
 
 
-<pre class="code">
-XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(System.out);
+<pre class="code">XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(System.out);
 //dump the output to console with caching
-envelope.serialize(writer);
-envelope.serializeWithCache(writer);</pre>
+envelope.serializeWithCache(writer); 
+writer.flush();</pre>
+
+
+<pre class="code">&nbsp;</pre>
 <div align="left"><b>Code listing 2.8</b></div>
 <p>The above mentioned features of the serializer forces a correct serialization even if only a part of the OM tree is serialized. The following serializations show how the serialization mechanism takes the trouble to accurately figure out the namespaces.
 The example is from code listing 2.6 which creates a small OM programmatically.
 Serialization of the root element produces</p>
 
-<pre class"xml">
-&lt;x:root xmlns:x="bar" xmlns:y="bar1"&gt;
+<pre class="xml">&lt;x:root xmlns:x="bar" xmlns:y="bar1"&gt;
  &lt;x:foo&gt;
    &lt;y:yuck&gt;blah&lt;/y:yuck&gt;
  &lt;/x:foo&gt;
@@ -250,9 +255,7 @@
 </pre>
 
 <p>However serialization of only the foo element produces </p>
-<pre class="xml">
-
-&lt;x:foo xmlns:x="bar"&gt;
+<pre class="xml">&lt;x:foo xmlns:x="bar"&gt;
 &lt;y:yuck xmlns:y="bar1"&gt;blah&lt;/y:yuck&gt;
 &lt;/x:foo&gt;
 
@@ -262,8 +265,7 @@
 Complete code for the OM based document building and serialization
 The following code segment shows how to use the OM for completely building a document and then serializing it into text pushing the output to the console. Only the important sections are shown here and the complete program listing can be found in the appendix.
 </p>
-<pre class="code">
-//create the parser
+<pre class="code">//create the parser
 XMLStreamReader parser = XMLInputFactory.newInstance().createXMLStreamReader(new FileReader(file));
 //create the builder
 OMXMLParserWrapper builder =   OMXMLBuilderFactory.createStAXSOAPModelBuilder(OMAbstractFactory.getOMFactory(),parser);
@@ -273,6 +275,7 @@
 XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(System.out);
 //dump the out put to console with caching
 envelope.serialize(writer);
+writer.flush();
 </pre>
 <div align="left"><b>Code listing 2.9</b></div>
 <h2>Section 3 - Advanced Operations with OM</h2>
@@ -282,8 +285,7 @@
 <p>It is possible that the OM tree does not get built completely when it is navigated. The navigable status shows whether the tree structure is navigable. When the navigator is complete it is not navigable anymore. However it is possible for a navigator to become non-navigable without being complete.
 The following code sample shows how the navigator should be used and handled using its states.
 </p>
-<pre class="code">
-//Create a navigator
+<pre class="code">//Create a navigator
 OMNavigator navigator = new OMNavigator(envelope);
 OMNode node = null;
 while (navigator.isNavigable()) {
@@ -292,17 +294,18 @@
 </pre>
 <div align="left"><b>Code listing 3.1</b></div>
 <h3>Accessing the Pull Parser </h3>
-<p>OM is tightly integrated with StAX and the getPullParser(Boolean cache) method in the OMElement provides a XMLStreamReader object. 
-This XMLStreamReader instance has a special capability of switching between the underlying stream and the OM object tree if the cache setting is off. However this functionality is completely transparent to the user. This is further explained in the following paragraphs.
-OM has the concept of caching, and OM is the actual cache of the events fired. However the requester can choose to get the pull events from the underlying stream rather than the OM tree. This can be achieved by getting the pull parser with the cache off. If the pull parser was obtained without switching off cache, the new events fired will be cached and the tree updated.
+<p>OM is tightly integrated with StAX and the getXMLStreamReader()/getXMLStreamReaderWithoutCaching() methods in the OMElement provides a XMLStreamReader object. 
+This XMLStreamReader instance has a special capability of switching between the underlying stream and the OM object tree if the cache setting is off. However this functionality is completely transparent to the user. This is further explained in the following paragraphs.</p>
+<p>&nbsp;OM has the concept of caching, and OM is the actual cache of the events fired. However the requester can choose to get the pull events from the underlying stream rather than the OM tree. This can be achieved by getting the pull parser with the cache off. If the pull parser was obtained without switching off cache, the new events fired will be cached and the tree updated.
 This returned pull parser will switch between the object structure and the stream underneath and the users need not worry about the differences caused by the switching. The exact pull stream the original document would have provided would be produced even if the OM tree was fully/partially built.
-The getPullparser() method is very useful when the events need to be handled in a pull based manner without any intermediate models. This makes such operations faster and efficient. 
+The getXMLStreamReaderWithoutCaching() method is very useful when the events need to be handled in a pull based manner without any intermediate models. This makes such operations faster and efficient. 
 </p>
 <!-- Special section -->
 <p class="special">
-<table width="100%">
+&nbsp;<table width="100%">
 			 <tr>
-			 		 <td><img src="images/OM005.gif" alt="Rememeber this"/></td>
+			 		 <td>
+                     <img src="images/OM005.gif" alt="Rememeber this" width="35" height="57"/></td>
 					 <td class="special-td">
 					 For consistency reasons once the cache is switched off it cannot be switched on again. <td>
 			 </tr>
@@ -313,11 +316,13 @@
 <h3>&nbsp;</h3>
 <h2>Section 4 - Known Limitations of OM</h2>
 <h3>Incomplete XML Info set support</h3>
-<p>The OM deliberately dropped the support for XML info set items such as DTDs and  Processing Instructions (PI's). Hence the OM cannot be called a complete info set representation. The initial reason for this was because the design goal of the OM was not to be "yet-another-object-model" but to be a SOAP specific Object model. Since DTD's and PI's are not supposed to be present in SOAP messages.</p>
+<p>OM deliberately dropped the support for XML info set items such as DTDs. Hence 
+OM cannot be called a complete info set representation. The initial reason for 
+this was because the design goal of the OM was not to be 
+&quot;yet-another-object-model&quot; but to be a SOAP specific Object model since DTD's are not supposed to be present in SOAP messages.</p>
 <h3>Inefficient Namespace serialization</h3>
 <p>Although the serializer acts correctly in every situation, the code that it produces may not be efficient all the time. Take the following case where a similar code listing to 1.6 is used but with two elements having the same namespace. Note that the newly added items are in bold.</p>
-<pre class="code">
-OMFactory factory = OMAbstractFactory.getOMFactory();
+<pre class="code">OMFactory factory = OMAbstractFactory.getOMFactory();
 OMNamespace ns1 = factory.createOMNamespace("bar","x");
 OMElement root = factory.createOMElement("root",ns1);
 OMNamespace ns2 = root.declareNamespace("bar1","y");
@@ -335,8 +340,7 @@
 <div align="left"><b>Code listing 4.1</b></div>
 <p>Serialization of the root element provides the following XML</p>
 
-<pre class="xml">
-&lt;x:root xmlns:x="bar" xmlns:y="bar1"&gt;
+<pre class="xml">&lt;x:root xmlns:x="bar" xmlns:y="bar1"&gt;
 &lt;x:foo&gt;
   &lt;y:yuck&gt;blahblah&lt;/y:yuck&gt;
  &lt;y:yuck&gt;blah&lt;/y:yuck&gt;
@@ -345,8 +349,7 @@
 
 </pre>
 <p>However if the serialization is carried on the foo element then the following XML is produced</p>
-<pre class="xml">
-&lt;x:foo xmlns:x="bar" &gt;
+<pre class="xml">&lt;x:foo xmlns:x="bar" &gt;
   &lt;y:yuck " xmlns:y="bar1"&gt;blahblah&lt;/y:yuck&gt;
   &lt;y:yuck " xmlns:y="bar1"&gt;blah&lt;/y:yuck&gt;
  &lt;/x:foo&gt;
@@ -355,10 +358,13 @@
 <p>Note that the same Namespace is serialized twice. This XML is semantically correct but the same semantics could have been achieved by placing the y namespace declaration on the parent element. 
 This behavior is due to the nature of the serialization where it tries to be accurate but not optimal. It is deliberately kept unchanged since such optimizations slow down the common case. 
 </p>
+<h2>Summary</h2>
+<p>This is meant to be a small yet comprehensive introduction to AXIOM. AXIOM 
+however is a lot more than what is described in this tutorial. Readers are 
+welcome to explore AXIOM, specially it's capabilities to handle binary content.</p>
 <h2>Appendix</h2>
 <h3>Program listing for complete OM - build and serialize</h3>
-<pre class="code">
-import org.apache.axis2.om.SOAPEnvelope;
+<pre class="code">import org.apache.axis2.om.SOAPEnvelope;
 import org.apache.axis2.om.OMFactory;
 import org.apache.axis2.om.OMXMLParserWrapper;
 import org.apache.axis2.impl.llom.factory.OMXMLBuilderFactory;
@@ -415,5 +421,4 @@
 <!-- End of footer -->
 </body>
 
-</html>
-
+</html>
\ No newline at end of file