Apache Axiom 1.2.11 Release Note
Axiom 1.2.11 is a maintenance release to support the upcoming Axis2 1.6 release. It also introduces a couple of new APIs that make it easier to support alternative Axiom implementations and that eliminate the need to refer to internal Axiom APIs.
Resolved JIRA issues:
- [AXIOM-12] - OMOutputFormat: doSWA and doOptimize should be mutually exclusive…plus we need doOptimizeThreshold
- [AXIOM-24] - OMDocument#serializeAndConsume doesn't consume the document
- [AXIOM-172] - OMChildrenQNameIterator doesn't work correctly if hasNext() is not called before next()
- [AXIOM-274] - Refactor/deprecate MIMEOutputUtils
- [AXIOM-275] - Implement non JavaMail implementation of MultipartWriter
- [AXIOM-313] - Add a new getDocumentElement method to StAXOMBuilder that allows to discard the OMDocument
- [AXIOM-333] - getFirstChildWithName should not read the next element.
- [AXIOM-346] - Enhance OMStAXWrapper/OMNavigator to work with OMDocument objects
- [AXIOM-351] - Links in Javadoc JARs are broken
- [AXIOM-352] - StAXDialectDetector doesn't recognize com.bea.core.weblogic.stax_1.7.0.0.jar
Changes in this release
Resurrection of the OMXMLBuilderFactory API
Historically, org.apache.axiom.om.impl.llom.factory.OMXMLBuilderFactory
was used to create Axiom
trees from XML documents. Unfortunately, this class is located in the wrong package and JAR (it is
implementation independent but belongs to LLOM). In Axiom 1.2.10, the standard way to create an
Axiom tree was therefore to instantiate StAXOMBuilder
or one of its subclasses directly. However,
this is not optimal for two reasons:
-
It relies on the assumption that every implementation of the Axiom API necessarily uses
StAXOMBuilder
. This means that an implementation doesn't have the freedom to provide its own builder implementation (e.g. in order to implement some special optimizations). -
StAXOMBuilder
and its subclasses belong to packages which haveimpl
in their names. This tends to blur the distinction between the public API and internal implementation classes.
Therefore, in Axiom 1.2.11, a new abstract API for creating builder instances was introduced. It is
again called OMXMLBuilderFactory
, but located in the org.apache.axiom.om
package. The methods
defined by this new API are similar to the ones in the original (now deprecated)
OMXMLBuilderFactory
, so that migration should be easy.
Changes in the behavior of certain iterators
In Axiom 1.2.10 and previous versions, iterators returned by methods such as
OMIterator#getChildren()
internally stayed one step ahead of the node returned by the next()
method. This meant that sometimes, using such an iterator had the side effect of building elements
that were not intended to be built. In Axiom 1.2.11 this behavior was changed such that next()
no
longer builds the nodes it returns. In a few cases, this change may cause issues in existing code.
One known instance is the following construct (which was used internally by Axiom itself):
while (children.hasNext()) {
OMNodeEx omNode = (OMNodeEx) children.next();
omNode.internalSerializeAndConsume(writer);
}
One would expect that the effect of this code is to consume the child nodes. However, in Axiom
1.2.10 this is not the case because next()
actually builds the node. Note that the code actually
doesn't make sense because once a child node has been consumed, it is no longer possible to retrieve
the next sibling. Since in Axiom 1.2.11 the call to next()
no longer builds the child node, this
code will indeed trigger an exception.
Another example is the following piece of code which removes all child elements with a given name:
Iterator iterator = element.getChildrenWithName(qname);
while (iterator.hasNext()) {
OMElement child = (OMElement)iterator.next();
child.detach();
}
In Axiom 1.2.10 this works as expected. Indeed, since the iterator stays one node ahead, the current
node can be safely removed using the detach()
method. In Axiom 1.2.11, this is no longer the case
and the following code (which also works with previous versions) should be used instead:
Iterator iterator = element.getChildrenWithName(qname);
while (iterator.hasNext()) {
iterator.next();
iterator.remove();
}
Note that this is actually compatible with the behavior of the Java 2 collection framework, where a
ConcurrentModificationException
may be thrown if a thread modifies a collection directly while it
is iterating over the collection with an iterator.
In Axiom 1.2.12, the iterator implementations have been further improved to detect this situation
and to throw a ConcurrentModificationException
. This enables early detection of problematic usages
of iterators.