| ~~ Licensed to the Apache Software Foundation (ASF) under one |
| ~~ or more contributor license agreements. See the NOTICE file |
| ~~ distributed with this work for additional information |
| ~~ regarding copyright ownership. The ASF licenses this file |
| ~~ to you under the Apache License, Version 2.0 (the |
| ~~ "License"); you may not use this file except in compliance |
| ~~ with the License. You may obtain a copy of the License at |
| ~~ |
| ~~ http://www.apache.org/licenses/LICENSE-2.0 |
| ~~ |
| ~~ Unless required by applicable law or agreed to in writing, |
| ~~ software distributed under the License is distributed on an |
| ~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| ~~ KIND, either express or implied. See the License for the |
| ~~ specific language governing permissions and limitations |
| ~~ under the License. |
| |
| ------------------- |
| Axiom 1.3 roadmap |
| ------------------- |
| |
| Introduction |
| |
| This page summarizes the planned changes for the next major release, i.e. Axiom 1.3. |
| Note that it is not intended as a wish list for new features, but identifies a set of |
| changes that break backward compatibility and therefore need to |
| be postponed to the 1.3 release. |
| |
| The overall goals for the 1.3 are: |
| |
| * Upgrade the API to use Java 5 features, in particular generics. Make Java 6 the minimum |
| supported version and get rid of the dependencies on Activation and the StAX API (which |
| are included in the JRE in Java 6). |
| |
| * Eliminate deprecated APIs and utility classes. |
| |
| * Eliminate remaining API inconsistencies. |
| |
| * Make the API more compact by clarifying the separation between the public API |
| and implementation classes and moving implementation classes out of <<<axiom-api>>>. |
| |
| API inconsistencies to be eliminated |
| |
| * Usage of <<<Object>>> instead of <<<DataHandler>>> |
| |
| There are several APIs that use <<<Object>>> although they expect or return |
| a <<<DataHandler>>>. This is probably a legacy of Axis 1.x where the Activation API |
| was an optional dependency. Today this no longer makes sense: |
| |
| * The Activation API is included in Java 6. |
| |
| * It is unlikely that Axiom actually works if Activation is not in the class path |
| because there is nothing in the build that enforces or tests that and there are no |
| known downstream projects that use Axiom without also depending on the Activation API. |
| |
| The following APIs will be changed to use <<<DataHandler>>> directly: |
| |
| * <<<OMText#getDataHandler()>>> |
| |
| * <<<OMFactory#createOMText(Object, boolean)>>> |
| |
| * Methods declared by the wrong interface in the node type hierarchy |
| |
| Some methods are declared at the wrong level in the node type hierarchy so that they may |
| be called on nodes for which they are not meaningful: |
| |
| * The <<<serialize>>> and <<<serializeAndConsume>>> methods that take an <<<OutputStream>>> |
| or <<<Writer>>> object are only meaningful for <<<OMContainer>>> objects. However, they |
| are declared by <<<OMNode>>>. Note that already in 1.2.x, these methods are deprecated. |
| |
| * <<<OMContainer>>> declares several methods that return child elements by name: <<<getChildrenWithLocalName>>>, |
| <<<getChildrenWithName>>>, <<<getChildrenWithNamespaceURI>>> and <<<getFirstChildWithName>>>. |
| Since the document element is unique, these methods are not meaningful for <<<OMDocument>>> |
| and they should be declared by <<<OMElement>>> instead. |
| |
| * Exception hierarchy |
| |
| The way exceptions are used in Axiom 1.2.x is not very consistent. In addition it doesn't allow application |
| code to distinguish between different types of error cases. This should be improved in |
| Axiom 1.3 to meet the following requirements: |
| |
| * Although the two implementations of the Axiom API (LLOM and DOOM) use StAX as XML parser and serializer, this |
| is not a strict requirement. The only strict requirements are that the implementation is able to |
| construct a tree from a <<<XMLStreamReader>>> supplied by application code, is able to serialize |
| a tree to an <<<XMLStreamWriter>>> and is able to construct an <<<XMLStreamReader>>> from a tree. |
| Therefore methods defined by the Axiom API should only declare <<<XMLStreamException>>> if they interact |
| directly with a StAX object supplied by application code. |
| |
| A good example is the <<<OMContainer#serialize(OutputStream)>>> method. In Axiom 1.2.x this method |
| is declared to throw <<<XMLStreamException>>>. This assumes that the implementation necessarily uses |
| StAX as XML serializer. This is a wrong assumption, because the implementation is free to use its |
| own serializer. Also note that the method doesn't declare <<<IOException>>> which would be much more relevant. |
| |
| * Axiom should have well-defined (and distinct) exceptions for at least the following two error cases: |
| |
| * An I/O error occurs during a deferred parsing operation. In that case, the unchecked exception should |
| wrap the original <<<IOException>>> so that it can be extracted by application code. |
| |
| * A parser error occurs during a deferred parsing operation. |
| |
| * <<<OMException>>> should only be thrown by APIs in the <<<org.apache.axiom.om>>> and <<<org.apache.axiom.soap>>> |
| packages (and their subpackages). However, in Axiom 1.2.x that exception is used by the MIME/attachments API |
| as well. |
| |
| * Methods for boolean attributes in <<<SOAPHeaderBlock>>> |
| |
| <<<SOAPHeaderBlock>>> has methods to get and set the boolean attributes <<<mustUnderstand>>> |
| and <<<relay>>>. However, the set of getters and setters is not the same for both attributes: |
| there is a <<<setMustUnderstand(String)>>> method, but no corresponding <<<setRelay(String)>>> method. |
| Probably the <<<setMustUnderstand(String)>>> method should just be removed. |
| |
| Removal of unnecessary or irrelevant APIs |
| |
| This section identifies APIs that have become unnecessary or irrelevant. Note that APIs that |
| have already been deprecated in 1.2.x (and will be removed in 1.3 anyway) are not listed here. |
| |
| * <<<org.apache.axiom.om.OMAttachmentAccessor>>> |
| |
| In Axiom versions prior to 1.2.9, the sequence of events produced by the <<<XMLStreamReader>>> |
| returned by <<<getXMLStreamReaderWithoutCaching>>> was inconsistent if the underlying stream is |
| XOP encoded (see AXIOM-255). This made it necessary for application code to (partially) handle the |
| XOP processing itself. That is the reason why the <<<XMLStreamReader>>> instance (which is |
| an <<<OMStAXWrapper>>>) implements <<<OMAttachmentAccessor>>>: it allowed the application code |
| to retrieve the binary content for undecoded <<<xop:Include>>> elements. |
| |
| Starting with Axiom 1.2.9 the sequence of events produced by the |
| <<<XMLStreamReader>>> is always the same (i.e. XOP is always completely decoded) and all binary |
| content is reported through the <<<DataHandlerReader>>> extension, making the <<<OMAttachmentAccessor>>> |
| API unnecessary in that context. |
| |
| The interface is used in several other contexts as well, but it is actually unnecessary in each of them: |
| |
| * The <<<Attachments>>> class implements <<<OMAttachmentAccessor>>>. However, it is not possible to |
| substitute an <<<Attachments>>> object by an arbitrary <<<OMAttachmentAccessor>>> instance (e.g. when |
| parsing an XOP/MTOM message). This would actually be a useful feature, but in that particular context, |
| there is an overlap with the <<<MimePartProvider>>> interface and that API would be better suited. |
| |
| * The <<<OMAttachmentAccessor>>> API is required in conjunction with the <<<setInlineMTOM>>> method |
| defined by <<<OMXMLStreamReader>>>. However, that method is deprecated. |
| |
| * The <<<XOPBuilder>>> interface extends <<<OMAttachmentAccessor>>>. However, as explained below, |
| that API will be removed in Axiom 1.3. |
| |
| * <<<org.apache.axiom.om.impl.builder.BuilderAwareReader>>> |
| |
| This API can't be preserved as is in Axiom 1.3. There are two reasons for this: |
| |
| * The only method defined by the <<<BuilderAwareReader>>> interface has a |
| parameter of type <<<StAXBuilder>>>, but that class will be removed from |
| <<<axiom-api>>> (see below). The parameter type would have to be changed to |
| <<<OMXMLParserWrapper>>>. |
| |
| * It the interface is considered a public API, then it is placed in the |
| wrong package. |
| |
| TODO: analyze the use cases for this API to see if we still need it |
| |
| * <<<org.apache.axiom.om.impl.builder.XOPBuilder>>> |
| |
| The <<<XOPBuilder>>> interface is implemented by <<<XOPAwareStAXOMBuilder>>> and <<<MTOMStAXSOAPModelBuilder>>>. |
| With the changes in r1164997 and r1207662, it is no longer used internally by Axiom. |
| The interface declares methods that give access to the <<<Attachments>>> object that was |
| used to create the builder. That is undesirable for two reasons: |
| |
| * For XOP/MTOM encoded messages, optimized binary data should always be accessed |
| through the <<<OMText>>> API and not by accessing MIME parts directly through |
| the <<<Attachments>>> API. |
| |
| * The existence of the <<<XOPBuilder>>> API (and in particular the <<<getAttachments>>> |
| method defined by that interface) implies that an XOP/MTOM builder is necessarily |
| created from an <<<Attachments>>> object. However, it may be desirable to support other |
| ways to supply the MIME parts to the builder (e.g. using an implementation of the |
| <<<MimePartProvider>>> API). |
| |
| Therefore the <<<XOPBuilder>>> API will be removed in Axiom 1.3. |
| |
| Classes to be moved from <<<axiom-api>>> to <<<om-aspects>>> |
| |
| Up to version 1.2.12, the core Axiom code was organized in three modules, |
| namely <<<axiom-api>>>, <<<axiom-impl>>> and <<<axiom-dom>>>, where <<<axiom-api>>> |
| contains both the public API as well as implementation classes shared by LLOM and DOOM. |
| Unfortunately the distinction between the public API and these shared implementation |
| classes has become somewhat blurred over time. In Axiom 1.2.13 a new module |
| called <<<axiom-common-impl>>> was introduced with the specific goal of separating the |
| shared implementation classes from the public API; with the introduction of AspectJ |
| in Axiom 1.2.15 this module is now called <<<om-aspects>>>. |
| |
| However, in Axiom 1.2.x it is generally not possible to move classes from |
| <<<axiom-api>>> to <<<om-aspects>>> without the risk of breaking existing code. |
| A new major release gives us the opportunity to move the existing shared classes to |
| <<<om-aspects>>> as well, so that in Axiom 1.3, <<<axiom-api>>> will only |
| contain Axiom's public API. This is one of the important goals for Axiom 1.3 |
| because it has multiple benefits: |
| |
| * The more compact the public API is, the easier it is for users to understand the |
| API and to locate the features they are looking for. |
| |
| * By definition, anything that is not part of the public API can be modified |
| without the risk of breaking application code. Clarifying the distinction between |
| the public API and internal implementation classes therefore gives the project |
| more flexibility to implement changes. |
| |
| * Having a well defined abstract API allows to create alternative implementations |
| of that API. |
| |
| This section identifies the classes and internal APIs that will be removed |
| from <<<axiom-api>>>. |
| |
| * Builder implementations |
| |
| In Axiom 1.2.13, the <<<OMXMLBuilderFactory>>> API allows to create any type of |
| object model builder (plain XML, SOAP, XOP and MTOM). The API also defines two |
| interfaces representing a builder: <<<OMXMLParserWrapper>>> and <<<SOAPModelBuilder>>>. |
| This means that application code should no longer reference the builder implementation |
| classes directly, but only <<<OMXMLBuilderFactory>>>, <<<OMXMLParserWrapper>>> and |
| <<<SOAPModelBuilder>>>. In Axiom 1.3 the implementation classes can therefore be moved |
| to <<<om-aspects>>>. They are: |
| |
| * <<<org.apache.axiom.om.impl.builder.StAXBuilder>>> |
| |
| * <<<org.apache.axiom.om.impl.builder.StAXOMBuilder>>> |
| |
| * <<<org.apache.axiom.om.impl.builder.XOPAwareStAXOMBuilder>>> |
| |
| * <<<org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder>>> |
| |
| * <<<org.apache.axiom.soap.impl.builder.MTOMStAXSOAPModelBuilder>>> |
| |
| TODO: there is one API that still references <<<StAXBuilder>>>, namely <<<BuilderAwareReader>>>; |
| it needs to be changed (or removed) |
| |
| Together with these classes, the following interfaces and helper classes should also |
| be moved to <<<om-aspects>>>: |
| |
| * TODO |
| |
| Public APIs that need to be moved to another package |
| |
| Some interfaces are part of the public API although they are placed in an |
| <<<impl>>> package. These interfaces need to be moved to another package to make it |
| clear that they are not internal or implementation specific interfaces: |
| |
| * <<<org.apache.axiom.om.impl.builder.CustomBuilder>>> |
| |
| APIs that need to be overhauled |
| |
| * <<<OMDataSource>>> |
| |
| The <<<OMDataSource>>> API has evolved over time and there have been several additions, not all of which |
| are well designed. Here is a [partial] list of issues with the design of this API: |
| |
| * The <<<OMDataSource#serialize(OutputStream, OMOutputFormat)>>> and <<<OMDataSource#serialize(Writer, OMOutputFormat)>>> |
| are currently only used when a corresponding <<<serialize>>> method is invoked directly on the <<<OMSourcedElement>>> |
| instance. This however is a rare event because a <<<OMSourcedElement>>> is usually serialized as part of a larger tree, |
| in which case <<<OMDataSource#serialize(XMLStreamWriter)>>> will be used. In addition, these methods are rarely invoked |
| directly by application code, and code doing this could be easily rewritten to construct a <<<OMSourcedElement>>> |
| first and to use the <<<serialize>>> methods on that element. |
| |
| The two methods could nevertheless be useful if they were used by <<<OMSourcedElement>>> to optimize the serialization |
| process for <<<OMDataSource>>> instances backed by objects that can be serialized to a byte or character stream in a |
| way that is more efficient than using an <<<XMLStreamWriter>>>. This would require <<<OMSourcedElement>>> to bypass |
| the <<<XMLStreamWriter>>> and let the <<<OMDataSource>>> directly write to the underlying stream. However, the current |
| API is not correctly designed for this purpose: |
| |
| * Since the two methods are defined by <<<OMDataSource>>> (and not by an optional interface), <<<OMSourcedElement>>> |
| has no way of knowing whether the data source implements an optimized serialization mechanism. In fact, most data sources |
| will have a trivial implementation based on <<<XMLStreamWriter>>> and in that case, using these methods would |
| actually be less efficient than using <<<OMDataSource#serialize(XMLStreamWriter)>>>. |
| |
| * To ensure that the optimization always produces well formed XML, the contract of the two methods would have to clearly |
| specify that the implementation must not write an XML declaration and also must not write a byte order marker |
| (a byte order marker may only appear at the beginning of the document). In fact, the <<<OMOutputFormat>>> argument |
| is not appropriate because only the charset encoding parameter would be relevant (for the method that writes |
| to an <<<OutputStream>>>). |
| |
| * To correctly serialize the content of the <<<OMDataSource>>> as a fragment of a larger document, the implementation |
| would need information about the current namespace context. However, that information is not passed to these methods. |
| Without that information, the implementation will likely generate redundant namespace declarations. It may also |
| generate incorrect XML if there is a default namespace. |
| |
| * The two methods are not XOP aware. |
| |
| * <<<MTOMXMLStreamReader>>> |
| |
| This should become an interface: |
| |
| * This would enable the implementation of proxies and maybe allow us to get rid of |
| <<<XMLStreamWriterFilter>>>. |
| |
| * This would allow us to move the implementation code out of <<<axiom-api>>>. |
| |
| * Attachment lifecycle manager |
| |
| The <<<LifecycleManager>>> API has a couple of issues that can't be fixed without breaking |
| backward compatibility: |
| |
| * There is some overlap with the <<<AttachmentCacheMonitor>>> class. There should be a single API to |
| manage the lifecycle of buffered attachments. |
| |
| * <<<LifecycleManager>>> is an abstract API (interface), but refers to <<<FileAccessor>>> which |
| is placed in an <<<impl>>> package. |
| |
| * <<<SOAPVersion>>> |
| |
| The <<<SOAPVersion>>> API uses a somewhat peculiar design pattern: it has two public implementation classes |
| (<<<SOAP11Version>>> and <<<SOAP12Version>>>) which do not add any methods and that have static <<<getSingleton>>> |
| methods to get the singleton instance for each of these classes. This should be changed to use a more traditional |
| pattern, namely the two singleton instances should be accessible using constants defined by <<<SOAPVersion>>>. |
| The implementing classes then no longer need to be public (they can be anonymous or have package access). |
| |
| In addition, <<<SOAPVersion>>> should be changed from an interface to an abstract class so that one can |
| define static methods to get the SOAP version by envelope namespace or media type. |
| |
| * <<<StAXParserConfiguration>>> |
| |
| The <<<StAXParserConfiguration>>> API relies on the assumption that the XML parser used by Axiom is |
| an implementation of StAX. However, as noted above, this is not a strict requirement; an Axiom |
| implementation could equally well use another API or provide its own XML parser. |
| Therefore <<<StAXParserConfiguration>>> should be replaced by something more generic. |
| |
| * <<<OMMetaFactory>>> |
| |
| The argument order is not consistent across methods. See e.g. the two <<<createOMBuilder>>> methods that |
| take an <<<InputSource>>> argument. |
| |
| * <<<OMElement>>> |
| |
| The argument order of the <<<addAttribute(String, String, OMNamespace)>>> method is inconsistent with that |
| of the <<<createOMAttribute>>> method in <<<OMFactory>>>. |
| |
| * <<<OMOutputFormat>>> |
| |
| This class should be made immutable (which would require introducing a builder class) so that instances |
| are safe to reuse. |
| |
| Miscellaneous |
| |
| * Make non coalescing mode the default |
| |
| By default, Axiom configures the underlying parser in coalescing mode. The reason is purely historical. |
| Axiom originally used Woodstox 3.x and that version implemented one aspect of the StAX |
| specification incorrectly, namely {{{http://jira.codehaus.org/browse/WSTX-140}it configured the parser by default |
| in coalescing mode}}, while the specification says otherwise. The problem is that (poorly |
| written) code that uses Axiom with a parser in coalescing mode doesn't |
| necessarily work with non coalescing mode. Therefore the choice was |
| made to make coalescing mode the default in order to ensure |
| compatibility when using a StAX implementation other than Woodstox 3.x. |
| |
| A new major release would be the right moment to change this and make non coalescing mode the default. |
| This enables a couple of optimizations (e.g. when reading and decoding base64 from a text node) and |
| ensures that an XML document can be streamed with constant memory, even if it contains large text nodes. |
| |
| * Don't allow <<<addChild>>> to reorder children |
| |
| The <<<SOAPEnvelope>>> implementations in LLOM and DOOM override the <<<addChild>>> method to |
| reorder the nodes if an attempt is made to add a <<<SOAPHeader>>> after the <<<SOAPBody>>>. |
| This introduces unnecessary complexity in the implementation and is questionable from an OO |
| design perspective because it breaks the general contract of the <<<addChild>>> method which is |
| to add the node as the last child. |
| |
| The <<<addChild>>> implementation for <<<SOAPEnvelope>>> should not do this. Instead it should |
| just throw an exception if a <<<SOAPHeader>>> is added at the wrong position. |